Compare commits

..

1336 Commits

Author SHA1 Message Date
ringabout
ce295d7243 fixes broken CI; bump macOS version to macos-11 (#20098)
* bump macOS image on Azure CI to macos-11
* fix CI error

(cherry picked from commit 8ef509b85b)
2022-07-28 07:47:52 +02:00
narimiran
c6e0983b47 fix typo 2022-07-20 11:20:33 +02:00
narimiran
c5cd23a776 fix important_packages 2022-07-20 11:19:41 +02:00
Tanguy
30ba13d22a Fix nested finally handling in closureiters [backport] (#19933)
* Fix nested finally handling in closureiters

* Fix CI

* review comment

* third time the charm

* Update compiler/closureiters.nim

Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>

Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>
(cherry picked from commit fb5fbf1e08)
2022-07-18 17:27:29 +02:00
narimiran
315f4ecff1 disable testing of 'fragments' package 2022-01-17 11:25:51 +01:00
flywind
49379e85ec mangle names in nimbase.h using cppDefine (#19395) [backport]
mangle names in nimbase.h
fix comments

(cherry picked from commit 4f6b59de96)
2022-01-17 11:18:03 +01:00
flywind
6ab3c1b365 nrvo shouldn't touch bycopy object[backport:1.2] (#19385)
fix nim-lang#19342

(cherry picked from commit 9b9ae8a487)
2022-01-17 07:40:43 +01:00
Ștefan Talpalaru
0dae9115c8 Nim-1.4: style fix (#19317)
this allows "--styleCheck:usages --styleCheck:error"
2022-01-05 01:31:09 +08:00
flywind
32882fa024 disable packages which doesn't support 1.4 (#19320)
ref https://github.com/nim-lang/Nim/pull/19317
2022-01-04 11:11:07 +01:00
Andreas Rumpf
dc1e948f15 Revert "Update uri.nim (#19148) [backport:1.0]" (#19280)
This reverts commit a3ef5df680.

(cherry picked from commit 81d32cf7e5)
2021-12-31 05:14:52 +01:00
Miran
65db3013a8 [backport:1.0] json: limit recursion depth (#19252)
* json: limit recursion depth

* do not run this check for JS backend

(cherry picked from commit c17baaefbc)
2021-12-14 18:21:19 +01:00
flywind
7f0e662032 oids: switch from PRNG to random module (#16203)
* switch from PRNG to random module
* fix the regression
* comments + tests
* runnableExamples
* make oids better

(cherry picked from commit 89a21e4ec7)
2021-12-13 15:03:56 +01:00
Dominik Picheta
547973c3e9 Update uri.nim (#19148) [backport:1.0]
(cherry picked from commit a3ef5df680)
2021-12-11 09:25:34 +01:00
Ștefan Talpalaru
4d5c5893ae nimc.rst: fix table markup (#19239)
(cherry picked from commit 1a92edeb89)
2021-12-11 05:48:23 +01:00
Ștefan Talpalaru
8c356fd971 nimRawSetjmp: support Windows (#19197)
* nimRawSetjmp: support Windows

Using `_setjmp()` directly is required to avoid some rare (but very
annoying) exception-related stack corruption leading to segfaults on
Windows, with Mingw-w64 and SEH.
More details: https://github.com/status-im/nimbus-eth2/issues/3121

Also add "nimBuiltinSetjmp" - mostly for benchmarking.

* fix for Apple's Clang++

(cherry picked from commit 69aabdab80)
2021-12-11 05:48:19 +01:00
Andreas Rumpf
17522d6ae1 fixes a possible 'javascript:' protocol exploit [backport:1.0] (#19134)
* fixes a possible 'javascript:' protocol exploit [backport:1.0]

* add tests

* Update tests/stdlib/trstgen.nim

* add the same logic for hyperlinks

* move the logic into a proc

Co-authored-by: narimiran <narimiran@disroot.org>
(cherry picked from commit 9338aa2497)
2021-12-10 11:56:52 +01:00
Tanguy
f8047c3e3c fix #19193 (#19195) [backport:1.2]
(cherry picked from commit cd592ed85b)
2021-12-10 11:50:13 +01:00
Etan Kissling
cfb6ebc07a allow HSlice bounded by constants of distinct types (#19219) [backport:1.2]
When creating heterogenous slices of distinct types, the compiler does
not initialize the internal type's `size` before accessing it.
This then leads to this crash message:
```
compiler/int128.nim(594, 11) `false` masking only implemented for 1, 2, 4 and 8 bytes [AssertionError]
```
This patch initializes the `size` properly, fixing the problem.

(cherry picked from commit 0213c7313b)
2021-12-10 11:49:39 +01:00
narimiran
8f20400466 we must use Ubuntu 18.04 2021-12-07 20:34:33 +01:00
Andreas Rumpf
6d3b706f6e misc bugfixes [backport:1.2] (#19203)
(cherry picked from commit 23c117a950)
2021-12-06 12:48:37 +01:00
Andreas Rumpf
0df0510722 fixes #14470 [backport:1.2] (#19115)
(cherry picked from commit 15157d06c3)
2021-12-06 12:41:49 +01:00
Andreas Rumpf
68df3c9afd fixes a 'mixin' statement handling regression [backport:1.2] (#18968)
(cherry picked from commit 8eef557157)
2021-12-06 12:41:33 +01:00
Etan Kissling
a8aaf5a27d allow converting static vars to openArray (#19048)
When assigning constant output to a seq, and then passing that static
seq to other functions that take `openArray`, the compiler may end up
producing errors, as it does not know how to convert `static[seq[T]]`
to `openArray[T]`. By ignoring the `static` wrapper on the type for
the purpose of determining data memory location and length, this gets
resolved cleanly. Unfortunately, it is relatively tricky to come up
with a minimal example, as there are followup problems from the failing
conversion, e.g., this may lead to `internal error: inconsistent
environment type`, instead of the relevant `openArrayLoc` error message.

(cherry picked from commit 490c4226a5)
2021-10-27 11:04:04 +02:00
flywind
80c8107c56 [tools] use the right parameter [backport:1.0] (#18957)
(cherry picked from commit b2873f0f63)
2021-10-06 13:41:18 +02:00
Andreas Rumpf
5bed375b52 fixes #16325 [backport:1.4] (#18784)
(cherry picked from commit a7cae2bda2)
2021-09-02 20:25:46 +02:00
Dankr4d
1228c5b3fc fixes #14511 [backport:1.4] (#18732)
* fixes #14511 [backport:1.4]

Signed-off-by: Dankr4d <dude569@freenet.de>

* Replaced fix with code from alaviss, for better readability, with small
changes.

Signed-off-by: Dankr4d <dude569@freenet.de>

* - Specified output in test.

Signed-off-by: Dankr4d <dude569@freenet.de>

* Replaced case in nnkRecCase with a simpler version, which just adds the
last son.

Signed-off-by: Dankr4d <dude569@freenet.de>

* Update tests/macros/t14511.nim

* Update tests/macros/t14511.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit c70e4040bd)
2021-09-02 20:25:39 +02:00
narimiran
0a8e9318d3 fix broken test 2021-08-24 07:28:19 +02:00
narimiran
22650a61e7 bump NimVersion to 1.4.9 2021-08-24 07:21:56 +02:00
flywind
8b80039cac fix #18702(fix parseutils.parseFloat) (#18703) [backport:1.0]
* fix #18702
* Apply suggestions from code review

(cherry picked from commit 901c5ded52)
2021-08-24 07:10:48 +02:00
Andreas Rumpf
b18c6fd09b fixes #18643 [backport:1.0] (#18678)
(cherry picked from commit 018465a234)
2021-08-24 07:10:26 +02:00
Andreas Rumpf
88340aab6d fixes #18411 (#18432) [backport:1.4]
(cherry picked from commit 1bed777314)
2021-08-24 07:09:10 +02:00
flywind
8a3e64f00e fixes #17768 [backport:1.4] (#18317)
* fixes #17768 [backport:1.4]

* tiny

(cherry picked from commit 2deb7011f5)
2021-08-24 07:09:00 +02:00
Timothee Cour
6c5585fc0b link stable and devel docs in nim docs (#18272) [backport:1.2]
(cherry picked from commit d3b27eb63e)
2021-08-24 07:08:47 +02:00
Yuriy Glukhov
ca1b7feb0f Fixes #17849 (#18055) [backport:1.2]
* Fixes #17849
* Update compiler/closureiters.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit a6bd6c7ed8)
2021-08-24 07:08:34 +02:00
narimiran
44e653a931 bump NimVersion to 1.4.8 2021-05-24 16:47:31 +02:00
narimiran
0250c4710d fix ccgexprs 2021-05-20 21:07:43 +02:00
Andreas Rumpf
8001c7be98 config system: special case -d:release and -d:danger [backport:1.4] (#18051)
(cherry picked from commit df429fa287)
2021-05-20 13:21:56 +02:00
Ștefan Talpalaru
94f80f5bcb asyncdispatch+stackTraceOverride: fix premature collection (#18039) [backport:1.2]
Copying StackTraceEntry instances when nimStackTraceOverride is defined
breaks the link between a cstring field that's supposed to point at
another string field in the same object.

Sometimes, the original object is garbage collected, that memory region
reused for storing other strings, so when the StackTraceEntry copy tries
to use its cstring pointer to construct a traceback message, it accesses
unrelated strings.

This only happens for async tracebacks and this patch prevents that by
making sure we only use the string fields when nimStackTraceOverride is
defined.

Async tracebacks also beautified slightly by getting rid of an extra line
that was supposed to be commented out, along with the corresponding debugging output.

There's also a micro-optimisation to avoid concatenating two strings just
to get their combined length.

(cherry picked from commit a1c82c39af)
2021-05-19 19:53:08 +02:00
Andreas Rumpf
1281d8dfb8 ARC: fixes memory leaks with newSeq used in a loop [backport:1.4] (#18040)
* ARC: fixes memory leaks with newSeq used in a loop [backport:1.4]
* Update tests/arc/tnewseq_legacy.nim

(cherry picked from commit 53935b8b27)
2021-05-19 18:20:21 +02:00
Thomas T. Jarløv
7a8817e87f Escape %00 / \0 in dbQuote (#18015) [backport:1.4]
Fix https://github.com/nim-lang/Nim/issues/17925

(cherry picked from commit 99788ee504)
2021-05-19 18:20:13 +02:00
Timothee Cour
a63d434180 refs #18011 disable some newly failing tests on cpp windows; refs #17946 increase timeout for tchannels (#18012)
(cherry picked from commit 2ce592a209)
2021-05-17 16:03:42 +02:00
Andreas Rumpf
9fc0955587 ORC: progress (#18000)
* ORC: progress

* ORC: bugfix; don't follow acyclic data even if only at runtime the subtype is marked as acyclic

* progress

* minor style changes

(cherry picked from commit 3bc625aff1)
2021-05-14 13:31:00 +02:00
Andreas Rumpf
cb22a99584 ORC: improvements (#17993)
* ORC: improvements
* ORC: fix .acyclic annotation for ref objects

(cherry picked from commit 39ad9a69a9)
2021-05-14 13:23:36 +02:00
Andreas Rumpf
ad5c784d22 ORC: critical bugfix for mixing acyclic refs with cyclic refs [backport:1.4] (#17991)
(cherry picked from commit 2c2ec48bc4)
2021-05-14 13:18:09 +02:00
Andreas Rumpf
a6d84179fc feature: the compiler can warn when you use the implicit 'result' variable (#17988) [backport:1.2]
* implements #17855

(cherry picked from commit 378ee7f888)
2021-05-14 13:14:52 +02:00
Andreas Rumpf
e4d5139de0 fixes #15848 [backport:1.2] (#17959)
(cherry picked from commit 51f3ef6cb8)
2021-05-14 13:12:45 +02:00
narimiran
9d23c14dd2 some other files need the same change too 2021-04-30 11:00:19 +02:00
narimiran
daad1cd9d9 do the same for build_all.bat too 2021-04-30 10:57:17 +02:00
narimiran
61ac87a2b8 use csources_v1 in build_all.sh 2021-04-30 10:55:06 +02:00
Dankr4d
f825c8f691 Fix #17755 (#17766)
Signed-off-by: Dankr4d <dude569@freenet.de>
(cherry picked from commit 6916faf83c)
2021-04-28 13:51:29 +02:00
Yuriy Glukhov
4b4ef2b4b3 Check for errors after sendPendingSslData (#16696)
* Check for errors after sendPendingSslData

* Leftover comment removed

(cherry picked from commit 165d39738d)
2021-04-28 13:50:51 +02:00
Yuriy Glukhov
431eb05708 Fixes #16436 (#16695)
* Fixes #16436

* Comments addressed

(cherry picked from commit 4ae520711d)
2021-04-28 13:50:30 +02:00
Andreas Rumpf
3e154e7740 CIs: attempt to use csources_v1 (#16282)
* CIs: attempt to use csources_v1
* also updated the BSDs
* also updated azure pipelines
* std modules should not itself use the 'std/' import dir...
* compiler has to be careful with std/ for v1 booting

(cherry picked from commit a9b62de895)
2021-04-28 08:35:00 +02:00
shirleyquirk
e70044fb28 Fix buffer-overrun bug in net (#17728) [backport:1.0]
(cherry picked from commit fdd4391534)
2021-04-21 15:09:35 +02:00
Joey
5618a34d61 Fix Httpclient headers from being modified accidentally (#17808)
(cherry picked from commit f1ce173283)
2021-04-21 15:08:48 +02:00
Miran
f48daa29f6 fix #16506 by changing the example (#16580)
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit d2f4f25b56)
2021-04-21 15:08:01 +02:00
narimiran
2640dc2637 bump NimVersion to 1.4.7 2021-04-21 15:07:19 +02:00
zah
2b6b080323 Remove the use of usrToCell in gcMark [backport:1.2] (#17709)
* Remove the use of usrToCell in gcMark [backport:1.2]

Recently, we've discovered a GC crash resulting from inlining of
the memory allocation procs that allowed the compiler to avoid
maintaining any references to the "user pointer" on the stack.
Instead, a "cell pointer" appeared there and all field accesses
were performed with adjusted offsets. This interfered with the
ability of the GC to mark the correct cell in the conservative
stack scans which lead to premature collection of objects.

More details here:
af69b3ceae

This commit closes another theoretical loophole that may lead to
the same problem. If a short proc is accessing both the object and
its reference count in a short sequence of instructions, the compiler
may be enticed to reduce the number of registers being used by storing
only a single pointer to the object and using offsets when reading
and writing fields. A perfectly good strategy would be to store only
the cell pointer, so the reference count updates can be performed
without applying offsets. Accessing the fields of the object requires
offsets anyway, but these can be adjusted at compile-time without any
loss. Following this strategy will lead to the same problem of marking
a wrong cell during the conservative stack scan, leading to premature
collection.

The problem is avoided by not using `usrToCell` in `gcMark`. Since
the cell discovery logic can already handle interior pointers, the
user pointers don't need to be adjusted for the GC to function correctly.

(cherry picked from commit 3b47a689cf)
2021-04-14 12:10:29 +02:00
narimiran
ab1ae92587 bump NimVersion to 1.4.6 2021-04-13 21:51:50 +02:00
narimiran
5dd88ca1a4 [ci skip] minor: fix indentation in manual.rst
(cherry picked from commit d3529d0d5a)
2021-03-31 13:42:11 +02:00
Miran
598d9f8402 [backport:1.2] Avoid inlining of newObj and newObjRC1 calls (#17582)
This is taken from:
af69b3ceae

Full original comment:

This is to avoid heavy inlining happening when two allocation calls
would occur shortly after each other.

This inlining would sometimes be accompanied with an optimisation
as the compiler is able to see that cellToUsr ending the first
allocation call is shortly followed by an usrToCell call. The
pointer arithmetic is redundant and the compiler can eliminate it,
leaving only the cell address in a register (and later the stack)
instead of the actual pointer to the user data, as one would expect.

This combined with a GC collect cycle will cause the stack scan to
only notice the cell address, which is of no good due to a usrToCell
in the gcMark call which shifts that address to an adjacent cell.
This means that the actual cell of importance will not get marked
and thus cause a premature collection of that cell. BOOM.

(cherry picked from commit 40093b4a93)
2021-03-30 11:47:28 +02:00
Danil Yarantsev
f7f7a02915 Free the certificate after checking in checkCertName (#17558) [backport:1.2]
* Fix small leak in checkCertName
* Size is not needed either
* Free the certificate after checking

(cherry picked from commit b36182b0a4)
2021-03-29 15:31:30 +02:00
Timothee Cour
28b301cbaa fix #17454 (#17461)
(cherry picked from commit d78ebe4a0e)
2021-03-29 15:27:09 +02:00
narimiran
69c2c05463 bump NimVersion to 1.4.5 2021-03-26 09:02:30 +01:00
Andreas Rumpf
cc6bc8960d closes #17085; boehm has problems with large allocations, that is expected and we don't care (#17487)
(cherry picked from commit 8ccde68f13)
2021-03-24 18:20:19 +01:00
narimiran
05991805fb change back part of the test 2021-03-24 18:19:42 +01:00
narimiran
82561f31eb backport json-related part of #17469 2021-03-24 17:48:39 +01:00
Timothee Cour
e5027dc3da fix #17383: json.%,to and jsonutils.formJson,toJson now works with uint|uint64 (#17389) [backport:1.2]
* fix #17383: json.%,to and jsonutils.formJson,toJson now works with uint|uint64
* fixup
* fix for js

(cherry picked from commit 895a40d1ac)
2021-03-19 15:49:56 +01:00
Igor Ribeiro de Assis
f97d840f96 Fix FutureStream memory usage (#17395) [backport:1.2]
(cherry picked from commit 9bb0e55749)
2021-03-18 17:23:06 +01:00
xioren
560800246e Relocate 4xx/5xx exception in downloadFile (#17332) [backport:1.2]
Move 4xx/5xx exception to before disk i/o. As it stands an empty file is created on http error 4xx/5xx.

(cherry picked from commit 3d198fdcc2)
2021-03-18 14:08:54 +01:00
Andreas Rumpf
cf1ecee794 fixes #11225; generic sandwich problems; [backport:1.2] (#17255)
* fixes #11225; generic sandwich problems; [backport:1.2]
* progress
* delegating these symbols must be done via 'bind'

(cherry picked from commit 2f213db7ee)
2021-03-18 14:08:54 +01:00
flywind
6b00463074 Add unsafeIsolate and extract to std/isolation [backport:1.4] (#17263)
(cherry picked from commit 19be5eb1eb)
2021-03-18 14:08:54 +01:00
flywind
e996d98a8a fix #16384 and #17144 (#17126) [backport]
(cherry picked from commit 6391f6e861)
2021-03-18 14:08:54 +01:00
flywind
5c88067953 fix #17264 [backport:1.4] (#17266)
* fix #17264
* fix vm
* fix js and add tests

(cherry picked from commit 171b03c386)
2021-03-18 13:13:51 +01:00
alaviss
061d106671 compiler/installer.ini: package cacert.pem on Windows [backport:1.2] (#17172)
Follow up of 5dc544e1f5

After updating windeps.zip, it appears that Windows' build was
unchanged. As it turns out, cacert.pem is not set for packaging by the
compiler package manifest.

This commit add cacert.pem to the Windows package.

(cherry picked from commit d35f366d6f)
2021-03-18 08:33:16 +01:00
Andreas Rumpf
c2e2f50d35 fixes yet another SSL problem on Windows [backport:1.2] (#17167)
(cherry picked from commit b48a32053f)
2021-03-18 08:32:40 +01:00
narimiran
2ff517462b remove tests for stuff not available in 1.4 2021-02-22 13:51:56 +01:00
narimiran
29a064e275 bump NimVersion to 1.4.4 2021-02-22 10:26:35 +01:00
flywind
bfc0d64825 fix #17118 (#17119) [backport:1.2]
* fix js unsigned integer
* Use `std` prefix for standard library modules
* fix #17118

(cherry picked from commit 32bf10126c)
2021-02-22 10:26:14 +01:00
Miran
540d16540b [backport:1.2] update nimble commit hash (#17109)
(cherry picked from commit da52e81327)
2021-02-19 20:34:36 +01:00
Andreas Rumpf
7705948d52 fixes #17085 [backport:1.2] (#17101)
(cherry picked from commit 4395a26764)
2021-02-19 20:33:41 +01:00
Timothee Cour
a154acda85 followup #17001: improve coverage for tests/openarray/topenarray.nim (#17006)
* followup #17001: improve coverage for tests/openarray/topenarray.nim

(cherry picked from commit 21e60b9a97)
2021-02-18 19:13:10 +01:00
flywind
8f9ea358b6 [JS] Ref #15952 make toOpenArray works better (#17001)
* ref 15952 toOpenArray works in JS

* fix

(cherry picked from commit 9bd4f503f4)
2021-02-18 19:13:01 +01:00
narimiran
8d7e1c4649 remove tests for not backported stuff 2021-02-17 22:04:03 +01:00
Andreas Rumpf
87dc838370 fixes #17033 [backport:1.4] (#17061)
* fixes #17033 [backport:1.4]

* make test robust against stdlib gensym things

* cleanup assertions.nim to make topt_no_cursor easier to get right

(cherry picked from commit f32ffb6ed8)
2021-02-17 18:38:53 +01:00
Andreas Rumpf
c04214f8cb don't introduce 'dispose', use '=dispose', fixes #17003 [backport:1.4] (#17062)
(cherry picked from commit e463a67c74)
2021-02-17 18:36:39 +01:00
Benoit Favre
132a694c6e Fix bug in removeDotSegments when path ends with dot (#17038) [backport:1.2]
(cherry picked from commit 8f54d3b792)
2021-02-17 18:36:27 +01:00
hlaaftana
c55506006f [backport:1.4] JS cstring null fixes (#16979)
* [backport:1.4] JS cstring null fixes
* fix JS move string
* make it look cleaner

(cherry picked from commit 81533a0014)
2021-02-17 18:36:05 +01:00
Miran
a263e9aae0 [backport:1.2] update the nimble commit hash to the latest one (#16971)
(cherry picked from commit 0d34345f29)
2021-02-09 19:08:22 +01:00
narimiran
94560a9faa remove 'tsugar' 2021-02-09 17:32:38 +01:00
hlaaftana
5f46474555 fix #16967 [backport:1.2] (#16976)
* fix #16967 [backport:1.2]

* move test to tsugar

(cherry picked from commit 49ee2f7f3b)
2021-02-09 15:39:39 +01:00
konsumlamm
21e1fa6217 Improve documentation for std/sha1 (#16970)
(cherry picked from commit cee58ccf7f)
2021-02-09 15:37:27 +01:00
hlaaftana
bf06fb7053 Remove declPragmas from lambdas [backport:1.0] (#16966)
* Remove declPragmas from lambdas [backport:1.0]

* add test for exportc

* fix test

* fix align, nodecl -> noinit

(cherry picked from commit 49b64e8dc7)
2021-02-09 15:37:12 +01:00
Andreas Rumpf
ccbdb95539 final SSL changes [backport:1.2] (#16983)
(cherry picked from commit 74d6a4d7f4)
2021-02-09 15:33:57 +01:00
Héctor M. Monacci
de98648caa Correct typo (#16972)
From `fliter proc` to `filter proc`

(cherry picked from commit a9f44b7257)
2021-02-08 22:00:15 +01:00
narimiran
3f1f26a7e2 disable 'fidget' package 2021-02-08 18:51:29 +01:00
narimiran
8f38f3e34d disable package 'bump' 2021-02-08 17:10:05 +01:00
Andreas Rumpf
c7d090c418 basic cleanups regarding SSL handling (#16940) [backport:1.0]
* basic cleanups regarding SSL handling
* enabled certificate checking on Windows
* updated the SSL test
* quoting helps

(cherry picked from commit abac35e743)
2021-02-08 17:08:10 +01:00
narimiran
9b31b12ca5 disable 'criterion' package 2021-02-02 14:34:25 +01:00
hlaaftana
3c74ec0a0f add finally as post expr block [backport:1.4] (#16896)
(cherry picked from commit def1f99289)
2021-02-02 10:10:18 +01:00
Andreas Rumpf
4da6577c97 fixes #16897 [backport:1.2] (#16900)
(cherry picked from commit 91ace2188a)
2021-02-02 10:10:10 +01:00
narimiran
93ee832d3c [ci skip] CountTable, remove link to unexisting proc
(cherry picked from commit 1d1c831efa)
2021-02-02 09:53:55 +01:00
narimiran
5e49d3b68a Revert "make --gc:arc --exceptions:quirky work again [backport:1.4] (#16583)"
This reverts commit 822c7acd3c.
2021-02-02 09:45:54 +01:00
Timothee Cour
5e5803f28f typetraits: make genericHead docs reflect reality; use runnableExamples (#16776) [backport:1.4]
(cherry picked from commit 8f1f0bd1da)
2021-02-01 15:19:07 +01:00
flywind
d9e14414a4 fix #16706 (#16717) [backport:1.4]
(cherry picked from commit ef9027c290)
2021-02-01 15:18:48 +01:00
Timothee Cour
c346c0b91b [backport 1.0] add backend support for js bigint (#16606)
* add backend support for js bigint

* cleanup

* add tests

* add -d:nimHasJsBigIntBackend

* cleanup

* more tests

(cherry picked from commit 025ca660f7)
2021-02-01 15:18:27 +01:00
Andreas Rumpf
822c7acd3c make --gc:arc --exceptions:quirky work again [backport:1.4] (#16583)
* make --gc:arc --exceptions:quirky work again [backport:1.4]

* fixes #16404 [backport:1.4]

(cherry picked from commit 6317e4004d)
2021-02-01 15:16:50 +01:00
cooldome
71bbbdbf96 fix #15043 (#16441) [backport:1.4]
* fix #15043

* Trigger build

(cherry picked from commit fbc8a40c7a)
2021-02-01 15:11:37 +01:00
Timothee Cour
1d8b7aa07c [backport => 1.0] fix #16428 vmops now works for generic procs (#16429)
* fix #16428 vmops now works for generic procs

* remove duplication

(cherry picked from commit bc84d9c8cb)
2020-12-27 14:45:54 +01:00
Andreas Rumpf
db5ce7ed48 asynchttpserver cleanups [backport:1.0] (#15966)
* asynchttpserver cleanups [backport:1.0]

(cherry picked from commit 122f22d163)
2020-12-27 14:19:08 +01:00
Code Hz
939702a001 removing out T from docs since it no longer working (#16378) [backport]
* remove `out T` from docs

see https://github.com/nim-lang/Nim/issues/16131

* remove `out T` in title
* remove entire paragraph

(cherry picked from commit 90dbb6f3fb)
2020-12-19 14:11:12 +01:00
Tomohiro
753aed9d63 Fix osproc so that it doesn't close pipe/process/thread handles twice (#16385) [backport]
* Add error check to closeHandle and fix closing handle twice in osproc

* Fix compile error on Linux

(cherry picked from commit dcdbae798c)
2020-12-19 14:11:04 +01:00
Andreas Rumpf
c9d7c67acb fixes #16365 [backport] (#16381)
(cherry picked from commit 868c31e88a)
2020-12-19 14:10:54 +01:00
flywind
265499ee57 fix #16364 (#16379) [backport]
* fix #16364

* add comments

* Update tools/dochack/dochack.nim

Co-authored-by: Clyybber <darkmine956@gmail.com>

Co-authored-by: Clyybber <darkmine956@gmail.com>
(cherry picked from commit 5d8f862bc6)
2020-12-19 14:10:40 +01:00
Andreas Rumpf
2f13f5bb56 fixes #16359 [backport] (#16377)
(cherry picked from commit b87bcb6d92)
2020-12-19 14:10:22 +01:00
lqdev
9a86afc8fd disabled sink openArray[T] for adding to seqs (#16352) [backport:1.4]
(cherry picked from commit 233c6a2fba)
2020-12-19 14:10:15 +01:00
rockcavera
553c2e5cff Fix #14259 #15621 (#16322) [backport:1.4]
* IPv6 text representation according to RFC 5952

* Revert IPv6 text representation according to RFC 5952

* fix #14259 #15621

fix #14259 #15621

* Update lib/system/io.nim

* reverted IoHandle removal

* adaptation of types for WinAPI

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit d15f63a0f2)
2020-12-19 14:10:06 +01:00
Andreas Rumpf
bf0ad3acab OSX: support for M1 [backport:1.0] (#16279)
(cherry picked from commit 94bb816de3)
2020-12-11 05:42:02 +01:00
Andreas Rumpf
4c918515fd fixes #16249 [backport:1.4] (#16251)
(cherry picked from commit 8178388a78)
2020-12-11 05:39:54 +01:00
Andreas Rumpf
6e45429ab1 fixes #16214 [backport] (#16252)
(cherry picked from commit edce5897a5)
2020-12-11 05:39:46 +01:00
narimiran
8a528979e8 bump NimVersion to 1.4.3 2020-12-11 05:39:02 +01:00
narimiran
3fb5157ab1 bump NimVersion to 1.4.2 2020-11-30 07:07:40 +01:00
Andreas Rumpf
74c687e395 fixes #16154; underlying system.add for seq is the real cause; will be addressed in a follow-up PR (#16161)
(cherry picked from commit c9a10bb9e4)
2020-11-27 17:51:35 +01:00
flywind
204369845a add testcase (#16156)
(cherry picked from commit 3510216c8a)
2020-11-27 17:51:27 +01:00
Andreas Rumpf
150fc44bb3 fixes #16119 [backport:1.4] (#16149)
(cherry picked from commit 9f1c5f64c5)
2020-11-27 17:50:29 +01:00
Timothee Cour
1a92a4b0bd remove all mentions of doc2, jsondoc2 (except 1 mentioning the alias) (#15683)
(cherry picked from commit 13b1b19a83)
2020-11-27 17:47:27 +01:00
Andreas Rumpf
498ac30f9a updated repr tests (#16147)
(cherry picked from commit 4fdaded227)
2020-11-27 17:47:17 +01:00
Andreas Rumpf
2d63592619 fixes https://github.com/status-im/nimbus-eth2/issues/1549 (#16146)
* fixes https://github.com/status-im/nimbus-eth2/issues/1549 [backport:1.4]

* test fixup

(cherry picked from commit cf516713d0)
2020-11-27 17:46:30 +01:00
cooldome
160436c8b3 fix #16120 (#16145)
(cherry picked from commit 8c12d3e29d)
2020-11-26 17:14:43 +01:00
flywind
c576c1cb76 ref #16054 undefine some stuff in JS backend (#16070)
(cherry picked from commit e7e9007c4c)
2020-11-26 14:17:47 +01:00
flywind
32e0542ca0 improve docs for prelude (#16135)
* improve docs for prelude

* better

(cherry picked from commit 0b3a45692c)
2020-11-26 14:17:38 +01:00
Andreas Rumpf
72f4a0d3e9 fixes #15076 (#16143)
* fixes #15076

* heapqueue: optimized for ARC

* added another test case [backport:1.4]

* code cleanup

(cherry picked from commit da753c6a2e)
2020-11-26 14:17:30 +01:00
flywind
cf30401f02 move tests under the compiler directory to testament (#16096)
(cherry picked from commit 57bd64582c)
2020-11-25 12:46:02 +01:00
flywind
4f89307180 improve the documentation of ropes (#16111)
(cherry picked from commit b7809cc992)
2020-11-25 12:44:41 +01:00
flywind
6494b95f3c ref #16054 remove typed array (#16077)
(cherry picked from commit 3fed85437b)
2020-11-25 12:43:59 +01:00
flywind
ef0776380c add simple runnableExamples for atomics (#16116)
(cherry picked from commit d2c6ac4750)
2020-11-25 12:43:25 +01:00
flywind
cfb38c2383 move tests to testament (#16101)
* move tests to testament

* minor

* fix random

* disable test random

(cherry picked from commit cbc793b30b)
2020-11-25 12:42:51 +01:00
Andreas Rumpf
99032ca07b fixes #16069; [backport:1.2] [backport:1.4] (#16115)
* fixes #16069; refs https://github.com/nim-lang/RFCs/issues/257 [backport:1.2] [backport:1.4]

* make tests green again

(cherry picked from commit d306a04466)
2020-11-24 16:18:18 +01:00
cooldome
e2f1fab458 fix #16110 (#16117)
(cherry picked from commit 1d14b2c9e6)
2020-11-24 16:12:27 +01:00
flywind
03f07f8b5e improve document for heapqueue (#16107)
(cherry picked from commit afb8b69c0a)
2020-11-24 16:10:18 +01:00
Miran
3597824c00 fix export links in the documentation (#16114) [backport:1.4]
* fix export links in the documentation

* fix `len` problem

(cherry picked from commit 9a86198ed5)
2020-11-24 16:10:02 +01:00
flywind
c55c49052f fix #16103 (#16109) [backport:1.0]
* fix #16103

* docs

(cherry picked from commit 823a71380d)
2020-11-24 16:08:37 +01:00
flywind
47ebaa4200 typeinfo minor improvement (#16083)
* typeinfo minor improvement

* minor

* Update lib/core/typeinfo.nim

* rename typeinfo

(cherry picked from commit e4d0f9f3de)
2020-11-24 16:08:24 +01:00
kemifl
4b27458cfc fix #14056 (#16071)
fix #14056, incorporate review comments

(cherry picked from commit a764a5b9bc)
2020-11-24 16:08:08 +01:00
flywind
1eda325177 fix ropes format errors (#16106) [backport:1.0]
* fix rope index

* add testcase

* fix ropes format

(cherry picked from commit 0c6c4be0e7)
2020-11-24 16:06:57 +01:00
flywind
62d497237a ref #5617 add lineinfo to complete (#16102)
(cherry picked from commit 7fc0c3dfbf)
2020-11-24 16:06:47 +01:00
RokkuCode
29f9cc0e3d fixes #16080 (#16091) [backport:1.2]
* fixes #16080

db_sqlite: Error: undeclared field: 'untypedLen'

* redacting fix

(cherry picked from commit ffccdf3c1a)
2020-11-23 15:24:47 +01:00
flywind
976b5bf7c5 correct errors in xmltree docs (#16104)
(cherry picked from commit 79ec1bdcbb)
2020-11-23 15:24:43 +01:00
flywind
74fa24ce45 fix rope index (#16100)
* fix rope index

* add testcase

(cherry picked from commit ab2c082cb3)
2020-11-23 15:23:53 +01:00
flywind
fbb58343d9 ast minor (#16079)
(cherry picked from commit 6a37c0682a)
2020-11-23 15:23:21 +01:00
flywind
e6ea779b06 fix #9695 asyncmacro: tfuturevar fails when activated [backport: 1.0] (#16090)
* fix asyncmacro

* Apply suggestions from code review

* Update lib/pure/asyncmacro.nim

(cherry picked from commit 6f1a72069a)
2020-11-23 15:22:35 +01:00
flywind
cb138fc304 sets minor improvement (#16087)
(cherry picked from commit f1764aaa9e)
2020-11-23 15:22:22 +01:00
flywind
c6f7337c77 deques minor improvement (#16084)
(cherry picked from commit c9371ef59d)
2020-11-23 15:22:14 +01:00
flywind
6c070452e4 xmltree minor improvement (#16085)
(cherry picked from commit 3040f05505)
2020-11-23 15:22:00 +01:00
flywind
475b7e1444 complex minor improvement (#16086)
(cherry picked from commit dd57d46f2f)
2020-11-23 15:21:53 +01:00
flywind
64692b185f heapqueue minor improvement (#16088)
(cherry picked from commit f3887dea2c)
2020-11-23 15:21:46 +01:00
Andreas Rumpf
da3948ae32 fixes #15671 [backport:1.4] (#15690)
* fixes #15671 [backport:1.4]

* progress

(cherry picked from commit d9038ed792)
2020-11-20 18:15:16 +01:00
cooldome
f052e251be fix #15958 (#15970) [backport:1.4]
* fix #15958

* also cover openArray and VarArgs

* more tests

* cover even more types

* cover even more types

* Trigger build

* Trigger build

* cover sets passed as arrays

(cherry picked from commit fcb2ec4ed6)
2020-11-20 15:01:12 +01:00
Miran
577b4f795c fix #16047 (#16066)
(cherry picked from commit 1ad7e4f30b)
2020-11-20 13:53:35 +01:00
satoru
e99c248106 colors: Reuse the HexDigits constant in strutils (#16065)
Co-authored-by: Xuecong Liao <xliao@flexport.com>
(cherry picked from commit 81a03238ed)
2020-11-20 13:39:59 +01:00
flywind
9c6444c192 alternative way to fix #16022 (#16064) [backport:1.4]
* alternative way to fix #16022
* add testcase for #16022

[backport:1.4]

(cherry picked from commit 6cf5ca1dc2)
2020-11-20 13:39:04 +01:00
Antonis Geralis
e94f9cdb4f Improve enumerate (#16053)
* Improve enumerate

* updates

* add tests

(cherry picked from commit 59332ec235)
2020-11-20 13:38:49 +01:00
Andreas Rumpf
4ddb8feb93 fixes #15942 [backport:1.2] [backport:1.4] (#16051)
(cherry picked from commit 1efd11e266)
2020-11-19 13:51:16 +01:00
flywind
ff8fbb3001 close #14847(add testcase for #14847) (#16045)
(cherry picked from commit 1bcc352137)
2020-11-19 13:51:04 +01:00
Andreas Rumpf
63296fb983 makes parsesql .gcsafe [backport:1.0] (#16039)
(cherry picked from commit 743f2f5faa)
2020-11-19 13:50:49 +01:00
Timothee Cour
80068f7dfc fix #16033 nim js --gc:arc works and ignores --gc:arc (#16036)
(cherry picked from commit 557dcfd87d)
2020-11-19 13:49:56 +01:00
Andreas Rumpf
8e181cbd3f fixes db_mysql broken quoting; refs c16ee37a71 (r44209990) [backport:1.4] (#16035)
(cherry picked from commit 2773efa034)
2020-11-19 13:48:40 +01:00
Igor Ribeiro de Assis
80c33b187d Do not read the whole file to compute SHA1 hash (fixes 15997) (#16006)
* Do not read the whole file to compute SHA1 hash (fixes 15997)

* Update lib/std/sha1.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

* Update lib/std/sha1.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

* Directly break from loop

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

 [backport:1.2] [backport:1.4]

(cherry picked from commit baaa19b927)
2020-11-19 13:48:06 +01:00
cooldome
817a16c027 Semfold for nil cast (#16030)
* bring back the semfold of nil

* remove space

* fix test

* proc type can't be dereferenced

(cherry picked from commit 87d3e5331a)
2020-11-19 13:46:59 +01:00
Juan Carlos
63ae6308c2 htmlgen: Add lazy loading (#15986)
(cherry picked from commit a8858eb93e)
2020-11-19 13:45:45 +01:00
Bung
f0b19e8ef2 add parent property to window in dom.nim (#15922)
(cherry picked from commit bc007a3cd3)
2020-11-19 13:45:28 +01:00
narimiran
41569f9693 fix wrong backport containing idgen 2020-11-18 11:53:22 +01:00
flywind
5977f553fc fix #6497 (#16027)
* fix #6497

* add testcase for #16027

(cherry picked from commit 581bcfe290)
2020-11-18 11:31:30 +01:00
flywind
462209f4b0 combine PR#16009 and PR#16012 (#16024)
* fix #15623
* add testcase for #15623
* add testcase
* combine #16009
* support casting nil to NilableTypes in VM

(cherry picked from commit e6e1e9574d)
2020-11-18 11:31:04 +01:00
flywind
55abacc514 fix #15972 (#15994)
* fix #15972

* add testcase

* more

(cherry picked from commit 0869d2a477)
2020-11-18 11:30:56 +01:00
Timothee Cour
ce1570a6fb defer: improve manual, clarify difference wrt try/finally (#16010)
(cherry picked from commit 50d035b789)
2020-11-18 11:04:29 +01:00
Timothee Cour
cc6497406f remove unused and misleading FilenameOption.foShort (#15982)
(cherry picked from commit 61352d5a20)
2020-11-18 11:03:26 +01:00
narimiran
00c9dafd5f telling us once about a change is enough [ci skip]
(cherry picked from commit 3e5e029ef8)
2020-11-18 11:01:23 +01:00
flywind
9560efafc2 rename: stmt -> typed and expr -> untyped (#15989)
* stmt -> typed

* expr -> untyped

* minor

(cherry picked from commit 4213f7a6c9)
2020-11-18 11:01:15 +01:00
cooldome
b92666745e fix #15910 (#15984)
* fix #15910

* produce op of op is nil

* Trigger build

(cherry picked from commit a4d02f591c)
2020-11-18 11:01:05 +01:00
Timothee Cour
d08c2f195c workaround #15713 disable freebsd tssl.nim (#15718)
(cherry picked from commit b56a037183)
2020-11-16 14:12:06 +01:00
Luca Guzzon
c225d0182a Console apps in Windows can raise OSError (#15874)
Console apps in Windows implementation can raise OSError so I've fixed it, see below some examples for reference:
- c07807bedf/lib/pure/terminal.nim (L170)
- c07807bedf/lib/pure/terminal.nim (L178)
- c07807bedf/lib/pure/terminal.nim (L191-L192)
- c07807bedf/lib/pure/terminal.nim (L196-L197)
- ...

(cherry picked from commit 49f68122e6)
2020-11-16 11:24:44 +01:00
narimiran
e0e8762e6b fix wrongly backported change containing nextId 2020-11-16 09:52:59 +01:00
Andreas Rumpf
fffb0dbea5 fixes #15753 [backport:1.4] (#15971)
(cherry picked from commit 7eb34d170a)
2020-11-16 07:30:53 +01:00
Clyybber
f02b359968 Fix nimsuggest/#117 (#15602)
(cherry picked from commit 92da06e64e)
2020-11-16 07:29:30 +01:00
Juan Carlos
7c4fbde78e https://github.com/nim-lang/Nim/pull/15968/files#r523468677
(cherry picked from commit 1b9f37c6dc)
2020-11-16 07:28:59 +01:00
Juan Carlos
2f08a1e390 Fix #15806
(cherry picked from commit c56a6133bb)
2020-11-16 07:28:43 +01:00
Juan Carlos
6cc39b5a57 Fix #15806
(cherry picked from commit 9ab1a86b5b)
2020-11-16 07:28:32 +01:00
Juan Carlos
2bfabfde49 Fix #15806
(cherry picked from commit 3cebae492e)
2020-11-16 07:28:26 +01:00
Juan Carlos
d4ce6acfed Fix #15806
(cherry picked from commit d0dda9efab)
2020-11-16 07:27:32 +01:00
flywind
11f6fd88ea minor
(cherry picked from commit bfa387d384)
2020-11-16 07:27:25 +01:00
flywind
452203a28e [docs minor]add some tips yo intern.rst
(cherry picked from commit 5af798c21b)
2020-11-16 07:27:20 +01:00
Timothee Cour
b47a98f7f2 targets: use cpp instead of c++ everywhere (was by far the most common) (#15961)
(cherry picked from commit 96930b9cae)
2020-11-16 07:25:54 +01:00
Timothee Cour
95efe6d3ca strengthen taddr.nim: add test case for #14578; reference other issues; test cpp (#15960)
(cherry picked from commit 1a47fc2291)
2020-11-16 07:25:40 +01:00
Araq
a2c51867f2 fixes the doc rendering
(cherry picked from commit 02f8b11a71)
2020-11-16 07:19:56 +01:00
Araq
0848a816b2 ported to FreeRTOS
(cherry picked from commit 9f566881f1)
2020-11-16 07:19:49 +01:00
Araq
1be3caf7c3 makes test green again
(cherry picked from commit fa7b12bcf9)
2020-11-16 07:19:40 +01:00
Araq
4095cae94c fixes 'nim doc'
(cherry picked from commit 19d52033f8)
2020-11-16 07:19:31 +01:00
Araq
3e9df7da45 better documentation
(cherry picked from commit cb19dc53ca)
2020-11-16 07:19:23 +01:00
Araq
abe178b602 attempt to make asynchttpserver better; fixes #15925; [backport:1.0]
(cherry picked from commit 8778d4a6f3)
2020-11-16 07:19:17 +01:00
Bung
42a3e31826 Fix #8404 JS backend doesn't handle float->int type conversion (#15950) [backport]
* Fix #8404 JS backend doesn't handle float->int type conversion
* handle conv to uint as cast, discard other cases
* limit to int32, times use int64
* toInt including tyInt64 break times timezones lib, ignore for now
* also affect to vm
* move to tests/misc/t8404.nim

(cherry picked from commit 797cb2e67b)
2020-11-16 07:18:16 +01:00
flywind
b9260514fe minor
(cherry picked from commit a86aa31081)
2020-11-16 07:12:23 +01:00
flywind
5d88e6c5f5 add testcase for #9754
(cherry picked from commit a968e7dd9b)
2020-11-16 07:12:16 +01:00
flywind
36429cabda nil
(cherry picked from commit 0f53b129b7)
2020-11-16 07:12:08 +01:00
flywind
a983c6a843 close #13062(add testcase for #13062) (#15956)
(cherry picked from commit d802a4a669)
2020-11-16 07:09:55 +01:00
flywind
561902ca2b close #2771(add testcase for #2771) (#15932)
(cherry picked from commit 7d51ad96e9)
2020-11-16 07:09:39 +01:00
lenoil98
b3b7a1e73f Update buildsh.nimf (#15945)
fix powerpc64le detection

(cherry picked from commit 778914c3ca)
2020-11-16 07:07:58 +01:00
wilypomegranate
efaa55d429 Don't use os for Standalone (#15944)
(cherry picked from commit 1fdfa234d7)
2020-11-16 07:07:25 +01:00
treeform
afedd5ee24 Add documentElement to Document. (#15943)
(cherry picked from commit 83432aecfc)
2020-11-16 07:07:05 +01:00
flywind
9b51f9b7e1 fix #15941 (#15948)
* fix #15941

* add testcase

* update

(cherry picked from commit 492e9afa4c)
2020-11-16 07:06:15 +01:00
flywind
71583cd2e9 add testcase
(cherry picked from commit 8ec3c141ae)
2020-11-16 07:05:58 +01:00
flywind
53421be985 make workaround for #15934 and #15620
(cherry picked from commit 077eba7b38)
2020-11-16 07:05:51 +01:00
flywind
37229707ed change some code-blocks to runnableExamples and correct some errors in docs (#15900)
* original docs are wrong
* fix pathnorm
* Update lib/pure/pathnorm.nim

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
(cherry picked from commit ef2677f5f3)
2020-11-16 07:00:48 +01:00
lenoil98
30362cde20 Add support for FreeBSD/PowerPC64 Little Endian (#15927)
* Update installer.ini

Add support for powerpc64 little endian

* Update buildsh.nimf

Add support for powerpc64 little endian

* Update makefile.nimf

Add support for freebsd/powerpc64 little endian

(cherry picked from commit 63c559e781)
2020-11-16 07:00:24 +01:00
Christopher Dunn
9fb713cf23 Fix a problem for long symlinks in conda (#15908) [backport]
* d8c80ea69d (diff-e1d8e552330911f9f779f85b6f2c00a15e790dcc3fbb3b28f5da1d660a30c5b8)

(cherry picked from commit c6ceefea6d)
2020-11-16 06:58:21 +01:00
flywind
23ea176cb2 fix #15916 (#15917) [backport]
* fix #15916

* add testcase for #15916

* add comments

(cherry picked from commit 402df0b061)
2020-11-16 06:58:07 +01:00
Fanael Linithien
48e5520894 Fix #15909 (#15914)
(cherry picked from commit 7d4f70280e)
2020-11-16 06:57:46 +01:00
flywind
23b0b10886 fix #14157 (#15877)
* fix #14157

* Update compiler/jsgen.nim

* add changelog

* Update compiler/jsgen.nim

* Update tests/js/tmodify_cstring.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 1f9bf43100)
2020-11-16 06:56:43 +01:00
Bung
04254fe9d6 fix #12726 Cannot take the compile-time sizeof Atomic types (#15928)
* fix #12726 Cannot take the compile-time sizeof Atomic types

* fix for arch 32

(cherry picked from commit 826e62953f)
2020-11-16 06:56:33 +01:00
Bung
272bc81f51 Fix 14127 js from int to int casting (#15918)
* fix #14127 from int to int casting

* add test for #14127

* use template for test, also test uint2int

* move to tests/types/t14127_cast_number.nim targets:c cpp js

(cherry picked from commit a81434a890)
2020-11-16 06:56:24 +01:00
narimiran
d10f841b60 nimdoc: items of ordered lists now have numbers instead of circles
(cherry picked from commit f02c7542fc)
2020-11-16 06:55:32 +01:00
narimiran
1781848122 remove codeowners [ci skip]
(cherry picked from commit b831033db6)
2020-11-16 06:55:25 +01:00
ee7
916c4bb484 Docs(strutils): Fix broken links (#15912)
The `dedent` and `unindent` links were introduced by commit d67c5cb751
(#15264).

(cherry picked from commit 42c434fa3d)
2020-11-16 06:55:00 +01:00
flywind
2e6cfe3a0d close #4318(add testcase for #4318) (#15904)
* close #4318(add testcase for #4318)

* Update tests/objects/t4318.nim

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
(cherry picked from commit 35f8803250)
2020-11-16 06:54:53 +01:00
Miran
04f810c2ec Correct all eggs (#15906)
* "eg" is a misspelled "egg", "e.g." is "exempli gratia"
* Also, "ie" is "i.e.".

(cherry picked from commit bbe49a14ae)
2020-11-16 06:54:45 +01:00
narimiran
192cb9ff90 fix norm package testing command
(cherry picked from commit c44ae647a9)
2020-11-16 06:54:34 +01:00
flywind
127d63b343 fix #12471 (#15901)
* fix #12471

* add testcase

* fix

* test nimdoc is tricky

* Delete t12471.nim

(cherry picked from commit b38f0403fd)
2020-11-16 06:54:25 +01:00
flywind
a27ed88688 follow #15874(add testcase for #15874) (#15893)
(cherry picked from commit d8e7caf5dd)
2020-11-16 06:54:10 +01:00
cooldome
7724cd534f fix #15825 (#15894)
* fix #15825

* better fix

(cherry picked from commit 338602a402)
2020-11-16 06:53:59 +01:00
Clyybber
4e89dffc15 Add testcase for #14601 (#15677)
(cherry picked from commit 7435d912ad)
2020-11-16 06:53:52 +01:00
narimiran
19a11bc8a6 fix the incorrect merge conflict of an earlier backport 2020-11-10 12:31:06 +01:00
Aethylia
244f3f62ce Added [:T] syntax explanation to generics tutorial. (#15890)
* Added [:T] syntax explanation to generics tutorial.

* Update doc/tut2.rst

Co-authored-by: flywind <43030857+xflywind@users.noreply.github.com>

* Update doc/tut2.rst

Co-authored-by: flywind <43030857+xflywind@users.noreply.github.com>

* Made second generics example runnable and added test line.

* Update doc/tut2.rst

* Update doc/tut2.rst

* Update doc/tut2.rst

Co-authored-by: flywind <43030857+xflywind@users.noreply.github.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 53eca459f1)
2020-11-09 16:26:00 +01:00
ee7
b6f8ed7193 CI(actions): Replace deprecated add-path commands (#15892)
This commit resolves the following warning in the CI logs:

> Error: The `add-path` command is deprecated and will be disabled soon.
> Please upgrade to using Environment Files. For more information see:
> https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/

The deprecation is due to an injection vulnerability (CVE-2020-15228).

See:
- https://bugs.chromium.org/p/project-zero/issues/detail?id=2070
- https://github.com/nim-lang/Nim/runs/1373146963#step:8:1

(cherry picked from commit 3948b40bcd)
2020-11-09 16:25:54 +01:00
cooldome
18289607eb Fix 15629 (#15888)
* fix #15858

* fix space

* fix #15629

* Revert "fix space"

* Revert "fix #15858"

(cherry picked from commit 69fe707025)
2020-11-09 16:25:22 +01:00
cooldome
d57418ab9e Fix #15858 (#15887)
* fix #15858
* fix space
* fix #15629
* Revert "fix #15629"

(cherry picked from commit d5a0a5dfff)
2020-11-09 16:25:14 +01:00
n5m
e7e33b14b5 improve Testament docs (#15881)
* fix mentions of recursive test discovery

* document that {.fatal.} pragmas cannot be caught

(cherry picked from commit 3bff12b966)
2020-11-09 16:25:07 +01:00
Bung
cd97e3ef98 export PrettyOptions,prettyPrint from nimpretty (#15865)
(cherry picked from commit 204435ad97)
2020-11-09 16:25:00 +01:00
cooldome
283698b1ec fix #15707 (#15870)
(cherry picked from commit 7b19217798)
2020-11-09 16:24:20 +01:00
flywind
8f35bca839 fix #12558 (#15864)
* fix #12558
* Update compiler/pragmas.nim

(cherry picked from commit 673c5990c6)
2020-11-09 16:24:00 +01:00
n5m
12145adecd include example of error-marked copy proc (#15886)
* include example of error-marked copy proc

* Update destructors.rst

(cherry picked from commit 3be404af04)
2020-11-09 16:23:45 +01:00
Clyybber
5ea4dea4ea Closes #12897 (#15867)
(cherry picked from commit 60c364fb22)
2020-11-09 16:22:13 +01:00
flywind
e7d14ce6f2 close #8829(add testcase for #8829) (#15866)
(cherry picked from commit fb60e35a54)
2020-11-09 16:22:05 +01:00
flywind
839ec1395d follow #11707(add pragmas examples for =>) (#15863)
(cherry picked from commit 9fd67958b9)
2020-11-09 16:21:57 +01:00
flywind
ac32cf129b fix #15851 (#15852)
* fix #15851

* {.cast(noSideEffect).}

(cherry picked from commit 218ff27b70)
2020-11-09 16:21:16 +01:00
cooldome
992912e21d static[T] related fixes (#15853)
* close #9679

* close #7546

* close #9520

* close #6177

(cherry picked from commit cdd459dd60)
2020-11-09 16:21:11 +01:00
cooldome
ca53629c42 fix #15609 (#15856)
* fix #15609

* fix test

(cherry picked from commit fa5f225efc)
2020-11-09 16:21:03 +01:00
Clyybber
554a9ad156 Tiny unittest doc fix
(cherry picked from commit d1bea1f71f)
2020-11-09 16:20:51 +01:00
cooldome
1c027d591c Fix #12636 (#15850)
* close #11142

* fix #12636

* undo unwanted changes

* fix illegal recursion case

(cherry picked from commit 3af7818af4)
2020-11-09 16:20:43 +01:00
cooldome
0ed4c2bc4f close #11142 (#15847)
(cherry picked from commit 9455a0c3e3)
2020-11-09 16:19:28 +01:00
flywind
ac25f63f82 document #15618 (#15810)
* document #15618

* Update lib/pure/unittest.nim

* Update lib/pure/unittest.nim

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>

* Update lib/pure/unittest.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
(cherry picked from commit adde5ba6b0)
2020-11-09 16:19:14 +01:00
flywind
e5a04f8914 fix adding empty sequence to HTTP headers (#15783)
* fix adding empty sequence to HTTP headers

* add tests

(cherry picked from commit c4cc907433)
2020-11-09 16:19:05 +01:00
flywind
8c31c210ee fix #15663 (#15839) [backport:1.4]
(cherry picked from commit 8e1fa84b0d)
2020-11-09 16:18:20 +01:00
flywind
64ded4a51f fix #15463 (#15831)
(cherry picked from commit a8af664e8b)
2020-11-09 16:18:03 +01:00
flywind
5da17acfce change non-working example to runnableExamples (#15841)
(cherry picked from commit cae92f670a)
2020-11-09 16:15:49 +01:00
flywind
5bc573cf1e close #10307(add testcase for #10307) (#15840)
(cherry picked from commit dfa2f011d7)
2020-11-09 16:15:42 +01:00
flywind
b100c67515 close #8457 (#15844)
(cherry picked from commit fdd25ed19c)
2020-11-09 16:15:35 +01:00
cooldome
c2263c685f Use modern enums in compiler (#15775)
(cherry picked from commit 00b495de95)
2020-11-09 16:14:22 +01:00
cooldome
01403f8cfa fix static[Slice[T]] as argument issue (#15842)
(cherry picked from commit 4c19c5dfae)
2020-11-05 09:19:51 +01:00
c-blake
2443b40623 Clarify the sense in which Nim supports recursive iterators in the (#15834)
manual, the tutorial, and the `tbintree` test.

(cherry picked from commit f17555770e)
2020-11-05 09:19:35 +01:00
flywind
3565d14cc4 fix #15835 (#15838)
* fix #15835

* add tests

(cherry picked from commit 7d640e0943)
2020-11-05 09:19:27 +01:00
flywind
6d9961c898 fix deprecated messages regarding high (#15832)
(cherry picked from commit 75dc69417a)
2020-11-05 09:18:45 +01:00
flywind
740112c1e0 fix #12640 (#15829)
(cherry picked from commit b8bcf236dd)
2020-11-05 09:17:52 +01:00
flywind
bf446e8cec follow #15818 and close #7109 (#15823)
* follow #15818 and close #7109

* Update compiler/jsgen.nim

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
(cherry picked from commit fde17b159f)
2020-11-05 09:17:42 +01:00
Andreas Rumpf
bb3cdcad99 fixes #15804 (#15820)
* fixes #15804

* fix the existing test

* add the testcase for #15804

Co-authored-by: narimiran <narimiran@disroot.org>
(cherry picked from commit dfd8a83f35)
2020-11-05 09:17:29 +01:00
flywind
9954b7f046 fixes #15594 (#15819)
(cherry picked from commit eb429988cd)
2020-11-05 09:17:12 +01:00
flywind
dd36bfffa1 more clear (#15812)
(cherry picked from commit 4fe56b56ce)
2020-11-05 09:16:24 +01:00
flywind
9d9bf12e1c Closure iterators are not supported by VM (#15818)
(cherry picked from commit 5b4c17b5e7)
2020-11-05 09:16:10 +01:00
flywind
45e87ade15 fix #8821 (#15809)
(cherry picked from commit 544cb107c7)
2020-11-05 09:16:00 +01:00
Thomas Tay
b238c077a1 Update tables documentation (#15807)
Added a case where a user might use mgetOrPut and create an accidental
copy of a seq.

(cherry picked from commit 5298366f86)
2020-11-05 09:13:52 +01:00
flywind
29cd083e12 fixes #15717
(cherry picked from commit 558115fa29)
2020-11-05 09:13:09 +01:00
flywind
2e35621af0 fix #15815 (#15817)
(cherry picked from commit 919593395c)
2020-11-05 09:13:05 +01:00
flywind
e0aa7cf09b fix #15145 (#15816)
(cherry picked from commit 27eb19cc48)
2020-11-05 09:13:00 +01:00
flywind
98bd81b4a3 closes #3670 [add testcase for #3670] (#15808)
* add testcase

* Update tests/template/twhenintemplates.nim

Co-authored-by: Clyybber <darkmine956@gmail.com>
(cherry picked from commit 98cec6b692)
2020-11-05 09:12:45 +01:00
Clyybber
5e7c6b7f7e Typos
(cherry picked from commit 1eb4a38a50)
2020-11-05 09:12:33 +01:00
n5m
0699b57402 improve public Testament docs (#15710)
* improve glob docs

* punctuation

* move spec descriptions above example

notably, change the description of timeout to reference seconds, not microseconds

* document nimout

* document sortoutput

* explain the action options

(cherry picked from commit bcb30566fc)
2020-11-05 09:12:26 +01:00
flywind
f235eb48a0 fix #15651 (#15800)
* fix

* minor

(cherry picked from commit 80b0748d75)
2020-11-05 09:12:17 +01:00
flywind
975a5b64ad support par expression as checkpoint (#15802)
(cherry picked from commit 8115b655e7)
2020-11-05 09:12:04 +01:00
flywind
5d2b1a8943 [closes #12682]add testcase for #12682 (#15796)
* add testcase for #12682

* fix

(cherry picked from commit bc9a521270)
2020-11-05 09:11:34 +01:00
Miran
b14958caa0 fix #15702, show enum fields documentation (#15792)
(cherry picked from commit 28bbcd9d45)
2020-11-05 09:11:28 +01:00
Clyybber
208ed6e816 Grammar fixes
(cherry picked from commit 7364794fed)
2020-11-05 09:11:23 +01:00
flywind
e085010e59 add testcase for #14227 (#15794)
(cherry picked from commit ae86df12af)
2020-11-05 09:11:08 +01:00
flywind
f6f1594cef [closes #11625 and closes #2488]add global and threadvar(with --threads:off mode ) pragmas supports for JS backend (#15772)
* add global pragma support for js backend

* globalThis

* add support for threadvar

* more tests

* Update compiler/jsgen.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 2cfe5e0745)
2020-11-05 09:11:02 +01:00
cooldome
c657af440a canAlias improvement (#15773)
* canAlias improvement

* fix comment

(cherry picked from commit 6fe2e8977d)
2020-11-05 09:10:20 +01:00
Miran
df069c8ddb promote collect macro as a map+filter replacement (#15788)
* promote `collect` macro as a map+filter replacement

* Update lib/pure/collections/sequtils.nim

(cherry picked from commit ec059240b0)
2020-11-05 09:10:05 +01:00
Timothee Cour
e524df8746 simplify toHex (#15821)
(cherry picked from commit 235e4930ab)
2020-11-05 09:09:55 +01:00
Miran
81a302b197 fix toHex - make it work with int literals (#15770)
(cherry picked from commit c0fdc8b215)
2020-11-05 09:09:46 +01:00
flywind
e301285d4c closes #6036 (#15779)
* add testcase for #6036

* try

* try again

* make it work

(cherry picked from commit 4374c638cd)
2020-11-05 09:09:30 +01:00
flywind
daba6d935f closes #7374 (#15781)
* add testcase for #7374

* minor

* fix test

(cherry picked from commit 1725db9295)
2020-11-05 09:09:09 +01:00
flywind
1d06c70c18 add testcase for #7416 (#15782)
(cherry picked from commit 3028c1be82)
2020-11-05 09:08:56 +01:00
flywind
a480cbddcc closes #7658 (#15784)
* fix #7658

* more

(cherry picked from commit 17f08b2939)
2020-11-05 09:08:49 +01:00
flywind
eb2ed782c6 add testcase for #8012 (#15785)
(cherry picked from commit 2de90a14cb)
2020-11-05 09:08:42 +01:00
flywind
dc6073b0b8 add testcase for #9165 (#15787)
(cherry picked from commit 1655c04aa3)
2020-11-05 09:08:38 +01:00
flywind
3d939dd863 add testcase for #9091 (#15791)
* add testcase for #9091

* more tests

(cherry picked from commit b5df823191)
2020-11-05 09:08:19 +01:00
flywind
d426f75593 fix #15638 (#15789)
(cherry picked from commit f79ded3cb6)
2020-11-05 09:08:14 +01:00
flywind
051c201068 add testcase for #7127 (#15780)
(cherry picked from commit d8fb2379c9)
2020-11-05 09:08:01 +01:00
flywind
b0291b88fc add tests for #7686 (#15771)
(cherry picked from commit 33e258c72f)
2020-11-05 09:07:51 +01:00
Antonis Geralis
1b5b98c943 Fix doc comment for sumKbn (#15769)
Co-authored-by: b3liever <b3liever@yandex.com>
(cherry picked from commit 912d8f80ad)
2020-11-05 09:07:43 +01:00
Andreas Rumpf
645200aa3d fixes #15413 (#15768)
* fixes #15413

* better hide it properly

* see if this makes our list of important packages happy

(cherry picked from commit 87a60c1b28)
2020-11-05 09:07:36 +01:00
Yanis Zafirópulos
a7bd58ed07 Massive documentation fixes + copy editing (#15747)
(cherry picked from commit 0cae8ef2ca)
2020-11-05 09:07:07 +01:00
Tim Smith
4a95d45b28 Spelling and Grammer fixes (#15719)
Co-authored-by: Tim Smith <tim.smith.hdg@gmail.com>
Co-authored-by: Miran <narimiran@disroot.org>
(cherry picked from commit 485d4ff802)
2020-11-05 09:07:01 +01:00
Antonis Geralis
60403c9e6b Make newObjUninit proc to adhere to its name (#15764)
Co-authored-by: b3liever <b3liever@yandex.com>
(cherry picked from commit 94e2b9e837)
2020-11-05 09:06:53 +01:00
cooldome
e39b01e126 fix #15756 (#15761)
* fix #15756

* simplify test

(cherry picked from commit 610e9b2fe9)
2020-11-05 09:06:45 +01:00
cooldome
a4f9bc55c7 ARC now capable of custom extra alignment. Ref, closure and seq support. (#15697)
(cherry picked from commit 0956a99537)
2020-11-05 09:06:39 +01:00
narimiran
e27f595aee change/remove deprecated stuff
(cherry picked from commit 732ddc02da)
2020-11-05 09:06:07 +01:00
narimiran
96bd6426c2 fix #15750
(cherry picked from commit b13fb9ddb8)
2020-11-05 09:05:46 +01:00
cooldome
afb5212fe0 fix #15752 (#15754)
(cherry picked from commit f8cac6bbbc)
2020-11-05 09:05:39 +01:00
shirleyquirk
5c48058c86 fixes #10456,#12928 issues when chaining templates to sortedByIt (#15734)
* update c_malloc's to csize_t

fix for broken --os:ios

* I'm an idiot sorry

* Create talgorithm.nim

* workaround for #10456

I don't understand the intricacies of how lambdalifting and template expansions interact with lent, so i don't know how to fix the real problem, but this sidesteps whatever issue that is.

* working test, use typeof rather than auto

(cherry picked from commit 218acfe367)
2020-11-05 09:05:21 +01:00
n5m
33375aff15 add tests for Testament "reject" action (#15709)
* add test for reject action

* highlight that a compilation failure is expected

* add the converse test for action=reject

* add trailing newline

* fix wording

(cherry picked from commit 066f3ebc2a)
2020-11-05 09:04:57 +01:00
Xavier Noria
1fbfd77580 Document implicit return values from procedures (#15738)
(cherry picked from commit 25955440df)
2020-11-05 09:03:57 +01:00
Timothee Cour
3326f1df1d [backport] fix #15595 procvar == works in VM (#15724)
(cherry picked from commit 3bdc000521)
2020-11-05 09:03:47 +01:00
Andreas Rumpf
a156484553 ensure the Nim compiler works with --experimental:strictFuncs --experimental:views [backport:1.4] (#15737)
(cherry picked from commit cf01945f54)
2020-10-27 09:06:45 +01:00
Juan Carlos
c8f6eb6c14 Documentation only iup (#15732)
* ReSync with Devel

* ReSync

* Add Examples for IUP, based from official doc

(cherry picked from commit 3a69f14621)
2020-10-27 09:06:20 +01:00
Yanis Zafirópulos
513ced8966 Copy editing (#15733)
(cherry picked from commit ae8eb1ec3d)
2020-10-27 09:05:46 +01:00
Andy Davidoff
75d76c28c8 add criterion to important packages (#15604)
* add criterion to important packages

* use a special nimscript for criterion tests

* fix criterion speed differently

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit ea6c28249a)
2020-10-27 09:02:46 +01:00
Jason Beetham
2351b66e08 Fixed iteration limit hit from execproc (#15723) [backport:1.2] [backport:1.4]
When calling procs from Nim in Nimscript you could hit the VM iteration limit even though the code is functioning properly. This resolves that by making the iteration limit reset eachtime you call a proc.

(cherry picked from commit a87617956f)
2020-10-27 09:02:11 +01:00
Danil Yarantsev
a2367d4bd2 Add support to the latest LibreSSL version (#15715) [backport:1.2] [backport:1.4]
(cherry picked from commit b2740f5c63)
2020-10-27 09:01:51 +01:00
Timothee Cour
4e91c11eff fix #15704 #15597 wrong VM register was freed (#15705)
* fix #15704 #15597 wrong VM register was freed

* same treatment for nkCheckedFieldExpr

* note concerning HighRegisterPressure

* bump NimPatch

* Update lib/system.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit d4c2e2c53f)
2020-10-27 09:00:51 +01:00
Timothee Cour
9d81415603 close #8007 (#15695)
(cherry picked from commit bf894ad3eb)
2020-10-27 09:00:48 +01:00
Danil Yarantsev
60ddbf1e45 Add tests to #15363 (#15633)
(cherry picked from commit d22ab0fb96)
2020-10-27 08:59:52 +01:00
Juan Carlos
a48c16b155 Fix Prelude (#15714)
* ReSync with Devel

* Fix prelude for JS target

* ReSync devel

* Fix prelude for JS target

(cherry picked from commit e284445e51)
2020-10-27 08:57:50 +01:00
rockcavera
796785abf6 fix #15698 (#15699)
* fix in the net.`$` to print zeros that are not in the compressed group

* Update lib/pure/net.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

* Update net.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 7252a50fef)
2020-10-27 08:57:18 +01:00
Timothee Cour
e89592787b [minor] nimVMDebug: fix codeListing formatting for jump-to-file to work (#15711)
(cherry picked from commit 64eb62889a)
2020-10-27 08:57:18 +01:00
Clyybber
9b37fc98a2 Try to fix CI failures (#15701)
* Use cligens release version

* Rework important_packages main loop

* Fix

* Fix

* Create pkgs dir

* Don't use nimble develop
since it doesn't work for binary only packages, and always install head

* Use git to get the latest release/tag instead

* Tackle the root cause

* Reduce diff

* Cleanup

(cherry picked from commit e18fc698ed)
2020-10-27 08:57:18 +01:00
Clyybber
9e8ad86d6a Revert "fixes #15280 [backport:1.2] (#15281)" (#15700)
This reverts commit 3f00a738db.

(cherry picked from commit d4022ebe53)
2020-10-24 17:16:02 +02:00
cooldome
d1924f2852 fix #15662 (#15678)
* fix #15662

* alternative fix

* fix spacing

(cherry picked from commit ae320b4e7d)
2020-10-24 17:15:08 +02:00
Clyybber
7a9db0e5c5 Fix #12410 (#15685)
* Fix #12410, big thanks to @pmetras for this fix

* Add testcase

(cherry picked from commit 01a62320f0)
2020-10-24 17:14:49 +02:00
Andreas Rumpf
e7b7356bd1 fixes view types for sizeof() and --gc:orc (#15680)
(cherry picked from commit 64016ddedc)
2020-10-22 20:21:49 +02:00
Andreas Rumpf
ce94ce40c7 fixes #15652 [backport:1.4] (#15679)
(cherry picked from commit 8358974b73)
2020-10-22 20:21:42 +02:00
Miran
6d99de7c2c [backport: 1.4] Better linebreaks (#15658)
(cherry picked from commit d8a6b0b04e)
2020-10-22 20:20:49 +02:00
n5m
06846d23ad expect valgrind test failure on memory leak (#15669)
* expect valgrind test failure on memory leak

* alloc 1 instead of 0

(cherry picked from commit 8da0e01769)
2020-10-22 20:20:15 +02:00
Gampol T
bc5c6c812b Fix #13609 (#15567)
* add documentation that discardable pragma cannot use on template

* Update doc/manual.rst

Co-authored-by: Euan <euantorano@users.noreply.github.com>

* Update doc/manual.rst

Co-authored-by: Euan <euantorano@users.noreply.github.com>

Co-authored-by: Euan <euantorano@users.noreply.github.com>
(cherry picked from commit b2f51e2950)
2020-10-22 20:19:23 +02:00
Andreas Rumpf
eb04535b53 fixes bootstrapping for any machine that has a Nim already installed [backport:1.4] (#15660)
(cherry picked from commit 9a059657ca)
2020-10-21 11:09:13 +02:00
Timothee Cour
11ef97d57f $(uint|uint64) now works with nimscript (#15644)
* $(uint|uint64) now works with nimscript

* fixup

(cherry picked from commit 3cbe8d2c53)
2020-10-21 11:08:43 +02:00
RecruitMain707
5874bce91c Fix compilation error for regions and memory profiling (#15641) (#15656)
Co-authored-by: Recruit_main707 <Recruit_main707@users.noreply.github.com>
(cherry picked from commit ed0f8a4973)
2020-10-21 11:08:14 +02:00
narimiran
38ebd767db even more "eg" fixes [ci skip]
(cherry picked from commit b418c54ec4)
2020-10-21 11:07:40 +02:00
Tomáš Hübelbauer
293ef09b49 Remove bit about opening files not raising (#15654)
Resolved #473

I am removing this bit because this advice to not throw on recoverable-from cases like a file failing to open is actually not respected by Nim standard library. `readFile` and `readLines` both throw and exceptions must be used as a method of control flow for the recovery from that. There are alternatives, like opening a file handle instead of using these helpers, but that's less convenient than these helper methods for cases where you really want to just slurp up a file to memory and use a fallback value if it doesn't exist or is for whatever reason not readable.

(cherry picked from commit 725c7caa02)
2020-10-21 11:07:33 +02:00
narimiran
8fb501b52c more "eg" fixes
(cherry picked from commit 5e9dd81baa)
2020-10-21 11:06:50 +02:00
narimiran
c087e2d8de it is not "eg", it is "e.g."
(cherry picked from commit 0a686659d2)
2020-10-21 11:06:28 +02:00
Clyybber
45977c2d70 Fix commentOffsetA for doc comments (#15643)
(cherry picked from commit f20e485827)
2020-10-21 11:03:47 +02:00
n5m
1d63995896 fix #15631 (#15632)
* trigger valgrind failure on memory leak

* remove non-malloc tests

* remove ORC test

is redundant because we already have an ARC test

* only run valgrind tests on 64-bit Linux

* disable freebsd and openbsd

* Remove tleak_refc

As to not test implementation details (or bug)

* Fix test failures by removing redundant test

Since this tests/shoulfail/tvalgrind.nim was specified here to fail this test
itself fails since it will be skipped on non-linux CI

* Remove test, reason detailed in the previous commit

* Remove redundant disables

* Revert removing disables

* Add and use valgrind: leaks

* Fix

Co-authored-by: Clyybber <darkmine956@gmail.com>
Co-authored-by: n5m
(cherry picked from commit 436e1fa5b1)
2020-10-21 11:03:17 +02:00
Clyybber
893dab429e Fix #15639 (#15640)
(cherry picked from commit 0f4b1ed270)
2020-10-21 11:02:27 +02:00
cooldome
1e9746aade arc allocation method aligned (#15588)
* progress

* fix typo

(cherry picked from commit 833035bacd)
2020-10-21 11:02:10 +02:00
cooldome
35f5a3e48f Tables, use sink val arguments more actively (#15625)
(cherry picked from commit 04f8fcfbd0)
2020-10-21 11:01:50 +02:00
n5m
642807de18 add tests for #15584 (#15619)
* add test for #15584

* Rename userlocks.nim to trlocks.nim

* add bug comment

* improve cmd

* reference bugfix, not bug

* add test that runs rlocks

* disallow joining

joining with other test cases (e.g., a test case that invokes `RLock.initRLock()`) may cause this test to compile, when the goal is to test if these lines can be compiled in isolation

(cherry picked from commit 78cbb52fa0)
2020-10-21 11:00:33 +02:00
Euan
8a9da2fa0d Fix FreeBSD build failures (#15613)
The FreeBSD is/was failing, due to a conflict with installing Git.

Git is guaranteed to be in the base image, so this removes that package from the package list. It also reverts back to the built-in `packages` tag since it's officially supported.

Should the build fail in the future, the best place to go is the #sr.ht channel on freenode.

(cherry picked from commit ba2a477e64)
2020-10-21 11:00:21 +02:00
n5m
a222aa14e1 document that Nim executable must be included (#15611)
(cherry picked from commit b16b2eb06f)
2020-10-21 10:59:20 +02:00
Clyybber
d86d7c9fe1 Fix #15599 (#15601)
* Fix #15599

* Add test

(cherry picked from commit 66cd9c2e57)
2020-10-21 10:58:57 +02:00
Andreas Rumpf
b3c77bb982 fixes #15560 (#15587)
(cherry picked from commit a43202ea57)
2020-10-21 10:58:01 +02:00
narimiran
1dffa67b6e bump NimVersion to 1.4.1 2020-10-21 10:57:51 +02:00
narimiran
bdcd87afca cosmetic fixes for the 1.4 changelog [ci skip]
(cherry picked from commit 6b8baab536)
2020-10-16 13:19:32 +02:00
narimiran
018ae963ba add bufixes for 1.4 in its changelog
(cherry picked from commit 091ec916fd)
2020-10-16 08:14:05 +02:00
narimiran
cffbf5e778 create a changelog for 1.4.0
(cherry picked from commit 6349001879)
2020-10-16 07:17:09 +02:00
narimiran
cac0e01725 bump NimVersion to 1.4.0 2020-10-15 16:10:08 +02:00
shirleyquirk
4ef255b69d fix rlock compilation failure (#15584)
* change SysLockType_Reentrant

fix edge case where using SysLockType_Reentrant doesn't trigger an #include pthread.h

* syslocktype_reentrant now a var
* remove nodecl to remove empty system_syslocks.c
* let is better than var.

in reality SysLockType = enum, maybe that would be a better fix
2020-10-15 12:54:01 +02:00
Andreas Rumpf
da4aa2e1fb renamed '=' to '=copy' [backport:1.2] (#15585)
* Assign hook name changed to `=copy`
* Adapt destructors.rst
* [nobackport] Duplicate tests for =copy hook
* Fix tests
* added a changelog entry

Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-10-15 12:52:30 +02:00
Igor Ribeiro de Assis
42c180c665 Fix crash in parsexml (#15582) (#15583)
Co-authored-by: Igor Ribeiro de Assis <igor.ribeiro_de_assis@zeiss.com>
2020-10-15 12:45:55 +02:00
Andreas Rumpf
fd9ab2ce6d ORC: API extensions for 1.4 (#15581) 2020-10-15 11:51:40 +02:00
Andreas Rumpf
1bbc20010e harden the ORC asyncleak3 test case (#15580)
* harden the ORC asyncleak3 test case

* add another ORC stress test
2020-10-15 09:42:43 +02:00
genotrance
a4c28394be Bump nimble (#15573) 2020-10-14 22:26:44 +02:00
Andreas Rumpf
644eb4dd54 ORC: critical bugfix for the cycle analyser, introduce -d:nimStressOrc for easier stress testing (#15572) 2020-10-14 22:26:21 +02:00
alaviss
c2ba4ef979 suggest: try to find the implementation of a symbol when def is used (#15555)
* suggest: try to find the implementation of a symbol when def is used

* suggest: return all declarations of the symbol on `def`
2020-10-14 17:08:56 +02:00
Clyybber
977bccdbff Make useVersion:1.0 disable the proc arg sym change (#15570)
* Make useVersion:1.0 disable the proc arg sym change

* Also do this for useVersion:1.2
2020-10-14 16:07:25 +02:00
Andreas Rumpf
8978112457 fixes a C code generator regression, no need to backport, only the 1.4 line is affected (#15569) 2020-10-14 13:58:36 +02:00
Timothee Cour
09cad44be9 ci docs: add config/nimdoc.cfg to paths (#15566) 2020-10-14 12:04:14 +02:00
Benjamin Lee
12c8ef5949 Update the list of GC options when raising an error (closes #15547) (#15553) 2020-10-14 11:20:59 +02:00
Andreas Rumpf
c664fb2843 sigmatch: hotfix [backport] (#15565) 2020-10-14 09:55:47 +02:00
narimiran
fc90eb9f27 change case in nimdoc [ci skip] 2020-10-14 09:26:44 +02:00
Timothee Cour
0c0f86b2c5 reference fusion docs (#15562) 2020-10-14 09:25:28 +02:00
alaviss
d1af9587b8 terminal: fix fgColor/bgColor commands [backport] (#15554)
Since #8296, fgSetColor is no longer a global. These commands were
probably left out from the change as an oversight, so some tests have
been added to make sure this won't happen again.
2020-10-13 17:39:32 +01:00
Timothee Cour
0134e34e03 dup docs: add an example with addQuoted (#15548)
* dup docs: add addQuoted example

* fixup
2020-10-13 08:24:30 +02:00
Christopher Dunn
f1d81dc6e6 Fix doc for CountTable (#15561) [backport] 2020-10-13 06:33:53 +02:00
Christian Ulrich
1f51a33998 close socket in getPrimaryIPAddr even if exception occurs (#15558) 2020-10-12 22:02:17 +02:00
Timothee Cour
30b966bdf7 unbreak CI: fix logic for skipping ci (#15556) 2020-10-12 21:04:40 +02:00
cooldome
9668a1106d Fix 15543 (#15544)
* fix #15543

* fix spacing

* fix test

* simplify test for freebsd platform
2020-10-12 10:12:32 +01:00
Andreas Rumpf
d66e274e1a refactoring: moved setOutFile to where it belongs 2020-10-11 20:44:04 +02:00
Andreas Rumpf
3492178494 refactoring: removed cmdlinehelper.mainCommand callback 2020-10-11 20:44:04 +02:00
flywind
c2c7f60259 docs minor (#15550) 2020-10-11 20:43:44 +02:00
Timothee Cour
3eac9b2344 os: add overload copyFile*(source, dest: string, isDir = false) (#15537)
* os: add overload copyFile*(source, dest: string, isDir = false)
* renamed to copyFileToDir
2020-10-11 20:43:01 +02:00
Andreas Rumpf
992952d868 nimpretty: do not produce 'line too long' messages (#15541) 2020-10-10 17:46:22 +02:00
Christian Ulrich
c7ccbfac39 close socket in getPrimaryIPAddr (#15538) [backport] 2020-10-10 07:06:13 +02:00
Timothee Cour
8a5f550491 followup after #15529 and #15534 (#15536) 2020-10-10 07:05:27 +02:00
genotrance
442841037a Fix #12027 (#15519) 2020-10-10 07:04:57 +02:00
genotrance
0a560144ce Bump nimble (#15539) 2020-10-10 07:04:03 +02:00
Andreas Rumpf
d430216288 fixes #15532 (#15534) 2020-10-09 16:18:36 +02:00
Timothee Cour
16e8005031 fix gitignore for testament cruft (#15530)
* fix gitignore for testament cruft

* fix rendertree => renderTree
2020-10-09 11:28:21 +02:00
Timothee Cour
8fb57d7451 close #13081 (#15529)
* close #13081

* fixup
2020-10-09 08:56:09 +02:00
cooldome
91ce4515c8 fix gc:arc in nimscript (#15525) 2020-10-09 08:52:26 +02:00
lihaifeng
3eaacac230 Update parsecfg.nim (#15513)
* Update parsecfg.nim

Returns the specified default value if the specified key value does not exist.

* Update lib/pure/parsecfg.nim

Co-authored-by: flywind <43030857+xflywind@users.noreply.github.com>

* Update lib/pure/parsecfg.nim

Co-authored-by: flywind <43030857+xflywind@users.noreply.github.com>

* Update lib/pure/parsecfg.nim

Co-authored-by: flywind <43030857+xflywind@users.noreply.github.com>

Co-authored-by: flywind <43030857+xflywind@users.noreply.github.com>
2020-10-08 17:17:00 +02:00
Andreas Rumpf
538a57a522 fixes #15511 (#15524) 2020-10-08 17:09:28 +02:00
Andreas Rumpf
cfba237d14 fixes #15510 (#15523) 2020-10-08 15:28:23 +02:00
ee7
aa0b73575c changelog.md: Group the new to procs (#15522)
* changelog.md: Group the new `to` procs [ci skip]

This also moves the `critbits.toCritBitTree` entry from the "Language
Changes" section to the "Standard library additions and changes"
section.

* changelog.md: Remove extra space
2020-10-08 14:21:20 +02:00
Andreas Rumpf
1e9d83efb0 fixes #15512 (#15521) 2020-10-08 14:17:27 +02:00
Araq
4d91cc7950 changelog improvements 2020-10-08 11:43:18 +02:00
Araq
0ac74ddd74 fixes a regression 2020-10-08 11:43:18 +02:00
cooldome
fe187719ab fix #15516 (#15518) 2020-10-08 09:12:03 +02:00
Andreas Rumpf
3b901d1e36 docgen: improve alignment of comments (still not perfect) (#15506)
* docgen: improve alignment of comments (still not perfect)

* fix error message text in `tunknown_named_parameter`

Co-authored-by: narimiran <narimiran@disroot.org>
2020-10-07 14:39:13 +02:00
Andreas Rumpf
0426a4d85a fixes #15508 (#15509) 2020-10-07 14:38:25 +02:00
Andreas Rumpf
acbe27b082 disable 'observable stores' warning message for 1.4 (#15507) 2020-10-07 13:05:19 +02:00
Andreas Rumpf
51e3e0c7c4 implements https://github.com/nim-lang/RFCs/issues/260 (#15505)
* implements https://github.com/nim-lang/RFCs/issues/260

* added a test case
2020-10-07 00:09:28 +02:00
Serban Constantin
dd86228548 update unittest docs with correct exit code info (#15502) 2020-10-06 18:05:57 +02:00
Paul Tan
fa84121421 effects: exclude swap() from "indirect calls" assumption (#15504)
swap() will never call any procs passed to it, and so it can be safely
excluded from the "assume indirect calls are taken" effects tracking
rule.
2020-10-06 18:05:31 +02:00
Juan Carlos
695f955f70 inline tiny proc (#15498) 2020-10-06 16:52:12 +02:00
IDF
9560e49e8f New hint for unused exceptions in .raises (#15492)
* New hint for unused exceptions in .raises

* Fix effects test

* Further adapt teffects1.nim
2020-10-06 16:49:30 +02:00
Andreas Rumpf
92163fa330 implements https://github.com/nim-lang/RFCs/issues/258 (#15503)
* implements https://github.com/nim-lang/RFCs/issues/258

* don't be too strict with custom pragma blocks

* cast pragmas: documentation

* added most missing inference query procs to effecttraits.nim
2020-10-06 16:47:15 +02:00
Benjamin Lee
acd71dd6bb Iterate over smaller set when computing intersection (#15497)
Closes #15496
2020-10-06 10:29:45 +02:00
Juan Carlos
aca1fae55a GitHub Actions Skip CI (#15289) 2020-10-06 04:52:49 +00:00
Araq
37758826ff typo 2020-10-06 06:33:43 +02:00
Araq
e9d7e21dbe minor reformating 2020-10-06 06:10:47 +02:00
Andreas Rumpf
4e438f9096 const view types; fixes some cases from https://github.com/nim-lang/Nim/issues/15428 (#15488) 2020-10-05 18:31:46 +02:00
Juan Carlos
1e28cea0d1 inline tiny func on httpcore (#15480) 2020-10-05 17:08:50 +02:00
David Krause
f25ca0d304 added testament documentation link to tools.rst (#15481) 2020-10-05 17:04:47 +02:00
flywind
af9cc2882f use func in uri module (#15486) 2020-10-05 17:04:08 +02:00
Miran
112b11c154 group procs of the same name in TOC (#15487)
* group procs of the same name in TOC

* correctly show `sink` parameters in TOC

* no need to reinvent the wheel - `mgetorPut` exists

* better setting of text color [ci skip]

* fix CSS for better alignment
2020-10-05 17:03:14 +02:00
Luis Felipe Manfroni
5967b6f60f doc(sugar): added description and examples to dup (#15455) 2020-10-05 12:02:08 +02:00
Euan
cc4c546f8f Fix #15493 - disable TLS emulation for NetBSD (#15494)
TLS emulation was already disabled for FreeBSD due to the same issue.
2020-10-05 12:00:06 +02:00
flywind
b760fdc9ca make testing for prologue more stable (#15491) 2020-10-05 09:57:23 +02:00
supakeen
bbe2eb20df Provide a configurable progressInterval. (#15477) 2020-10-04 11:32:07 +01:00
Abhishek Dubey
ccd1f58183 Installation Instruction (#15485)
The instruction command was missing `install` for Ubuntu.
2020-10-04 10:58:19 +02:00
alaviss
fc973b2c0c renderer: use the biggest integer type for masking literals (#15482)
On 32-bit system the mask would have a size of 32-bit, which is smaller
than the BiggestInt (usually 64-bit) it was masked against.

For some reason this only affect 32-bit Windows but not 32-bit Linux.
Might just be a difference in how gcc handle out of bound shifts for
Windows and Linux.
2020-10-04 00:39:56 +02:00
Andreas Rumpf
2288188fe9 fixes https://github.com/nim-lang/RFCs/issues/257 [backport:1.2] (#15479) 2020-10-03 17:34:42 +02:00
supakeen
662c508075 Return type of asyncftpclient to fix example. (#15476)
Related to: #13641
2020-10-03 13:43:43 +02:00
alaviss
dcd0ce1775 niminst: restore ZIP building functionality (#15472)
This is necessary for building Windows releases, was erroneously removed
by #15451.
2020-10-02 22:48:35 +02:00
ee7
0a05176057 heapqueue.nim: Add toHeapQueue proc (#15459)
Similar to:
- `critbits.toCritBitTree`
- `deques.toDeque`
- `sets.toHashSet`
- `tables.toTable`

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-10-02 16:01:03 -04:00
ee7
d48b356e49 intsets.nim: Add toIntSet proc (#15460)
Similar to:
- `critbits.toCritBitTree`
- `deques.toDeque`
- `sets.toHashSet`
- `tables.toTable`
2020-10-02 21:10:24 +02:00
alaviss
7ef22bf912 koch: remove c2nim from windows release builds (#15471)
We don't ship this tool with any other OS, and the c2nim bundle is
non-deterministic due to the lack of a pinned commit.
2020-10-02 19:18:44 +02:00
Andreas Rumpf
9828392df3 implements https://github.com/nim-lang/RFCs/issues/257 (#15466) 2020-10-02 18:53:22 +02:00
alaviss
e3eae3f7c7 tools/deps: fix git dir check (#15470)
On Windows, a successful call will have a trailing newline appended, so
strip that away before doing any checks.
2020-10-02 18:52:20 +02:00
Andreas Rumpf
ff70ff529d remove nim.cfg file change lefover [backport:1.2] (#15469) 2020-10-02 18:51:49 +02:00
Andreas Rumpf
7d8c1be8fb parser hotfix: don't run into endless loops; regression (#15468) 2020-10-02 18:26:52 +02:00
Andreas Rumpf
1f4b9cebd4 Added std/effecttraits.nim (#15462) 2020-10-02 17:22:31 +02:00
Andreas Rumpf
aa1d7fe1e9 closureiters: fixes #15243 (#15454) [backport:1.2]
* fixes #15243 [backport:1.2]
2020-10-02 12:38:16 +02:00
Euan
f785174c60 Ref #14094 - disable hot code reloading tests on NetBSD (#15458) 2020-10-02 11:17:31 +02:00
flywind
6e32a9e88c use func in httpcore (#15457) 2020-10-02 08:47:24 +02:00
Juan Carlos
d1eb76184b Clean out niminst (#15451) 2020-10-01 22:19:06 +02:00
Euan
b4fe0c8862 Fix #15452 - ip protocol not defined on NetBSD (#15453) 2020-10-01 22:15:34 +02:00
Clyybber
37e0d6f32d Fix typo 2020-10-01 19:58:53 +02:00
Clyybber
800d6204cd Fix "arraq" typo :) 2020-10-01 19:58:08 +02:00
shirleyquirk
84d9b1227d fixes #15430, pop pragma takes invalid input (#15449)
* fix #15430, pop pragma

{.pop, experimental.} should be allowed, but not {.pop experimental.}
2020-10-01 18:07:55 +02:00
c-blake
26d656e73e Add first draft of new osproc.readLines (#15429)
* Add first draft of new osproc.readLines

* Add test for new osproc.readLines

* Rename test to start w/t to run; Also add newline to output

* Suppress hint messages.

* Output should match this time.

* Shoulda picked a program with simpler syntax than ..lol

* Address https://github.com/nim-lang/Nim/pull/15429#issuecomment-701890898
and https://github.com/nim-lang/Nim/pull/15429#issuecomment-701985976 by
factoring `readLines` into `iterator lines` and a wrapper `proc`.

* Address https://github.com/nim-lang/Nim/pull/15429#issuecomment-702127289
and also add a `ReadIOEffect` tag to the iterator (called by the wrapper..
so it should need no separate tag, if I understand correctly).
2020-10-01 18:06:38 +02:00
cooldome
531ed2dc36 fix #15405. deepcopy arc (#15410)
* fix #15405
* fix tests
* deepcopy for ARC has to be enabled via --deepcopy:on

Co-authored-by: Araq <rumpf_a@web.de>
2020-10-01 17:39:48 +02:00
alaviss
3919f0aa54 koch: unify nimble building scripts [backport:1.4] (#15443)
This commit gets rid of buildNimble in favor of the simpler
bundleNimbleExe, which does pretty much the same thing.
2020-10-01 17:20:38 +02:00
flywind
0bfa0fcaea [docs minor] unify generates and Generates (#15434)
* [docs] unify generates and Generates

* fix typo
2020-10-01 15:17:16 +02:00
Juan Carlos
5e160bff1b Add critbits.toCritBitTree (#15444)
* Add critbits.toCritBitTree

* https://github.com/nim-lang/Nim/pull/15444#discussion_r498035342
2020-10-01 15:11:10 +02:00
Juan Carlos
8f90ac6af1 Clean out (#15448) 2020-10-01 15:07:57 +02:00
Andreas Rumpf
ab405c936e views: yet another bugfix (#15447)
* views: yet another bugfix

* views: extended the spec

* views: take into account potential hidden mutations via proc calls
2020-10-01 15:04:36 +02:00
Juan Carlos
79a92da8ef Clean out (#15440) 2020-10-01 12:39:50 +02:00
Juan Carlos
4e7d383f29 Clean out jssys (#15442) 2020-10-01 11:21:27 +02:00
Andreas Rumpf
2b91845f1d refactoring, fixes yet another strictFuncs regression (#15446) 2020-10-01 11:16:04 +02:00
Andreas Rumpf
b703f02ad2 added missing .noalias support for object fields (#15445) 2020-10-01 09:46:50 +02:00
Juan Carlos
6b3654c48d Add 1 overload to apply (#15439) 2020-10-01 09:22:22 +02:00
Andreas Rumpf
86d7b63e2a better support for view types (#15436)
* you can put borrows into tables

* enforces mutating views only mutate mutable data
2020-09-30 20:44:18 +02:00
flywind
9c86f4867e fix doc search(escape HTML code) (#15433)
* use release version

* fix doc search
2020-09-30 10:52:49 +02:00
Miran
eb2a4961c7 various documentation fixes [backport] (#15422) 2020-09-29 23:43:12 +02:00
Andreas Rumpf
4058801607 spec for view types (#15424)
* spec for view types
* spec additions
* refactoring; there are two different kinds of views
* refactorings and spec additions
* enforce that view types are initialized
* enforce borrowing from the first formal parameter
* enforce lifetimes for borrowing of locals
* typo in the manual
* clarify in the implementation what a borrow operation really is
2020-09-29 23:42:38 +02:00
shirleyquirk
f8866598e7 odbc regression from #14357 (#15417)
#14357 changed from sending 'val', an int, to a pointer to int, which is understandable, but not how SQLSetEnvAttr works.
"Depending on the value of Attribute, ValuePtr will be a 32-bit integer value or point to a null-terminated character string"
2020-09-29 17:08:24 +02:00
Yuriy Glukhov
22d0a39932 Dont assert on setstacksize result in iOS (#15427) [backport:1.2] 2020-09-29 16:55:53 +02:00
Timothee Cour
5f9b366180 document that items no longer works with enum with holes (#15426) 2020-09-29 07:54:17 +02:00
Andreas Rumpf
50b6f6996a .noalias annotation; frontend support (#15419)
* .noalias annotation; frontend support

* added .noalias support to Nim; implements https://github.com/nim-lang/RFCs/issues/204
2020-09-28 13:51:39 +02:00
Andreas Rumpf
453167a41e cleanup lib/system/stacktraces.nim; refs #15416 (#15418) 2020-09-28 10:51:13 +02:00
Andreas Rumpf
f1ac01459c produce runtime type information for reified openArrays (#15415)
* produce runtime type information for reified openArrays

* added a test case
2020-09-27 20:44:22 +02:00
hlaaftana
0ea559611d Fix proc generic params ident defs, missing empty (#15412) 2020-09-27 19:47:58 +02:00
Andreas Rumpf
57b7841c18 better support for slices as views (#15414)
* moved view tests to tests/views
* refactoring
* more refactorings
* better support for system.toOpenArray for first class view types
2020-09-27 09:20:10 +02:00
Andreas Rumpf
e6616115e6 cursor inference: makes combparser work; refactorings (#15411)
* cursor inference: makes combparser work; refactorings
2020-09-26 13:11:35 +02:00
alaviss
d4892e9388 koch, compiler: bundle fusion as part of the source archive (#15409)
This allows distributions to build Nim from the downloaded source
archive without an Internet connection.
2020-09-26 09:31:55 +02:00
Miran
2de6e18774 fix #11537, correct parse inline code without surrounding spaces (#15399) 2020-09-25 09:25:47 +02:00
Andreas Rumpf
e9fa486493 fixes #14983 (#15320)
* fixes #14983

* allow bootstrapping with 0.20

* added a test case for the new system.add with a sink parameter

* make npeg green again
2020-09-25 08:49:21 +02:00
cooldome
68ec7a018b Revert "fix #15035 (#15236)" (#15408)
This reverts commit f8c48fc186.
2020-09-24 22:21:14 +02:00
Andreas Rumpf
e3b5f80a89 more precise borrow checking of 'result' (#15406) 2020-09-24 22:07:23 +02:00
Andreas Rumpf
ce72d7ffc5 fixes #15403 (#15404) 2020-09-24 19:34:59 +02:00
Miran
496e9f74e1 fix #14474, crash inside of a sole code-block (#15402) 2020-09-24 16:41:08 +02:00
Andreas Rumpf
4ec5cbac0d fixes #15361 (#15401)
* fixes #15361; better cursor inference
2020-09-24 15:41:45 +02:00
flywind
8a6c5edc43 use release version (#15400) 2020-09-24 14:14:23 +02:00
flywind
e85c5ad379 fix #15333 (#15336) 2020-09-24 08:54:13 +02:00
genotrance
7a6f4eca19 Bump nimble (#15398) 2020-09-24 08:07:32 +02:00
cooldome
f21a49b2c4 Fix #15389 (#15390)
* allow result symbol reuse

* try different approach

* Revert "try different approach"

This reverts commit abcfb6b759.
2020-09-24 00:07:30 +01:00
Miran
fe3211fbcf fix the indentation in --help and --fullhelp (#15387)
* fix the indentation in `--help` and `--fullhelp`

* a better way to fix it
2020-09-23 12:44:41 +02:00
Araq
94c8d53a03 'koch temp' bugfix 2020-09-23 10:41:33 +02:00
Andreas Rumpf
e2d80b15a6 finish the stacktraces.nim implementation [backport:1.2] (#15393) 2020-09-23 10:01:52 +02:00
Clyybber
4b9eea2fcc Fix forward declarations in shadow scope contexts (#15386)
* Fix forward declarations in shadow scope contexts

* Add testcase for #15385

* Less empty lines

* Fix tests

* Inline isShadowScope

* Add original testcase (with reduced amount of iterations)

* Add testcase without forward decl
2020-09-22 18:24:13 +02:00
Miran
11c377c114 add enumerate macro (#15297)
* add `enumerate` macro

* address the comments

* put `enumerate` in its own module
2020-09-22 13:08:36 +02:00
flywind
ab05e141c0 deinitLock (#15383)
* deinitLock

* minor
2020-09-22 13:07:31 +02:00
Andreas Rumpf
1fae66e4df better nativestacktrace support; refs #15284; backport [1.2] (#15384)
* nimStackTraceOverride: enable stack traces in exceptions

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

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

* cleaned up PR #15284

Co-authored-by: Ștefan Talpalaru <stefantalpalaru@yahoo.com>
2020-09-22 13:03:24 +02:00
Clyybber
d67c5cb751 Add strutils.indentation and make unindent use it (#15264)
* Add strutils.indentation and make unindent use it

* Code style

* Fix bootstrapping

* Improve wording

* Fix test

* Introduce without breaking change

* Fix

* Reduce diff

* Fix docs link

* Add since annotation

* Update changelog
2020-09-22 10:43:12 +02:00
alaviss
aca9c5fb30 os: make getApplFreebsd available for NetBSD (#15381)
NetBSD was switched to getApplFreebsd() in #15359, however the proc was
not made available for the said target.

This commit exposes `getApplFreebsd()` to NetBSD.
2020-09-21 19:52:44 +02:00
genotrance
8f511fd0e6 Bump nimble (#15380) 2020-09-21 11:48:00 -05:00
Miran
4645183272 fix #6430, support :target: for images (#15379) 2020-09-21 17:01:12 +02:00
flywind
40a868bccc add testcase for #6060 (#15366)
* add testcase for #6060

* Remove overspecific testament spec

Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-09-21 13:37:14 +02:00
flywind
6c83eb48c2 add testcase for #7165 (#15368)
* add testcase for #7165

* Remove overspecific testament spec

Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-09-21 13:32:05 +02:00
Juan Carlos
db9ab2a4c0 Documentation prelude (#15377) 2020-09-21 12:37:14 +02:00
Andreas Rumpf
c2434d939e fixes #15360 [backport:1.2] (#15378) 2020-09-21 12:35:23 +02:00
flywind
0a1e4cad7f add testcase for #9710 (#15365)
* string is not nil anymore

* tatus
2020-09-21 12:21:05 +02:00
Andreas Rumpf
4d75059e8b added a basic ORC test I still had lying around (#15376) 2020-09-20 22:47:48 +02:00
Andreas Rumpf
04cecdf9c2 async: removed the 'unown' references, async never worked with --newruntime anyway and --newruntime is dead (#15374) 2020-09-20 18:01:07 +02:00
Araq
cdac67376c arc: added tmarshal.nim test case 2020-09-20 10:43:57 +02:00
Araq
33be7c6f5e arc: =deepcopy fixes 2020-09-20 10:43:57 +02:00
Andreas Rumpf
ebb632ccba fixes #15369 (#15371) 2020-09-20 01:07:13 +02:00
Andreas Rumpf
a15d77df7e ORC/ARC async progress (#15370)
* ARC/ORC: fixes memory leak for empty seqs that have a non-zero capacity

* async: minor refactorings

* it helps to finish a refactoring
2020-09-20 00:27:32 +02:00
Andreas Rumpf
cbdda631db base64: fixes the error message for an invalid base64 input character [backport:1.2] 2020-09-20 00:05:41 +02:00
Andreas Rumpf
9a34009f00 ORC and stdlib optimizations (#15362) 2020-09-19 00:27:43 +02:00
Timothee Cour
8ae4a774b7 doc fix typo in lib/pure/httpclient.nim (#15364) 2020-09-19 00:20:41 +02:00
Euan
ae1f5c1559 Use sysctl on NetBSD to get exe name (#15359) 2020-09-18 22:26:53 +02:00
yatsen1
341cd844b2 fix coro proc crash for stack problem when run long enough than a GC cycle (#7612) (#11410)
Co-authored-by: drswinghead <drswinghead@gmail.com>
Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-09-18 17:17:09 +02:00
Andreas Rumpf
d19316bbb9 more ORC bugfixes (#15355)
* introduced --define:nimArcIds

* ORC: bugfixes
2020-09-18 11:55:58 +02:00
narimiran
59b7857167 bump NimVersion to 1.3.7 2020-09-18 11:50:15 +02:00
Andreas Rumpf
2671efab78 async: minor refactorings (#15354) 2020-09-18 11:22:34 +02:00
jcosborn
e56d50d747 fix infinite recursion in typeRel (#15241)
* fix generic constraints

Co-authored-by: James Osborn <osborn@Jamess-MacBook-Pro.local>
2020-09-18 11:21:37 +02:00
flywind
c57023f324 string is not nil anymore (#15352) 2020-09-18 10:02:31 +02:00
Miran
cbd78ec1f6 close #6071, remove the mentions of deprecated docSeeSrcUrl (#15350) 2020-09-17 19:55:18 +02:00
Andreas Rumpf
bc9967f05a Revert "Introduce explicit copy (#15330)" (#15346)
This reverts commit a3e9cc5234.
2020-09-16 23:24:17 +02:00
cooldome
d938c6411e fix #15326 (#15341) 2020-09-16 21:37:23 +02:00
Juan Carlos
913ffbb92d Add documentation for Testament (#15344) 2020-09-16 21:31:35 +02:00
Yuriy Glukhov
28a64869f0 Fixed undeclared nimIdentNormalize compilation error in parseEnum (#15343) 2020-09-16 19:41:57 +02:00
Andreas Rumpf
8b66412a8b fixes #9754 [backport] (#15342) 2020-09-16 19:41:14 +02:00
cooldome
341be0b61c proc params as syms (#15332)
* proc params are now syms

* Fix typesrenderer

* Add testcase for disrupteks issue

* fix test

* Trigger build

* Trigger build

* Trigger build

Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-09-16 17:25:24 +01:00
cooldome
a3e9cc5234 Introduce explicit copy (#15330) 2020-09-16 17:26:45 +02:00
Andreas Rumpf
ae4ede6b00 fixes #15325 (#15340) 2020-09-16 17:26:13 +02:00
flywind
de7f2372be docs minor and #15335 (#15337) 2020-09-16 14:58:50 +02:00
Andreas Rumpf
fd31e8ff6f allow old styled RTTI for arc/orc (#15331) 2020-09-16 14:57:01 +02:00
flywind
0aaf4e2dfa Methods docs improvement (#15338)
* docs improvement

* minor
2020-09-16 14:51:01 +02:00
Andreas Rumpf
bc179ccc3f fixes #15076 (#15329) 2020-09-15 12:40:23 +02:00
Juan Carlos
073bea6606 Remove Deprecated {.this:self.} from Documentation so people dont use it anymore (#15328) 2020-09-15 11:59:33 +02:00
Andreas Rumpf
c38487aa22 fixes a critical ORC bug, refs #15076 (#15323) 2020-09-14 12:50:23 +02:00
flywind
e111b610ca test cookies with comma for #15319 (#15322)
* test cookies with comma for #15319

* space
2020-09-14 12:20:42 +02:00
flywind
366216da64 fix cookie with comma (#15319) 2020-09-14 09:00:29 +02:00
Juan Carlos
a667475aaf dom.Navigator add missing attributes (#15310)
* Add missing attributes and methods to dom.Navigator

* Add missing attributes and methods to dom.Navigator

* Add missing attributes and methods to dom.Navigator
2020-09-14 08:58:21 +02:00
Jaremy Creechley
6c49767a6c Fixing issue #15302 -- lwip doesn't support signals (#15303)
* Fixing issue #15302 -- lwip doesn't support signals

* Adding test to catch issue #15302 -- lwip/freertos net library
don't try to build / run on windows, it'll compile only but not run

Fixing issue #15302 -- reworking test to compile on other platforms
2020-09-14 08:57:49 +02:00
Andreas Rumpf
1df5cfba52 fixes #15147 (#15315) 2020-09-12 23:11:38 +02:00
Clyybber
60ad95f799 Add testcase for invalid if statement (#15313) 2020-09-12 14:28:19 +02:00
Clyybber
1881fc5812 Fix #15305 (#15311)
* Fix #15305

* Fix test
2020-09-12 12:39:46 +01:00
flywind
a41b243fea remove annoying messages when creating orderedTables (#15309)
* nativesockets docs minor [backport: 1.2]

* remove annoying messages
2020-09-12 10:34:11 +02:00
narimiran
5f08d39398 fix broken links in the documentation 2020-09-12 09:22:14 +02:00
genotrance
f1f694dccb Bump nimble (#15304) 2020-09-11 11:57:54 -05:00
Araq
9e4920c068 fixes #15021 2020-09-11 14:21:09 +02:00
Juan Carlos
c4e03b540e Fix #15183 (#15300) 2020-09-11 08:57:57 +02:00
Andreas Rumpf
0c41ac792b fixes #15122 (#15301) 2020-09-11 01:50:42 +02:00
Miran
6a621b35e7 fix warnings for deprecated low and high (#15291) 2020-09-11 01:04:07 +02:00
hlaaftana
625edf6a98 Add /lib/fusion to gitignore (#15295) 2020-09-11 00:43:10 +02:00
Juan Carlos
b03d221d0b Improve prelude so it does not hijacks documentation when used (#15299) 2020-09-11 00:25:09 +02:00
Andreas Rumpf
9a110047cb testament improvement: allow inline error messages inside test cases (#15294)
* testament support for inline error messages
* adapt teffects1.nim test to show the potential
2020-09-10 16:30:20 +02:00
cooldome
61c85e034d Fix #15286 (#15292)
* fix #15286

* fix spacing
2020-09-10 12:40:39 +02:00
Andreas Rumpf
3f00a738db fixes #15280 [backport:1.2] (#15281)
* fixes #15280 [backport:1.2]

* make tests green again

* adapt tests
2020-09-09 14:20:10 +02:00
Andreas Rumpf
217675cf84 borrow checking refinements (#15290)
* added basic borrowing test
2020-09-09 14:19:22 +02:00
Ivan Bobev
ccd77b42af Add some enhancements to jsonutils.nim (#15133)
* Add some enhancements to `jsonutils.nim`

* Use `jsonutils.nim` hookable API to add a possibility to deserialize
  JSON arrays directly to `HashSet` and `OrderedSet` types and
  respectively to serialize those types to JSON arrays.

* Also add a possibility to deserialize JSON `null` objects to Nim
  option objects and respectively to serialize Nim option object to JSON
  object if some or to JSON `null` object if none.

* Move serialization/deserialization functionality for `Table` and
  `OrderedTable` types from `jsonutils.nim` to `tables.nim` via the
  hookable API.

* Add object `jsonutils.Joptions` and parameter from its type to
  `jsonutils.fromJson` procedure to control whether to allow
  deserializing JSON objects to Nim objects when the JSON has some
  extra or missing keys.

* Add unit tests for the added functionalities to `tjsonutils.nim`.

* improve fromJsonFields

* Add changelog entry for the jsonutils enhancements

* Add TODO in `jsonutils.nim`

* Added an entry to "Future directions" section in `jsonutils.nim` as
  suggestion for future support of serialization and de-serialization of
  nested variant objects.

* Added currently disabled test case in `tjsonutils.nim` for testing
  serialization and de-serialization of nested variant objects.

* Move JSON hooks to `jsonutils.nim`

Move `fromJsonHook` and `toJsonHook` procedures for different types to
`jsonutils.nim` module to avoid a dependency of collections modules to
the `json.nim` module.

The hooks are removed from the following modules:

  * `tables.nim`

  * `sets.nim`

  * `options.nim`

  * `strtabs.nim`

* Add some tests about `StringTableRef`

Add tests for `StringTableRef`'s `fromJsonHook` and `toJsonHook` to
`tjsonutils.nim`.

* Disable a warning in `jsonutils.nim`

Mark `fun` template in `jsonutils` module with `{.used.}` pragma in
order to disable `[XDeclaredButNotUsed]` hint. The template is actually
used by the `initCaseObject` macro in the same module.

Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>
2020-09-09 14:18:59 +02:00
narimiran
8a2cd7b24b [ci skip] fix typo in the manual 2020-09-09 12:59:14 +02:00
flywind
8c82144ba5 add getprotobyname (#15273)
* add getprotobyname

* tests, docs, changelog

* add since
2020-09-09 12:47:22 +02:00
Miran
7d4f0df107 deprecate high(value) and low(value) (#15283) 2020-09-09 12:43:04 +02:00
Clyybber
f3552b86c1 Better semiStmtList parsing (#15123)
* Better semiStmtList parsing
* Add examples from forums and wiki
* Move parseIfExpr near parseIfOrWhen
* Update grammar
2020-09-09 07:36:31 +02:00
Andreas Rumpf
10988d4840 borrow checking (#15282)
* refactoring: move procs to typeallowed.nim
* frontend preparations for first class openArray support
* prepare the code generator for first class openArray
* code generation for first class openArray; WIP
* code generation for open arrays, progress
* added isViewType proc
* preparations for borrow checking
* added borrow checking to the front end
2020-09-09 07:32:03 +02:00
Miran
c49b88163c "for-loop macros" are no longer an experimental feature (#15288) 2020-09-08 14:25:25 +02:00
flywind
a81610230d nativesockets docs minor [backport: 1.2] (#15285) 2020-09-08 11:27:43 +02:00
Scott Wadden
098a8a7c52 nimeval errorHook support (#15255) 2020-09-07 20:05:07 +02:00
Andy Davidoff
0b74d26d0c don't raise index defects on malformed ast (#15278)
* don't raise index defects on malformed ast

* style
2020-09-07 20:04:07 +02:00
flywind
e08b802d79 more Protocol supports in windows (#15274) [backport:1.2] 2020-09-07 12:10:20 +02:00
Andreas Rumpf
2f6d04fd5d strict funcs: use control flow information for a more precise analysis (#15271)
* strict funcs: use control flow information for a more precise analysis

* cursor inference uses control flow information
2020-09-06 22:01:39 +02:00
genotrance
072c655653 Bump nimble (#15272) 2020-09-06 07:05:35 +02:00
shirleyquirk
57f98dae9a Fix c_malloc inside syslocks.nim to take size_t (#15268) [backport]
* update c_malloc's to csize_t
2020-09-05 23:00:59 +02:00
Clyybber
35ff17410f Expand hoisted default params in sem (#15270)
* Expand hoisted default params in sem
Introduce ast.newTree{I,IT}
Add test for default params in procs

* Cleanup

* Simplify hoist transformation and expand test
2020-09-05 22:01:47 +02:00
IDF
70d6238756 Add SSL_CTX_set_session_id_context (#15233)
* Added SSL_CTX_set_session_id_context()

* Added basic nimdoc

* Raise an error if sessionIdContext is longer than the maximum length

* Update nimdocs
2020-09-04 22:27:51 +01:00
Bung
c16ee37a71 Fix #15219 SQL escape in db_mysql is not enough (#15234) 2020-09-04 11:04:27 +02:00
cooldome
77df02313d fix #15238 (#15262)
* fix_15238

* fix test
2020-09-04 10:26:14 +02:00
Miran
4fb17bc03b fix #15257, toHex couldn't handle large uint64 (#15261) [backport:1.2] 2020-09-04 09:23:27 +02:00
Andreas Rumpf
48f2997221 fixes system.add for strict funcs (#15259)
* fixes system.add for strict funcs

* fixes #15248
2020-09-03 12:59:34 +02:00
Silvio
3172ca5475 replace / with _ in trId (#15256)
Fixes jquery error when clicking to collapse/expand a panel
2020-09-02 20:53:02 +02:00
PMunch
244760197c Fix sets for architectures with default integers smaller than 32 bits (#15258) [backport] 2020-09-02 10:07:08 +02:00
Andreas Rumpf
ff13f8cc3c fixes #15210 [backport:1.2] (#15237)
* fixes #15210 [backport:1.2]

* use patched version of bigints library
2020-08-31 14:46:23 +02:00
Jaremy Creechley
a76ae8f795 Changes for FreeRTOS/LwIP Port for the ESP32 (ESP-IDF) (#15250)
* Changes for FreeRTOS/LwIP Port for the ESP32 (ESP-IDF)

Adding FreeRTOS/LwIP to compiler:

* adding freertos option
* dyncalls for freertos
* add freertos to posix os list
* adding lwip option

Setting up networking FreeRTOS/LwIP Port:

* setting up lwip network for freertos
* fixing posix / networking for freertos
* disable setInheritable for freerots
* using lwip for net control items

* Fix builds by ignoring lib/posix/posix_freertos_consts.nim similar to lib/posix/posix_other_consts.nim
2020-08-31 11:48:54 +02:00
Andy Davidoff
b5424b826e template hygiene (#15240) 2020-08-29 08:06:11 -04:00
Clyybber
13e659cfec Big compiler Cleanup (#14777) 2020-08-28 22:18:09 +02:00
cooldome
f8c48fc186 fix #15035 (#15236) 2020-08-28 17:57:52 +02:00
Clyybber
fb58066b61 Fix #5691 (#15158)
* Fix #5691
* Cleanup and thoughts
* Use scope approach
* Seperate defined/declared/declaredInScope magics
* Fix declaredInScope
* Update spec accordingly
2020-08-27 15:50:59 +02:00
jcosborn
d11933ad99 fix some issues overloading with generics and inheritance (#15211)
* fix some issues overloading with generics and inheritance

* fix passing procs with subtype matches
2020-08-27 12:56:38 +02:00
Andreas Rumpf
ccccd30cf6 fixes #15221 (#15230) 2020-08-27 11:25:20 +02:00
Scott Wadden
a9a9860b0b Raise KeyError if passed an invalid row entry (#15227) 2020-08-26 20:00:54 +02:00
Juan Carlos
d85015e922 Remove unroll pragma from stdlib (#14706) 2020-08-26 16:51:41 +02:00
Araq
40969296e9 fixes #15207 [backport:1.2] 2020-08-26 15:27:15 +02:00
Araq
71025b8a8f deleted dead code, writetracking.nim was replaced by varpartitions.nim 2020-08-26 15:27:15 +02:00
Miran
5163fe7d87 remove deprecation from math.round (#15224) 2020-08-25 15:59:42 +02:00
Bung
7cee63bba3 avoid #8231, bitwise move to mul,div (#15070)
* avoid #8231, bitwise move to mul,div

* add test for #8231

* fix bitwise move when div result is float

* bitwise move depends on typ.size
2020-08-25 09:58:32 +02:00
Miran
15ff89cec1 [backport] fix #15064, strscans.scanf edge case for '$+' (#15223) 2020-08-25 09:57:15 +02:00
narimiran
5651a2f711 PRs with no activity in last year are marked as stale 2020-08-24 13:44:19 +02:00
Jon
8321617a78 fix in doc: incomplete output (#15222) [ci skip] 2020-08-24 08:33:51 +02:00
Mamy Ratsimbazafy
07d82b5cc4 Use more lent in options (#15208) 2020-08-24 08:05:17 +02:00
alaviss
575697e1f4 doc/nimdoc.css: align field names to the right (#15217) 2020-08-23 09:48:37 +02:00
wltsmrz
9bae1ed205 Unsigned iovlen (#15216) 2020-08-22 23:14:50 +02:00
John Dupuy
66eba3388a Added more SSL documentation to net module. (#15206)
* Added more SSL documentation to `net` module.

* Changed two of the net.nim doc refs to links.

* Update lib/pure/net.nim doc wording.

Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>

* Update lib/pure/net.nim - added space to doc URI

Co-authored-by: alaviss <leorize+oss@disroot.org>

* Fixed another doc URI in net module.

* For net module doc added warning to connect procedure.

* Update net.nim

Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>
Co-authored-by: alaviss <leorize+oss@disroot.org>
2020-08-22 11:00:38 +01:00
Elijah Shaw-Rutschman
8a004e2fc0 Add test coverage for atomics (#15193)
* Add test coverage for atomics

Signed-off-by: Elijah Shaw-Rutschman <elijahr@gmail.com>

* Fix compareExchange bugs for non-trivial objects

Bugs fixed:

1. compareExchange would not set the desired value in the success case.
2. compareExchange would not set var expected to the found value in the failure case.
3. withLock would spin forever running the unit tests. try..body..finally prevents this. Not sure why this makes a difference, since an exception wasn’t being raised, but clearing the guard in a finally block seems correct anyways.

Signed-off-by: Elijah Shaw-Rutschman <elijahr@gmail.com>
2020-08-18 18:02:10 +02:00
Andreas Rumpf
ddff13f01b better strict funcs, WIP (#15199)
* better strict funcs, WIP

* progress
2020-08-18 12:45:22 +02:00
jcosborn
e194cb41a4 fix overloading issue with generic invocation (#15135)
* fix overloading issue with generic alias

* add test for inheritance depth
2020-08-18 08:23:19 +02:00
alaviss
e9df8ebcfd gc_regions: cleanup & fixes for deallocation (#11920)
* gc_regions: withRegion nows return the modified MemRegion

* gc_regions: make withScratchRegion dealloc correctly

* tests/gc: add tregionleak test

This test checks if memory within regions are freed properly.
2020-08-17 20:20:48 +02:00
Andreas Rumpf
6feb3900b1 fixes #15177, the error message is now what it should have been (#15195) 2020-08-17 14:32:52 +02:00
Bung
cd28fe2ef7 add openssl missing procs (#15180) 2020-08-17 10:54:34 +02:00
narimiran
39906c52c4 stale bot is now active only for pull requests 2020-08-17 09:11:33 +02:00
Juan Carlos
c9fdad2c21 db_postgres document how to use it with unix socket (#15187) 2020-08-17 08:39:58 +02:00
slangmgh
ba042af9cc std/with support field assign (#14484)
* std/with support filed assign

* add changelog

* add support x.dup.with

* add example

* revert support x.dup.with; add example

* update changelog; fix assignment in parameter

* Update changelog.md

* add example for assignment in parameter

* Remove colon style assign

Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-08-15 01:33:21 +02:00
alaviss
957bf15a08 asyncnet: don't try to close the socket again [backport] (#15174)
The closed flag isn't a good design by any means, but let's have this
working first before I get rid of the flag and potentially create a
non-backportable commit.
2020-08-12 08:04:54 +02:00
Cléber Zavadniak
ce2da87eca Fix typo on CoroutineRef* doc (#15179)
Just a small fix for a typo ("for for").
2020-08-12 04:46:16 +02:00
Clyybber
2cea52ee7e Allow pragmas on parameters (#15178) 2020-08-11 22:28:49 +02:00
Andreas Rumpf
813f16a2a3 Fix #8473 (#15169)
* Make explicit {.nimcall.} a seperate calling convention

* Add testcase for #5688

* Fix bootstrapping

* Remove little lies :)

* Use typeflag instead
2020-08-11 14:50:46 +02:00
Silvio
963db9e7da docs: dlimport -> dynlib (#15175) 2020-08-11 14:49:57 +02:00
Ico Doornekamp
2260ede247 Added array type definition to manual (#15173)
Co-authored-by: Ico Doornekamp <git@zevv.nl>
2020-08-10 14:01:47 +02:00
Clyybber
b022576ce9 Use typeflag instead 2020-08-10 12:57:32 +02:00
haxscramper
e5dbdc1d37 [FIX] strtabs interpolation in nimscript (#15172)
* [FIX] strtabs interpolation in nimscript

* [TEST] Use `static` in strtabs test
2020-08-09 14:12:53 +02:00
Andreas Rumpf
2a8bf470af fixes #15101 [backport] (#15171) 2020-08-08 23:08:34 +02:00
Clyybber
26a867c83c Remove little lies :) 2020-08-08 13:22:53 +02:00
Clyybber
2a8d010742 Fix bootstrapping 2020-08-08 12:50:06 +02:00
Clyybber
78b2012a92 Add testcase for #5688 2020-08-08 12:45:07 +02:00
Clyybber
38068f9778 Make explicit {.nimcall.} a seperate calling convention 2020-08-08 12:36:20 +02:00
c-blake
0bc8dd0b00 Add iterator inotify_events which is *almost always* needed logic for (#15152)
client code since Linux `inotify` is much like Linux `getdents64`.

Expanding on "almost always"..The only time that this `iterator` logic
is ***not*** needed on the output of a `read` from inotify fd's is when
one passes a length to `read` *guaranteed* to only pass one event struct
in the buffer.  That unusual circumstance requires (at least!) knowing
the length of the delivered filename before an event occurs, and the
filename itself is optional for some event types.

It is *far* more common to not know lengths in advance which means one
passes a buffer big enough for at least one maximum length directory
entry (256 bytes) which is then also big enough for *many* "typical"
length entries and therefore many events.  In such more common scenarios
this iterator logic is definitely needed.

Further, not using this logic, yet treating the return from read as "the
whole answer" can test ok on "thin" event streams (e.g. 1 event per ms),
hiding a latent bug of processing only the first event.
2020-08-08 07:26:20 +02:00
flywind
eee3b189ff fix #15148 (#15149)
* fix #15148

Co-authored-by: alaviss <leorize+oss@disroot.org>
2020-08-08 07:24:54 +02:00
ee7
6f482ab934 deques.nim: Refactor the toDeque functionality (#15166)
This commit polishes the new proc introduced by d9ed816b10.

Changes:
- Rename to `toDeque` for more consistency with well-known procs like
  `toHashSet` and `toTable`.
- Rename the `openArray` parameter. The name `arr` was potentially less
  clear given that the proc can be used with a seq (or string).
- Add a `since` annotation.
- Reword the doc comment, and clarify that ordering is preserved.
- Add runnableExamples.
- Add "see also" cross linking between `initDeque` and `toDeque`.
- Remove duplicate `nextPowerOfTwo`. The `initImpl` template already
  includes it.
- Implement the proc using the `items` iterator, rather than indexing.
  This matches the implementation of `sets.toHashSet` and
  `tables.toTable`.
- Add a test within `when isMainModule`.
- Add a changelog entry.
2020-08-07 22:54:34 +02:00
cooldome
a528382e05 fix sqlgetdata regression in odbc (#15161)
* fix sqlgetdata import

* fix db_odbc

* more fixes

* fix style
2020-08-07 22:37:54 +02:00
archnim
d9ed816b10 Added the ability to initialize a deque with an openArray (#15138)
* Add ability to initialize a deque with a sequence

Example:
var dq = initDeque[char](@['a', 'b', 'c'])

* Update deques.nim

* Optimized deque initialization

* Sequence replaced by open array in deque initialization
2020-08-05 12:41:42 -04:00
cooldome
ef6358f0b0 implement (#15153) 2020-08-04 19:22:35 +02:00
narimiran
eb3ba0ae5f limit stalebot a bit more 2020-08-04 13:00:09 +02:00
Andreas Rumpf
64aec6eb85 fixes a collect() bug reported on the forum (#15156) [backport:1.2] 2020-08-04 12:45:15 +02:00
flywind
2d494f42f3 minor improvement (#15155) 2020-08-04 11:29:57 +02:00
narimiran
836660a297 put stale limit at 3 years
It needs to be slowly brought down to limit the notifications
and prevent excessive spamming.
2020-08-04 11:00:04 +02:00
narimiran
e4710f893e stalebot: don't send messages to keep spam down 2020-08-04 10:47:16 +02:00
narimiran
9b08c7b375 add stale bot 2020-08-04 09:03:20 +02:00
Andreas Rumpf
d6161e7e9e fixes #15129 [backport:1.2] (#15144) 2020-08-01 22:03:15 +02:00
sschwarzer
98eb8410f2 Remove noSideEffect pragmas (#15143)
These don't seem to make sense for the purpose of the procs and lead
to errors when the `--experimental:strictFuncs` feature is enabled.

See also https://github.com/nim-lang/Nim/issues/15142
2020-08-01 22:00:25 +02:00
alaviss
c619cedd7c net: allow close() to ignore SSL failures due to disconnections (#15120)
* net: allow close() to ignore SSL failures due to disconnections

Comes with this PR is also a SIGPIPE handling contraption.

* net: don't do selectSigpipe() on macOS

macOS sockets have SO_NOSIGPIPE set, so an EPIPE doesn't necessary mean
that a SIGPIPE happened.

* net: fix alreadyBlocked logic

* net: WSAESHUTDOWN is also a disconnection error
2020-08-01 21:27:55 +02:00
flywind
3ce32a7e40 export asyncdispatch handles (#15140)
* improve epoll docs

* export handles

* add comments and changelog
2020-08-01 21:27:21 +02:00
Andreas Rumpf
8e3f51f06c fixes #15130 (#15141)
* fixes #15130

* you really have to copy from cursors
2020-08-01 18:04:04 +02:00
Andreas Rumpf
9ff2c50155 fixes #15122 [backport:1.2] (#15139) 2020-08-01 13:16:50 +02:00
alaviss
e192e07bf0 ci_docs: build fusion docs (#15127) 2020-08-01 11:33:19 +02:00
flywind
a7736b6b43 improve epoll docs (#15137) 2020-08-01 11:30:51 +02:00
Andreas Rumpf
4ab6887a67 fixes #15111 (#15136) 2020-08-01 07:39:00 +02:00
Andreas Rumpf
6b88cd0d42 Revert "Small typo (#15132)" (#15134)
This reverts commit 4bf8d38248.
2020-07-31 20:27:58 +02:00
Oliver Daniel
4bf8d38248 Small typo (#15132)
The expected output necessarily cannot match the formatted string.
2020-07-31 16:35:50 +02:00
Andreas Rumpf
d23ae49535 fixes #15071 [backport] (#15131) 2020-07-31 12:13:33 +02:00
genotrance
f1971243d3 Bump nimble (#15126) 2020-07-30 13:13:34 -05:00
Andreas Rumpf
355b275175 fixes #15112 (#15124) 2020-07-30 19:19:59 +02:00
Andreas Rumpf
d130175342 cursor and mutation tracking fixes (#15113)
* fixes #15110
* fixes #15096

* prepare varpartitions for cursor inference
* new cursor inference begins to work
* make tests green
2020-07-30 17:32:48 +02:00
jcosborn
32c6146200 fix overloading case with generic alias (#15116)
* fix overloading case with generic alias

* revert reorganization of tests
2020-07-30 15:34:11 +02:00
treeform
604f7461d7 Fix tables.CountTable largest and smallest (#15115)
It needs to have len defined first because of the assert .len > 0.  I just moved it up a bit to make them work.
2020-07-29 23:49:51 -04:00
alaviss
20315637aa asyncnet, net: don't attempt SSL_shutdown if a fatal error occurred (#15066)
* asyncnet, net: don't attempt SSL_shutdown if a fatal error occurred

Per TLS standard and SSL_shutdown(3ssl). This should prevent errors
coming from a close() after a bad event (ie. the other end of the pipe
is closed before shutdown can be negotiated).

Ref #9867

* tssl: try sending until an error occur

* tssl: cleanup

* tssl: actually run the test

I forgot to make the test run :P

* tssl: run the test on ARC, maybe then it'll be happy

* tssl: turns off ARC, switch tlsEmulation on for freebsd

* tssl: document why tlsEmulation is employed

* net: move SafeDisconn handling logic to socketError
2020-07-30 00:35:02 +02:00
genotrance
0788a7f970 Bump nimble (#15114) 2020-07-29 15:42:08 -05:00
flywind
c645dba038 fixes #14139 (#15107)
* fix #14139
* Update lib/pure/collections/heapqueue.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-07-29 16:18:27 +02:00
Clyybber
2629d619a1 Fix forward declaration issues in template/macro context (#15091)
* Fix forward declaration issues in template/macro context

* Correct forward declaration resolving for overloads

* Remove old dead code

* WIP consistent gensym ids

* Minimize diff

* Remove obsoleted hack

* Add templInstCounter to give unique IDs to template instantiations

* Remove obsoleted code

* Eh, init in myOpen, not myProcess...

* Remove optNimV019

* Add testcase for #13484
2020-07-29 16:17:20 +02:00
c-blake
196e747df1 Attempt to explain better why delImplIdx is the way it is. Maybe this can (#15108)
avoid future implementation mischief.  (Maybe not.  Sometimes, general
distrust of theory leads people to distrust simple reasoning over times
from CPUs trying as hard as possible to mask DRAM latency via pre-fetch.)
2020-07-29 11:19:02 +02:00
Andreas Rumpf
a3a87cdb29 fixes #14616 [backport:1.2] (#15109) 2020-07-29 11:11:58 +02:00
c-blake
b2a1944587 Fulfill https://github.com/nim-lang/Nim/pull/14995#issuecomment-664914391 (#15104)
request.  This can be conceived as an alternate, more capable resolution of
  https://github.com/nim-lang/Nim/issues/12200
than
  https://github.com/nim-lang/Nim/pull/12208

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

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

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

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

The only user-visible changes from the +-42 delta here are speed, iteration
order post deletes, and relaxing the `Positive` constraint on `val` in
`proc inc` again, as indicated in the `changelog.md` entry.
2020-07-28 23:48:50 +02:00
Andreas Rumpf
86c9b78339 disable sink inference, only enable it for the stdlib. Reason: better source code compatibility (#15105) 2020-07-28 19:18:46 +02:00
Euan
e4e4931432 Change clibdir and cincludes for NetBSD (#15102) 2020-07-28 12:01:25 -04:00
Bung
e2b1491905 Fix #11352 strutil.insertSep() fails on negative numbers (#15087)
* fix #11352 strutil.insertSep handle negtive number

* test for #11352

* optimize

* not parts string var

* Update lib/pure/strutils.nim

Thanks!

Co-authored-by: alaviss <leorize+oss@disroot.org>

* need to be countdown

Co-authored-by: alaviss <leorize+oss@disroot.org>
2020-07-28 11:47:22 +02:00
Miran
39487f9728 deprecate tables.allValues; continuation of #15047 (#15092) 2020-07-28 11:40:56 +02:00
Andreas Rumpf
be78b35bb8 cleanup ARC documentation (#15100) 2020-07-28 11:34:44 +02:00
narimiran
a2f330569c yet another fusion fix 2020-07-28 10:57:24 +02:00
narimiran
75083979f9 another bump 2020-07-28 09:27:00 +02:00
narimiran
d6a0c35330 bump FusionStableCommit to the latest commit 2020-07-28 08:51:10 +02:00
Ray Imber
d60fae576f Improvements to Windows install instructions (#15099) 2020-07-28 02:04:04 -04:00
Andreas Rumpf
e6f0d4a5a5 fixes #15076 (#15095) 2020-07-27 23:27:20 +02:00
Timothee Cour
377f716766 fix #14698 nkRecWhen caused internalAssert in semConstructFields when generic type not mentioned in fields (#14709)
* fix #14698 nkRecWhen caused internalAssert in semConstructFields when generic type not mentioned in fields

* address comment

* Update compiler/semtypinst.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-07-27 22:32:21 +02:00
Bung
cac09a43ae fix #11354 jsgen not carefully handle genAddr with nkHiddenAddr,nkStm… (#15078)
* fix #11354 jsgen not carefully handle genAddr with nkHiddenAddr,nkStmtListExpr; genAsgn with lvalue tyVar and rvalue tyPtr

* correct logic

* add test for #11354

* handle nkHiddenAddr when n.len == 1

* Update compiler/jsgen.nim

* Update compiler/jsgen.nim

* Apply suggestions from code review

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-07-27 21:13:49 +02:00
Bung
191c388792 fixes #14189 (#15080) [backport] 2020-07-27 14:06:54 +02:00
Araq
947ecd1257 more renamings 2020-07-27 13:07:09 +02:00
Araq
46bd6787b8 code cleanup 2020-07-27 13:07:09 +02:00
Araq
318f0992ea fixes a closure iterator memory leaks, progress on #15076 2020-07-27 13:07:09 +02:00
Danil Yarantsev
4c43915b59 Add test-cases for #12576 and #12523 (#15085)
* Add a test-case for #12576

* Add a test-case for #12523
2020-07-27 13:01:50 +02:00
alaviss
c292c57e48 Small optimization for the CI pipeline. (#15088)
* azure-pipelines: cache csources to speed up build

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

* azure-pipelines: remove ppa avoidance configs

Testing shows that there aren't any difference between having this and
not having it, so removing this to simplify the code.
2020-07-27 10:38:20 +02:00
Jjp137
a62bc55955 parsecsv: fix '\0' being displayed as '0' in docs (#15086) [backport] 2020-07-27 08:17:23 +02:00
Araq
a0049d1fb0 compiler: minor code cleanups 2020-07-27 08:05:52 +02:00
genotrance
c229df95a4 Bump nimble (#15077) 2020-07-26 08:44:14 +02:00
Andreas Rumpf
aae998feff fixes #15038 [backport:1.2] 2020-07-26 01:16:06 +02:00
Andreas Rumpf
624762cfb7 fixes #15052 2020-07-26 01:16:06 +02:00
Miran
5c4e2bf68e fix nightlies: smaller log files (#15074)
Hopefully this will fix
"The job exceeded the maximum log length, and has been terminated."
2020-07-25 22:56:37 +02:00
alaviss
33c2d7bfc4 koch: bundle nim-lang/fusion with Nim (#15061)
Initial work on bundling nim-lang/fusion as part of the Nim distribution.
2020-07-25 22:52:18 +02:00
Danil Yarantsev
080bed8b6b Add a test-case for #12990 (#15072)
* closes #12990
* Add a test-case for #12990
2020-07-25 20:35:20 +02:00
Andreas Rumpf
2aca748ddd strict func: much better error messages (#15068)
* strict func: much better error messages
* documented the 'strict funcs' mode
2020-07-25 19:36:53 +02:00
Andreas Rumpf
7ca32c86bb writing to a location counts as "side effect"; implements https://github.com/nim-lang/RFCs/issues/234 (#15030) 2020-07-25 15:14:28 +02:00
Miran
1330597f6d deprecate tables.add (#15047) 2020-07-25 09:53:47 +02:00
Bung
2dddf32726 fix #14684 (#15059) 2020-07-25 09:52:29 +02:00
Bung
9746868832 fix #14534 (#15060) [backport] 2020-07-25 09:51:59 +02:00
genotrance
8211d38569 Bump nimble commit (#15053) 2020-07-25 01:16:25 -05:00
jcosborn
add003a074 fix assignment to converted concept type (#15051)
* fix assignment to converted concept type

* check for resolved concepts

* add extra test
2020-07-24 21:19:11 +02:00
Miran
4b93c61f0d jsre: try to fix nightlies (#15057) 2020-07-24 21:15:20 +02:00
Araq
12a9fe017e fixes #15056 [backport] 2020-07-24 17:49:25 +02:00
Andreas Rumpf
18a70a7563 fixes #15036 2020-07-23 20:27:17 +02:00
Andreas Rumpf
c90c53e8bb fixes #15044 [backport:1.2] 2020-07-23 20:27:17 +02:00
Miran
14d16c2174 json.nim: smaller init size (#15048)
There was a recent `rightSize` change in tables.nim, so the existing
value (4) was creating too large tables.
2020-07-23 15:42:12 +02:00
Andreas Rumpf
925dd92e07 enforce browsers.nim only handles URLs [backport] (#15045) 2020-07-23 11:03:39 +02:00
Miran
ec65bfae3a Change testing commands for some packages (#15041) 2020-07-22 14:57:40 +02:00
Andreas Rumpf
d84894de2e fixes #15026 [backport] (#15040)
no test case since only a special case was affected and the special case got removed
2020-07-22 13:02:03 +02:00
Hugo Granström
32ac1b7c9d fix #15033 (#15034) 2020-07-22 10:30:46 +02:00
Danil Yarantsev
f25454d5c6 Add a testcase for #14480. Fixes #14480 (#15037) 2020-07-22 09:52:38 +02:00
Mildred Ki'Lya
503c5e0520 smtp: Fix STARTTLS, request HELO once TLS is established (#15032) 2020-07-22 00:30:33 -04:00
Andreas Rumpf
911e39351e ARC: optimize the code better when --panics:off (#15031) 2020-07-21 23:23:33 +02:00
Miran
5fafa2fd5c fix several newline problems (#15028) [backend]
* prevent newlines where they shouldn't be
* 'contentLength' shouldn't be negative
2020-07-21 22:49:08 +02:00
genotrance
450a3e3179 Fix #2408 - add -d:globalSymbols (#14904) 2020-07-21 19:14:36 +02:00
Bung
64d629c617 Shadow Dom apis (#14979)
* shadow dom api

* fix typos

* host to Element type

* fix code style

* move elementsFromPoint to dom_extensions.nim
2020-07-21 19:11:12 +02:00
Andreas Rumpf
c8a72e0748 Merge pull request #15027 from nim-lang/araq-cursor-fix
cursor inference bugfix
2020-07-21 07:33:37 +02:00
Andreas Rumpf
3a4e4cec4d cursor inference bugfix 2020-07-20 18:37:14 +02:00
Andreas Rumpf
80d3ef9952 hotfix: firstOrd/lastOrd for 'tyLent' as it shows up in strange places, as usual 2020-07-20 17:44:35 +02:00
Andreas Rumpf
70acba7f0d readLine: Unicode support for Windows console (#14782)
* readLine: Unicode support for Windows console

When input is read from the Windows console, input encoding is UTF16. This is translated internally to UTF8.

* readLine: Remove recursive imports

* readLine: Fix issues with --gc:arc

**--gc:arc** defines **nimv2**. This changes the definition of **WideCStringObj**.
Also an empty string should be returned in case of EOF.
2020-07-20 14:39:27 +02:00
Andreas Rumpf
49d4b50fe5 fixes #14194 (#15023) 2020-07-20 14:28:00 +02:00
alaviss
9a76398ec6 koch: use in-tree Nim to run test if possible (#15018)
Fixes #15013
2020-07-20 08:02:48 +02:00
Andreas Rumpf
71dd5f85b9 'isolate' builtin; refs https://github.com/nim-lang/RFCs/issues/244 (#15011) 2020-07-20 07:50:19 +02:00
alaviss
bb1adf6a70 io: fix SetHandleInformation signature to match Windows' (#15017)
* io: fix SetHandleInformation signature to match Windows'

Fixes #14980

* rename Handle -> IoHandle because system.nim is a mess
2020-07-20 00:17:33 -04:00
narimiran
b16284633e enable 'nimterop' test 2020-07-20 05:44:06 +02:00
Dominik Picheta
1e3a0ef1e1 [Backport] Fixes callbacks being dropped on Linux/macOS/BSD. (#15012)
Fixes #15003.

This is a serious bug which occurs when data cannot be read/sent
immediately and there are a bunch of other read/write events
pending. What happens is that the new events are dropped which
results in the case of the reported bug resulted in some data not
being sent (!).
2020-07-19 08:41:36 +02:00
Araq
ffe7b3a9bf threadpool.nim: minor code style changes 2020-07-18 21:40:57 +02:00
Andy Davidoff
ae358a0c7a fix docs for nativesocket read/write selects (#15010)
The sockets which *cannot* be _[read from or written to]_ will also be removed from ``readfds``.
2020-07-18 16:39:41 +02:00
Timothee Cour
169ca37d26 enable,document,test getImplTransformed, very useful for understanding how nim transforms code (#14924)
* enable,document,test getImplTransformed, very useful for understanding how nim transforms code
2020-07-18 10:49:36 +02:00
Tomohiro
c983466c15 Fix #14906 (#14949)
* Fix #14906 by wrapping outputStream with PipeOutStream

* Fix compile error when ./build_all.sh

* Use PipeOutStream on posix

* Fix compile error when build_all.sh

* Use ptr UncheckedArray

* Replace copyRefObj

* Remove tmp buffer from posPeekData

* Add more tests for outputStream

* Add comments about PipeOutStream.buffer

* Fix bug in posReadLine

* Move implementation of newPipeOutStream to streamwrapper module
2020-07-18 10:41:33 +02:00
cooldome
edbbbdf1a8 fix odbc regressions (#15009) [backport]
* fix odbc regressions

* make only necessary changes
2020-07-18 10:21:09 +02:00
Andreas Rumpf
d4984e069a arc: cursors for simple for loop variables (#15008)
* arc: cursors for simple for loop variables

* merged devel
2020-07-17 15:24:36 +02:00
Bung
c2f80de1c7 fix #14822 copy test into var in matrix process, so can reset startTime before actully run (#15000)
* TTest pass by ref , so can reset startTime before actully run

* change TTest to ref type

* clone test in matrix process
2020-07-17 11:01:47 +02:00
Miran
c62513049c fix #14082, don't crash on incorrectly formatted input (#14977) [backport]
* fix #14082, don't crash on incorrectly formatted input

* address code review

* remove duplication
2020-07-17 10:59:53 +02:00
Clyybber
1355b461aa Show that a variable is cursor in --expandArc (#15002) 2020-07-17 10:56:17 +02:00
flywind
9fb7467fda fix #15006 (#15007) 2020-07-17 10:53:26 +02:00
Andreas Rumpf
6b607413e9 cursor inference: hotfix (#14999) 2020-07-16 12:07:06 +02:00
Bung
ba5604b96d fix #13621, the nim-livereload is mentioned as proposal in #8927 (#14998) 2020-07-16 11:18:59 +02:00
Clyybber
282128ab66 Fix #14994 (#14996)
* Fix #14994

* Revert misplaced "optimization"

* Typo
2020-07-15 23:33:58 +02:00
Andreas Rumpf
617c1f16d7 disable debug output 2020-07-15 23:04:18 +02:00
Andreas Rumpf
c5358b0d4b An optimizer for ARC (#14962)
* WIP: an optimizer for ARC
* do not optimize away destructors in 'finally' if unstructured control flow is involved
* optimized the optimizer
* minor code cleanup
* first steps to .cursor inference
* cursor inference: big steps to a working solution
* baby steps
* better .cursor inference
* new feature: expandArc for easy inspection of the AST after ARC transformations
* added topt_cursor test
* adapt tests
* cleanups, make tests green
* optimize common traversal patterns
* moved test case
* fixes .cursor inference so that npeg compiles once again
* cursor inference: more bugfixes

Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-07-15 23:00:06 +02:00
Clyybber
813dd1b670 repr_v2 improvements (#14992)
* Support proc in arc repr

* Typo

* Improve repr for strings and chars
2020-07-15 22:04:15 +02:00
Clyybber
e057b1d839 Fix #14990 (#14991)
* Fix #14990

* Add testcase
2020-07-15 19:00:52 +02:00
Clyybber
08159733cd Fix #14985 (#14988) 2020-07-15 11:34:10 +02:00
flywind
c5f64f101b fix #13086 (#14987)
* fix #6608

* minor

* fix

* clean tests

* make testamnet happy

* again

* minor

* fix #13086
2020-07-15 03:46:17 -04:00
Clyybber
f2b041f168 Reenable a few tests 2020-07-14 19:50:42 +02:00
Clyybber
ddfb7d9877 Closes #10396 2020-07-14 19:50:42 +02:00
Clyybber
695a537c05 Closes #13253 2020-07-14 19:50:42 +02:00
Clyybber
03b0374e5c Closes #8426 2020-07-14 19:50:42 +02:00
Juan Carlos
9465b5db44 Clean up macros (#14959) 2020-07-14 16:44:56 +02:00
Clyybber
2b0e336c97 injectdestructors fixes and refactor (#14964)
* injectdestructors fixes and refactor

* Tiny cleanup

* Refactor and expand testcase

* Closes #14902 by adding testcase

* Better naming

* Fix test failures

* Misc cleanup

* Add testcase for #14968

* Better approach; expand testcases

* Optimizations and fixes

* Add testcase

* typo

* Tiny cleanup
2020-07-14 14:15:39 +02:00
Bung
f999f916f3 add missing props,procs (#14978) 2020-07-14 13:53:41 +02:00
Hendrik
9ed0dbfa6e fix index error (#14974)
Co-authored-by: Hendrik Albers <mail@hendrik.dev>
2020-07-14 13:15:22 +02:00
Timothee Cour
e07d661d16 fix #14475; unittest.require now works with nim c; require and check now works with -d:nodejs (#14676)
* fix #14475; make unittest work with -d:nodejs

* fixup

* fixup

* disable inim, delaunay which failed after unittest.require got fixed

* re-enable tests that have been fixed
2020-07-14 13:14:32 +02:00
jcosborn
ffaf4797be add full tests from #9463 (#14975) 2020-07-14 11:24:17 +02:00
flywind
086efac49b fix #6608 (#14963)
* fix #6608
2020-07-14 09:22:48 +02:00
Miran
f4f21c89e5 asyncftpclient.nim - don't assume a sufficiend line length (#14973) 2020-07-14 02:18:02 -04:00
Andreas Rumpf
6cc0061a72 optimize the new nimPrepareStrMutationV2 with inlining (#14969) 2020-07-12 16:50:56 +02:00
Alexander Wolfe
124feb2af8 nimpretty support for multiple files (#14890) 2020-07-12 16:07:31 +02:00
flywind
9ec9a31f46 Fix #12759 (#14967)
* add testcase for #5926

* fix #12759
2020-07-12 03:31:03 -04:00
Clyybber
d409694b02 :D 2020-07-11 19:17:40 +02:00
flywind
21772b6419 add testcase for #5926 (#14965) 2020-07-11 17:09:41 +02:00
Juan Carlos
6d10baa339 https://github.com/nim-lang/Nim/pull/14948#issuecomment-656498426 (#14958) 2020-07-11 06:21:59 -04:00
Clyybber
425972c4e8 Add testcase for some old fixed issues (#14960)
* Add testcase for #2703

* Add testcase for #2586

* Small fix
2020-07-10 19:21:50 +02:00
Clyybber
1850efbb6c Add testcase for #14383 (#14957) 2020-07-10 18:10:32 +02:00
Clyybber
db6ffeba8e Add testcase for #13815 (#14956) 2020-07-10 17:31:15 +02:00
Clyybber
0db32e9885 Add testcase for #12571 (#14955) 2020-07-10 17:13:37 +02:00
Clyybber
b21782a667 Add testcase for #4722 (#14954) 2020-07-10 17:02:49 +02:00
kwgchi
229a623849 Update readme.md (#14953) 2020-07-10 16:45:26 +02:00
Miran
371b416ac8 fix #14912, make --useVersion:1.0 work again (#14945)
* fix #14912, make `--useVersion:1.0` work again
* a better fix
* add test
2020-07-10 16:44:12 +02:00
Manuel Bojato
04232d92cd Fix theme switch load from local storage (#14897)
* fix theme switch load from local storage

* Fix tests

Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-07-10 15:06:07 +02:00
Araq
4603197fe8 fixes a minor regression 2020-07-10 13:36:02 +02:00
Araq
112511084d fixes the tcontrolflow regression, clen idea of an escaping expression 2020-07-10 13:36:02 +02:00
Araq
b59385f22b no wasMoved() calls after destructors necessary 2020-07-10 13:36:02 +02:00
Araq
37a98c77f3 optimize sinks even when in a loop 2020-07-10 13:36:02 +02:00
Araq
78513a9204 renderer.nim: more obvious debug output 2020-07-10 13:36:02 +02:00
Clyybber
bf51cee431 Update docs and changelog 2020-07-10 13:36:02 +02:00
Clyybber
4a1128d16c Move wasMoved out of =destroy 2020-07-10 13:36:02 +02:00
Clyybber
3e52136f26 Cosmetics 2020-07-10 13:36:02 +02:00
Araq
f92d2eaa35 cleanup of PR #14833 (VM profiler) 2020-07-09 19:21:20 +02:00
Ico Doornekamp
d7ccd82eac VM profiler (#14833)
* Crude VM profiler

* Added --profileVM flag, refactoring

* fixed FileLine hash

* Use TLineInfo instead of own FileLine, updated formatting

* Refactoring, moved PStackFrame to vmdefs for cleaner data structure

* Moved vmprofiler to separate file

* Simplified TLineInfo hash, use toFileLineCol for output

* Hash

* Moved profile data into Config, dump only once at end of run

* Changed profile output header to show '#instr' instead of 'count'

* Do not accumulate instrcount for non-top frames

Co-authored-by: Ico Doornekamp <git@zevv.nl>
2020-07-09 19:18:35 +02:00
Andreas Rumpf
c38a459582 fixes #14925 (#14947) 2020-07-09 17:24:23 +02:00
flywind
64815f59b2 add testcase for #4668 (#14946)
closes #4668
closes #9463
2020-07-09 12:53:12 +02:00
flywind
40b58a0a18 fix #11009 (#14935) 2020-07-09 09:57:35 +02:00
treeform
399b2e3134 Add missing dom.nim things (#14944) 2020-07-09 09:18:27 +02:00
flywind
00528cbc3c Add testcase for #10465 (#14943)
* add debug format string

* remove try except

* add changelog

* add docs and more tests

* Update lib/pure/strformat.nim

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>

* minor

* add testcase

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
2020-07-09 01:51:18 +02:00
flywind
3db6d9ea0c add docs and more tests for debug format strings (#14861)
* add debug format string

* remove try except

* add changelog

* add docs and more tests

* Update lib/pure/strformat.nim

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>

* minor

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
2020-07-08 22:21:30 +02:00
Clyybber
9016dd96ee Add testcase for #12129 (#14940)
* Add testcase for #12129

* Fix test
2020-07-08 22:04:21 +02:00
Andreas Rumpf
bc712c28fc fixes #14865 (#14937) 2020-07-08 18:59:34 +02:00
Clyybber
27579cfd3a Make arc compile laser again 2020-07-08 16:20:16 +02:00
Miran
3de5296337 remove a condition that table size must be passed as power of 2 (#14926)
* remove a condition that table size must be passed as power of 2
* remove power-of-2 condition from sets and sharedtables
* remove power-of-2 condition from deques
* use 'correctSize' for both branches
* prettify changelog.md and fix typos
* add a changelog entry
* fix double-call of 'right-size'
* fix the same thing in sets.nim
* introduce a new internal proc `slotsNeeded`

Deprecate the public proc `rightSize`, which is not needed anymore.
Now it is an identity function, allowing the old code to work
correctly and without extra allocations.
2020-07-08 15:01:47 +02:00
Andreas Rumpf
06d776a582 fixes #14900, this time for real, maybe (#14934) 2020-07-08 14:47:14 +02:00
Araq
cb1ecbf956 closes #14878 2020-07-08 12:22:55 +02:00
Araq
e42ce877a6 fixes #14805 2020-07-08 12:22:55 +02:00
Araq
ecf8cbbbe0 fixes #14900 2020-07-08 10:48:12 +02:00
Araq
cdce245a23 fixes #14899 2020-07-08 10:48:12 +02:00
Araq
b17e1efc67 progress 2020-07-08 10:48:12 +02:00
Andreas Rumpf
87f6a9592c fixes #14402 (#14908)
* fixes #14402

* added a test case
2020-07-08 08:21:55 +02:00
narimiran
e82a14b273 fix mistake in times.nim docs 2020-07-07 22:57:06 +02:00
Clyybber
8480bef1c4 Add testcase for #14864 (#14928)
* Add testcase for #14864

* :D
2020-07-07 22:43:36 +02:00
Dominik Picheta
25ceacbe4f Revert commit 3e843ab335. Closes #14930. 2020-07-07 19:18:02 +01:00
Andreas Rumpf
a61a7889b8 injectdestructors: refactoring, added more cases explicitly (#14929) 2020-07-07 17:47:57 +02:00
Araq
95808c2806 speed up Nim's lexer by using cstring instead of string. C optimizers are fragile. 2020-07-07 15:17:58 +02:00
Araq
49cea86d8b weaken tosproc test for my Windows machine which doesn't have 'ls' 2020-07-07 15:17:58 +02:00
awr1
37253d660f Minor improvements to typecast section of manual (#14896)
* Minor improvements to typecast section of manual

* Clarification to casting w/ concrete types

* Added less ambiguous language
2020-07-07 10:22:55 +02:00
Tomohiro
61a6098f2d Limit number of error messages from gcc/clang backend (#14852)
* Limit number of error messages from backend

* Avoid duplication of -fmax-errors

* make tests/misc/trunner.nim success
2020-07-07 10:22:10 +02:00
Clyybber
5bd2da3f64 Fix #14911 (#14922) [backport]
* Fix #14911

* Add testcase

* Fix test
2020-07-07 10:21:18 +02:00
Clyybber
ebd97884a0 Add testcase for #14472 (#14921) 2020-07-06 20:53:38 +02:00
ee7
a754160d65 tables.nim: Add named fields in smallest and largest (#14919)
The `smallest` and `largest` procs for `CountTable` returned a tuple
with named fields, but the same procs for `CountTableRef` returned an
anonymous tuple.

This commit makes those `CountTableRef` procs more consistent, and adds
a test.

Fixes: #14918
2020-07-06 14:02:03 +02:00
Araq
65af99a203 added security.md; refs #14882 2020-07-06 14:01:25 +02:00
Araq
6f962a4b36 fixes #14830 2020-07-06 13:41:56 +02:00
narimiran
46aacf917f Fix style inconsistencies due to the previous commit 2020-07-06 11:24:43 +02:00
narimiran
ebaf603c84 revert 0944b0f4 2020-07-06 10:55:51 +02:00
Dean Eigenmann
842efab8ae Update btrees.nim (#14916) 2020-07-06 10:23:42 +02:00
Juan Carlos
21b3ca636f Fix logging tiny bug (#14910)
* Fix logging tiny bug

* Update changelog.md

Co-authored-by: Danil Yarantsev <tiberiumk12@gmail.com>

* Update changelog.md

Co-authored-by: Danil Yarantsev <tiberiumk12@gmail.com>

* Update changelog.md

Co-authored-by: Danil Yarantsev <tiberiumk12@gmail.com>

* https://github.com/nim-lang/Nim/pull/14910#discussion_r450012032

Co-authored-by: Danil Yarantsev <tiberiumk12@gmail.com>
2020-07-06 04:00:25 -04:00
Clyybber
af27e6bdea Fix #14396 (#14793)
* Correct Left-To-Right evaluation of proc args
* Fix CPP backend
* Add testcase
* closes #14396
* closes #14345
* Improve test and optimize
* Improve testcase and optimize literals
* Fix bug
* Expand testcase and use DFA to optimize
* Turn genParams into proc
* Turn withTmpIfNeeded into a proc
* Cleanup
* Fix crash
* Better analysis
* Cleanup
* Trailing newline..
* Fix build
* Tiny cleanup

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-07-04 17:45:07 +02:00
Andreas Rumpf
1854d29781 scoped memory management (#14790)
* fixes the regressions
* closes #13936
* scope based memory management implemented
* enabled tcontrolflow.nim test case
* final cleanups
2020-07-04 07:37:24 +02:00
Timothee Cour
695154970d deprecate existsDir; use dirExists instead (#14884) 2020-07-03 23:04:23 +02:00
Juan Carlos
4f6acf24ff Add jsre (#14870) 2020-07-03 20:13:10 +02:00
Timothee Cour
a6cbe58e8c typetraits.$: $((int, float), int) is now "((int, float), int)" instead of "(tuple of (int, float), int)" (#14812)
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-07-02 16:19:43 +02:00
Timothee Cour
dc5a40f3f3 {.deprecated: [existsFile: fileExists].} (#14735)
* {.deprecated: [existsFile: fileExists].}

* s/existsFile/fileExists/ except under deps

* workaround pending #14819

* fix test
2020-07-02 16:19:13 +02:00
Tomohiro
366b9a7e4a Fix #12745 (#14879) 2020-07-02 13:20:34 +02:00
Juan Carlos
d590611fc5 Clean out sharedlists (#14857) 2020-07-02 08:40:58 +02:00
Juan Carlos
cbcaf2bbc4 Clean out strutils (#14859)
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-07-01 23:16:50 +02:00
Timothee Cour
930a0c999b cleanup comment now that #14434 was fixed (#14874) 2020-07-01 14:16:22 -07:00
Clyybber
1440e70c62 allow packed union (#14868)
Co-authored-by: Arne Döring <arne.doering@gmx.net>
2020-07-01 11:41:03 +02:00
Miran
1edb9a6178 fix #14401, trailing comma confuses nimpretty (#14867) 2020-07-01 11:40:13 +02:00
Timothee Cour
2867a33ebc fix #14846; add macros.extractDocCommentsAndRunnables (#14849)
* fix #14846; add macros.extractDocCommentsAndRunnables

* fixup

* update tests

* address comment
2020-07-01 09:26:23 +02:00
Juan Carlos
05384efec5 Clean out sharedtables (#14858)
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-06-30 19:09:13 +02:00
Juan Carlos
a519f3b038 Removed asyncdispatch.newAsyncNativeSocket, was deprecated since 0.18 (#14854)
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-06-30 16:29:53 +02:00
alaviss
56b3d422b0 typetraits: features and fixes (#14791)
* typetraits: add support for nnkTypeOfExpr

* typetraits: don't wrap typedesc symbols in StaticParam

* typetraits: add nested generics support to genericParams

* typetraits: make genericParams understand array[I, T] whackiness

Also moved tests to ttypetraits

* typetraits: clarify comment on genericParams
2020-06-30 15:25:53 +02:00
Ray Imber
36fa79a524 Fix asyncdispatch drain behavior (#14820) (#14838)
* Fix asyncdispatch drain behavior (#14820)

* Changed test to use asyncCheck instead of discard after code review (#14820)

* Added some debug statements to help understand what is happening in Azure.

* Removed debug statements and increased timeouts by 1 order of magnitude to account for slow Azure VMs

Co-authored-by: Ray Imber <ray@crankuptheamps.com>
2020-06-30 15:23:53 +02:00
flywind
8be54b8fa7 add debug fmt string like python's (#14808)
* add debug format string

* remove try except

* add changelog
2020-06-30 15:21:37 +02:00
Timothee Cour
89a15e417d CI openbsd: 3x batching via NIM_TESTAMENT_BATCH ; overall CI finishes in 21m instead of 34m (#14851)
* CI openbsd: 2x batching via NIM_TESTAMENT_BATCH

* auto-generate .builds/openbsd_x.yml to avoid code duplication

* 3x batching
2020-06-30 14:21:30 +02:00
Juan Carlos
04deb6c942 Clean out dom (#14855)
* Clean out dom

* Clean out dom
2020-06-30 10:08:16 +02:00
Juan Carlos
74d1f25010 Clean out oldast (#14837)
* Clean out old Deprecated CLI switch
* Update to remove --oldast CLI option
2020-06-30 10:01:25 +02:00
lbartoletti
5c1fa142d6 New freebsd platforms (#14801)
* add riscv as riscv64

* add all platforms supported by FreeBSD
2020-06-29 10:31:25 +02:00
Timothee Cour
1b41c3122b fix #13432 typetraits.$: $(int,) is now (int,); $tuple[] is now tuple[] (#14799)
* typetraits.$: $(int,) is now (int,); $tuple[] is now tuple[]

* changelog
2020-06-29 09:34:05 +02:00
Juan Carlos
5d5df4a394 Clean out Deprecated proc (#14797)
* Remove and/or clean out Deprecated 'add' proc for floats
* Update a test
2020-06-29 09:33:07 +02:00
aguspiza
d968163cd1 SSL_CTX_load_verify_locations parameters are reversed (#14815) [backport] 2020-06-29 08:50:37 +02:00
Clyybber
299ddda5f6 Make unreachable code a warning instead of an error (#14816)
* Make unreachable code a warning

* Adapt test

* Trigger CI
2020-06-29 08:49:53 +02:00
Timothee Cour
3732556468 fix ./koch tests following #14823 (#14845) 2020-06-28 14:34:34 -07:00
Clyybber
62394616e8 DFA and injectdestructors cleanup (#14824)
* DFA and injectdestructors cleanup

* More precise write analysis

* Cleanup obsoleted path

* Unify defInstrTargets and useInstrTargets

* Misc cleanups

* Nicer CFG printing

* Misc cleanups 2
2020-06-28 19:36:30 +02:00
Danil Yarantsev
7936768560 Fix some typos (#14843) 2020-06-28 19:17:18 +02:00
Clyybber
4f70180a58 Fix typo 2020-06-28 18:03:39 +02:00
Danil Yarantsev
c285739d55 Remove double entry for thiscall (#14842) 2020-06-28 18:00:43 +02:00
Andrey Makarov
d9c1501757 get rid of $READLINK variable (#14841) 2020-06-28 17:59:57 +02:00
Clyybber
394a56650a Fix #14647 (#14776)
* Fix #14647

* Correct fix

* Typo and add test

* For real now :p
2020-06-28 17:47:47 +02:00
Clyybber
037990bc78 Changelog: Tiny style improvement 2020-06-28 15:38:24 +02:00
lqdev
5d5271b789 fixed #14839 (#14840) 2020-06-28 13:38:57 +02:00
Clyybber
54a52e7d08 Update link to parseSpec proc 2020-06-28 00:13:54 +02:00
rockcavera
252f668829 add a second asyncnet.recvFrom (#14237)
* add a second asyncnet.recvFrom

* fixes

* pre-allocating address

* add a new nativesockets.getAddrString()
2020-06-27 22:59:08 +01:00
Manuel Bojato
bc66788b3f docs: Make ..<, .. ^ more discoverable (#14835) 2020-06-27 23:42:58 +02:00
Manuel Bojato
22f1b5120e Fix nimdoc invalid css on theme switch class (#14834) 2020-06-27 23:36:31 +02:00
Sizhe Zhao
ad00d616e8 Warn about calling wrappers at compile time until #14049 is fixed. (#14828) 2020-06-27 16:51:48 +02:00
Timothee Cour
90808877c5 testament: generic N-fold batching: windows CI 37mn=>16m (#14823)
* testament: run CI faster thanks to batching
* move ta_in, tstdin into existing tosproc
* move ta_out,tafalse,texitcode,tstderr into existing tosproc
* joinable osproc
* move tstdout into existing tosproc
* spec: batchable; fix tests
* fixup
2020-06-27 16:51:17 +02:00
Clyybber
fdb37400cb Testament: Reenable arraymancer (#14831) 2020-06-27 15:58:19 +02:00
Sizhe Zhao
70b07edf42 Fix missing comma (#14829) 2020-06-27 12:11:29 +02:00
treeform
f926dc53f1 Add all missing css properties to dom.nim. (#14825)
* Add all missing css properties

* remove extra space
2020-06-26 19:15:21 +01:00
Timothee Cour
4dfb062f4d update contributing.rst and docstyle.rst: refer to a bug via bug #1234 + other guidelines (#14796)
* add a testing convention in nep1
* misc updates to contributing.rst and docstyle.rst
* address comments
2020-06-26 10:40:34 +02:00
Timothee Cour
49fcda3330 followup after https://github.com/Vindaar/ggplotnim/pull/74 wrt #14447 lent iterators (#14817)
* followup after https://github.com/Vindaar/ggplotnim/pull/74 wrt #14447 lent iterators

* ggplotnim: remove -d:nimHasWorkaround14720
2020-06-26 04:10:22 +02:00
treeform
baa80ca9d4 Add hasAttribute method to dom.nim. (#14814)
See: https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttribute
2020-06-25 14:45:37 -07:00
ktamp
41c97e4b70 readLine: Fix issues with --gc:arc
**--gc:arc** defines **nimv2**. This changes the definition of **WideCStringObj**.
Also an empty string should be returned in case of EOF.
2020-06-26 00:31:06 +03:00
narimiran
13193b2964 turn 'runnableExample' into 'code-block' to make nightlies green
This example doesn't work on our nightlies CI.
Other procs in this module already use 'code-block'.
2020-06-25 16:55:11 +02:00
Clyybber
0a9a639230 Add testcase for #4796 (#14784)
* Add testcase for #4796

* Fix test
2020-06-25 15:12:30 +02:00
alaviss
1a0725f022 koch: add --localdocs to allow building only local docs (#14783)
* koch: add --localdocs to allow building only local docs

This flag also make koch doc use the passed arguments when building
the offline docs.

This is useful when generating nightlies as we would want to use
--doccmd:skip and also skipping a pass of docgen speed things up
drastically (for non-native targets).

This flag superseded the undocumented --docslocal.

* kochdocs: filter google analytics code from the arg list instead

This commit introduce a small PEG expression to filter out the google
analytics code before building local docs when --localdocs is not
specified. This lets us keep any arguments unrelated to google analytics
when building local docs, useful for use with --doccmd:skip
2020-06-25 10:28:57 +02:00
Timothee Cour
0c56eeda0e expr => untyped; stmt => typed (#14804)
* expr => untyped; stmt => typed

* changelog + comment
2020-06-25 10:22:08 +02:00
Timothee Cour
32f335f594 fix #14802 (#14803) 2020-06-25 08:00:19 +02:00
Danil Yarantsev
0327159344 Add test-cases to some fixed issues to close them (#14795) 2020-06-24 20:38:08 -07:00
ktamp
c6e09e335a readLine: Remove recursive imports 2020-06-25 00:22:24 +03:00
Danil Yarantsev
80952cadaa Reject casts to builtin typeclasses (#14788)
* Closes #14231, closes #14452

* Merge test to tcast.nim
2020-06-24 22:32:01 +02:00
Timothee Cour
3e5743d6f7 add typetraits.elementType (#14780)
* add typetraits.elementType

* add a test for 0-sized seq
2020-06-24 22:31:07 +02:00
Euan
0434aef4cd Patch #14716 - add missing when (#14792) 2020-06-24 18:44:10 +02:00
Timothee Cour
37081e2945 fromJson: support object variants (#14694) 2020-06-24 18:03:01 +02:00
Euan
a3ae52de1a Fix #14715 - detect tool fails on FreeBSD (#14716) 2020-06-24 18:02:18 +02:00
Timothee Cour
b49ac11a77 fix #10343 (#14789) 2020-06-24 18:00:35 +02:00
Clyybber
302e3b7f44 CI: Install the pkg we cloned (#14770) 2020-06-24 17:27:46 +02:00
narimiran
2220ff70be cleanup [ci skip] 2020-06-24 13:16:40 +02:00
Constantine Molchanov
1b196d85aa Fix Norm test path. (#14779) 2020-06-24 00:36:41 +02:00
ktamp
a3b9516249 readLine: Unicode support for Windows console
When input is read from the Windows console, input encoding is UTF16. This is translated internally to UTF8.
2020-06-23 23:31:41 +03:00
treeform
9ebbe000a8 Enable fidget in important_packages. (#14742)
* Enable fidget in important_packages.

Fidget now works with `nimble test` and there is a CI: https://github.com/treeform/fidget/commits/master

* Add libx11-dev to make fidget compile.

* try libxcursor-dev

* try xorg-dev
2020-06-23 20:37:29 +02:00
Miran
6bf2990f66 [backport] fix #14748, move gdb files to other section of installer.ini (#14772) 2020-06-23 20:36:59 +02:00
Miran
881d1ee57b fix #14750, don't allocate too much in newWideCString (#14773) 2020-06-23 16:15:37 +02:00
Clyybber
685d03e2e0 Correct changelog (#14775)
These switches were removed, not deprecated :)
2020-06-23 15:20:31 +02:00
Andreas Rumpf
16bdc547b7 fixes #14760 (#14769) 2020-06-23 15:17:17 +02:00
Clyybber
4cb41f53f0 Add testcase for #14440 (#14771) 2020-06-23 14:17:12 +02:00
Juan Carlos
28510a9da9 Deprecated laxStrings for mutating the internal zero terminator on strings and its Deprecated code cleaned out (#14766)
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-06-23 13:20:53 +02:00
Juan Carlos
c3459c7b14 Deprecate oldNewlines, clean out deprecated code from oldNewlines (#14763) 2020-06-23 11:22:07 +02:00
Juan Carlos
79ed8e79ef Documentation GC (#14739) 2020-06-23 11:21:33 +02:00
Araq
ebd1cc0265 minor bugfixes for 'func' and .borrow 2020-06-23 10:58:55 +02:00
Andreas Rumpf
da29222f86 init checks and 'out' parameters (#14521)
* I don't care about observable stores
* enforce explicit initializations
* cleaner code for the stdlib
* stdlib: use explicit initializations
* make tests green
* algorithm.nim: set result explicitly
* remove out parameters and bring the PR into a mergable state
* updated the changelog
2020-06-23 10:53:57 +02:00
Timothee Cour
a9eee6db65 misc testament cleanups (#14764)
* misc testament cleanups extracted cleanups from #14530

* make sure all CI failures can be searched with `FAIL: ` including megatest failures
2020-06-23 10:53:03 +02:00
Juan Carlos
8e54bc5b0c Deprecate and/or remove ospaths (#14767) 2020-06-23 10:51:33 +02:00
Timothee Cour
511bd947d3 fix bug in semgnrc: runnableExamples should not semcheck, even with > 1 arg (#14768) 2020-06-23 10:06:36 +02:00
Timothee Cour
235d8ba069 unbreak CI, refs https://github.com/timotheecour/Nim/issues/167 (#14765) 2020-06-22 18:38:23 -07:00
Clyybber
03c8bbcc6e Remove outdated comment and copy of length (#14759) 2020-06-22 22:05:18 +02:00
b3liever
59ba4d8c03 added normal variate function (#14725)
* added normal variate function
* change method only slightly faster
* changelog + since

Co-authored-by: b3liever <b3liever@yandex.com>
2020-06-22 20:48:33 +02:00
Andreas Rumpf
451129de42 fixes #14240 [backport:1.2] (#14757) 2020-06-22 14:11:13 +02:00
Andreas Rumpf
8df20276c9 fixes #14458 [backport:1.2] (#14756) 2020-06-22 13:06:22 +02:00
alaviss
c8554ebc0c posix_other: add define to force time_t to 64 bit [backport] (#14753)
This is a temporary remedy for time_t transition to 64 bit on newer
Linux libc (musl >= 1.2.0, glibc >= 2.32).

In the future we might want to move away from libc, or figure out a way
to reliably detect the real size of C types at compile time, both of
which are difficult.
2020-06-22 09:23:24 +02:00
ee7
1e484ed62b [backport] Docs: Fix broken code-block (#14749)
This commit indents the contents of a `code-block` in `httpclient.nim`
so that it displays correctly. The bug was introduced by 42a64245f8.

I did a quick search for other `code-block`s that are broken in the same
way, but the only other one I found (in `pegs.nim`) is not included in
the generated documentation.
2020-06-22 08:12:50 +02:00
treeform
1ffe113450 Export fields from the Selection object. (#14752)
See: https://developer.mozilla.org/en-US/docs/Web/API/Selection
2020-06-21 20:41:24 +02:00
Andreas Rumpf
3ba0c30758 sizeof for empty objects/tuples should be 1; fixes #14690 (#14751) 2020-06-21 19:58:37 +02:00
alaviss
c7dee55b87 encodings: use only one iconv definition [backport:1.2] (#14741)
Fix an issue reported on IRC: using encodings with --dynlibOverrideAll
result in duplicated iconv definitions, causing compile errors.

This commit remove the `var` wrapper of iconv and go all out on
pointers, as it should due to how the API accepts nil. Also corrected
the API to resemble iconv(3p).
2020-06-21 19:28:03 +02:00
treeform
ca71a60ff6 Add css white-space property to dom.nim. (#14743)
https://developer.mozilla.org/en-US/docs/Web/CSS/white-space
2020-06-21 19:25:29 +02:00
Timothee Cour
79c90b30ee nep1: use subjectVerb, not verbSuject (#14732) 2020-06-19 23:38:43 +02:00
Kaushal Modi
ac8ab4c549 Clarify the use of the backwards index operator (^N) in tut1 (#14681)
* Clarify the use of the backwards index operator (^N) in tut1

For consistency:
- Do `[a .. ^b]` (notice spaces on both sides of `..`)
- Do `[c ..< d]` (notice spaces on both sides of `..<`)

Fixes https://github.com/nim-lang/Nim/issues/14671.

* tut1: Add a note that ^ template calls can be saved to consts
2020-06-19 10:22:48 -04:00
Juan Carlos
99c198625c Deprecate unroll pragma, remove from documentation (#14705) 2020-06-19 15:08:45 +02:00
Timothee Cour
2039e3e883 fix #13899 defer now works with async (#14723) 2020-06-19 15:08:00 +02:00
Araq
65c7884a3c fixes #14718 [backport] 2020-06-19 15:02:38 +02:00
Clyybber
45d1e55e72 Add testcases for #11811 and #14315 (#14726)
* Add testcase for #11811

* Add testcase for #14315
2020-06-19 14:56:38 +02:00
Araq
45bc6954c5 improve the parser's error message 2020-06-19 10:50:39 +02:00
Araq
522bc8dda1 added a space 2020-06-19 10:32:16 +02:00
Timothee Cour
5ad8b9e8eb fix #14685 tests/async/t7758.nim flaky (#14721)
* fix #14685 tests/async/t7758.nim flaky

* address comment

* address comment
2020-06-19 09:53:45 +02:00
Timothee Cour
9c42ae91b7 add legacy workaround; improve test so that it actually tests for the bugfix 2020-06-19 09:53:06 +02:00
solo989
408518c9fe Update tuple newLit 2020-06-19 09:53:06 +02:00
BarrOff
99ad65fdd6 make nim-gdb compatible with BSD systems (#14700) 2020-06-18 20:48:55 +02:00
Timothee Cour
bb62feff72 fix #14691 docgen works again for methods (#14701)
* fix #14691 docgen methods

* fixup
2020-06-18 08:47:16 +02:00
Timothee Cour
7df27b5035 [cleanups] doassert => doAssert; mark deadcode (#14711) 2020-06-17 20:25:25 -07:00
Miran
e7f280bd26 Remove deprecated stuff from stdlib (#14699)
* update to the latest Jester

* remove deprecated procs from some stdlib modules

* 'criterion' is not maintained anymore and relies on obsolete stuff
2020-06-17 15:25:02 +02:00
Timothee Cour
8619534293 remove compilerproc from newIdentNode (#14692) 2020-06-17 08:10:34 +02:00
Juan Carlos
15a45e8e73 Documentation update nims.rst (#14683)
* Update nims.rst to add modules that work on NimScript as mentioned in the changelog.md

* https://github.com/nim-lang/Nim/pull/14683#issuecomment-644976921
2020-06-17 07:58:03 +02:00
solo989
bdd2c25e9f Update macros.nim (#14697) 2020-06-17 07:57:04 +02:00
Timothee Cour
ff93302f69 use check to investigate #14685 flaky tests/async/t7758.nim (#14689) 2020-06-16 15:57:57 -07:00
Timothee Cour
7ded490ec0 cleanup tests/test_nimscript.nims (#14686) 2020-06-16 14:38:30 -07:00
Dylan Modesitt
e35b21e553 Close#5586 (#14682)
* re-enable macos and bsd on some coro tests

* re-enable macos and bsd on some coro tests
2020-06-16 16:24:26 +02:00
Euan
1bc2e19498 Set cincludes and clibdir for FreeBSD, OpenBSD and NetBSD. (#14680) 2020-06-16 11:44:28 +02:00
Timothee Cour
dfe51d10a1 addQuitProc now works with closures, and c, js(node/browser) backend; fix some bugs in testament (#14342)
* make addQuitProc great again

* fix bugs in testament

* fix test

* change 2016 => 2020

* addQuitProc => addExitProc + locks

* move to std/exitprocs
2020-06-16 11:43:48 +02:00
Timothee Cour
45cac4afda fix #14179, fix #14142, make CI 1.4x faster (2x faster locally) (#14658)
* fix #14142: no more clash with: import os + use of existsDir/dirExists/existsFile/fileExists/findExe in config.nims

* remove a comment

* Revert "fixes the regression #12860 caused; hotfix"

This reverts commit 3d2459bdc0.

* Revert "Undefine `paramCount` & `paramStr` in nimscript.nim for *.nims (#12860)"

This reverts commit d38853c504.

* noNimScript => noWeirdTarget + noNimJs
2020-06-16 08:56:12 +02:00
Euan
7b12f13946 Use cc on OpenBSD and link to libm when building result (#14672) 2020-06-16 08:50:57 +02:00
Timothee Cour
de5cde473a hintMsgOrigin now works in VM code (#14678)
* `hintMsgOrigin` now works in VM code

* remove a simplification for now
2020-06-16 08:49:57 +02:00
Timothee Cour
faedb14a16 misc cleanups in compiler msgs: use toHumanStr, etc (#14677) 2020-06-15 21:17:24 -07:00
Timothee Cour
49033eb531 make tests/stdlib tests joinable (#14626)
* make tests/stdlib tests joinable

* fixup
2020-06-15 13:27:33 +02:00
Timothee Cour
d51beb7b20 make fromJson/toJson work with array[range, typ], + 1 bugfix (#14669)
* make toJson more robust

* properly handle array
2020-06-15 13:22:43 +02:00
Timothee Cour
bf604c6829 normalizeExe (#14668) 2020-06-15 10:57:34 +02:00
solo989
3cbf59336d Update newLit set[T] to work when set is empty. (#14662)
* Update macros.nim

* Update lib/core/macros.nim

Co-authored-by: Clyybber <darkmine956@gmail.com>

Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-06-15 09:15:17 +02:00
Ico Doornekamp
571bc011ea Added --benchmarkVM to times.cpuTime() documentation (#14663) 2020-06-15 08:58:11 +02:00
Juan Carlos
a056b4c3f1 Change 'Future Directions' to link memory management documentation (#14664) 2020-06-15 08:55:24 +02:00
jcosborn
5a22d6b57b fix codegen bug due to changing existing symbol declaration in template (#14666) 2020-06-15 08:40:12 +02:00
alaviss
d749c8cd87 compiler/commands: make gitHash settable at compile-time. (#14654)
This is useful for building nightlies, since we will be building from a
generated source archive and git metadata is lost there.
2020-06-14 11:22:55 +02:00
Andy Davidoff
4e3edf5836 add arc and orc to gc list (#14653) 2020-06-14 11:12:08 +02:00
Timothee Cour
0fc5d3f13b fix #14655 setLen(seq) now zeros memory (#14656)
* simplify sysstr.nim

* fix #14655
2020-06-14 11:11:26 +02:00
Dominik Picheta
d3b25a2948 Clarify imported exceptions note in manual 2020-06-13 11:44:01 +01:00
Timothee Cour
d149823019 fix #13166 tioselectors flaky test on freebsd+OSX (#14634) 2020-06-12 21:19:23 -07:00
Araq
5a26c3799b reorder.nim: fixed typos 2020-06-12 11:57:29 +02:00
Timothee Cour
e30a08103d remove tyOpt, mOpt (#14636)
* remove tyOpt, mOpt

* fixup
2020-06-12 11:03:52 +02:00
Juan Carlos
82e424189e Add rstgen.rstToLatex convenience proc for renderRstToOut and initRstGenerator with outLatex output, see https://github.com/nim-lang/fusion/pull/11#issuecomment-641804899 (#14629) 2020-06-12 10:51:55 +02:00
djazz
1168c75381 httpcore: Add http code 308 Permanent Redirect (#14639)
* httpcore: Add http code 308
* httpclient: Add 308 to redirection proc
* fix typo
2020-06-12 10:16:38 +02:00
alaviss
67d34366dc tools/kochdocs: add log folding supports for more CI services (#14643)
Added log folding for:
- Github Actions
- Azure Pipelines
2020-06-12 10:06:29 +02:00
Timothee Cour
c83a22b76e Disable tfdleak_multiple on platforms other than Windows (#14624) 2020-06-11 12:54:32 -07:00
c-blake
6aa971d39f Add proc find to heapqueue (#14628)
* Unwind just the "pseudorandom probing" (whole hash-code-keyed variable
stride double hashing) part of recent sets & tables changes (which has
still been causing bugs over a month later (e.g., two days ago
https://github.com/nim-lang/Nim/issues/13794) as well as still having
several "figure this out" implementation question comments in them (see
just diffs of this PR).

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

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

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

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

* Fix `data.len` -> `dataLen` problem.

* Add neglected API call `find` to heapqueue.

* Add a changelog.md entry, `since` annotation and rename parameter to be
`heap` like all the other procs for consistency.

* Add missing import.
2020-06-10 19:53:18 +01:00
Timothee Cour
8bbdb8f43f fix #14545 windows CI docs (#14590)
* fix #14545 windows paths
* add lib/std/private/strutils2.nim
* remove dependency strutils2 => strutils
* address comment: lib/std/private/strutils2.nim => compiler/strutils2.nim
2020-06-10 14:10:57 +02:00
ee7
5131af1a44 exceptions.nim: Fix a bad Error -> Defect renaming (#14621)
This commit fixes a mistake from 7d6cbf290a.
2020-06-10 09:34:20 +02:00
Timothee Cour
b7b84fa165 parseutils: integerOutOfRangeDefect => integerOutOfRangeError (#14627) 2020-06-09 23:57:27 -07:00
Timothee Cour
d81bc69587 enable tioselectors on osx; more diagnostic for #13166 (#14625) 2020-06-09 19:15:18 -07:00
Juan Carlos
387e337a2a Documentation update a description (#14619)
* Documentation update a description in a page listing links

* Update doc/docs.rst

Co-authored-by: Danil Yarantsev <tiberiumk12@gmail.com>

Co-authored-by: Danil Yarantsev <tiberiumk12@gmail.com>
2020-06-09 22:17:32 +01:00
Andreas Rumpf
6085ad95ff fixes #14279 (#14618) 2020-06-09 20:39:26 +02:00
Andreas Rumpf
b3029ba213 fixes #14578 (#14615) 2020-06-09 17:05:01 +02:00
Juan Carlos
881fa94b57 Documentation Fix Typo, Add Table (#14609) 2020-06-09 15:43:42 +02:00
ynfle
aa70cfdea2 Fix(astspec.txt): type of repeated word (#14612) 2020-06-08 20:14:26 -07:00
Max Grender-Jones
cc3409e264 Make the example better describe the desired outcome (#14611) 2020-06-08 18:49:07 -07:00
lbartoletti
30c09e4607 [OpenBSD] Add arm support (#14608)
* add arm support to openbsd

* use clang on openbsd
2020-06-08 20:06:04 +02:00
Andreas Rumpf
c308c2e60b optimized wrapWords; fixes #14579 (#14606) [backport:1.2] 2020-06-08 14:34:26 +02:00
Andreas Rumpf
e3f80e434a fixes #14557 (#14607) 2020-06-08 14:32:45 +02:00
Timothee Cour
c7a1a7b8bf toJson, jsonTo, json (de)serialization for custom types; remove dependency on strtabs thanks to a hooking mechanism (#14563)
* json custom serialization; application for strtabs
* serialize using nesting
* make toJson more feature complete
* add since
* Revert "Improve JSON serialisation of strtabs (#14549)"

This reverts commit 7cb4ef26ad.

* better approach via mixin
* toJson, jsonTo
* fix test
* address comments
* move to jsonutils
* doc
* cleanups
* also test for js
* also test for vm
2020-06-08 10:35:23 +02:00
Tomohiro
733bd76f6b Fix sugar.dump: It doesn't work correctly with compile time expression (#14580) 2020-06-08 10:28:42 +02:00
Timothee Cour
0d814f2d44 hotfix disable nitter refs https://github.com/timotheecour/Nim/issues/167 (#14603) 2020-06-08 08:15:34 +02:00
alaviss
8edac9cf1d openssl: use explicit result for SSL_in_init (#14597)
Sometimes the analysis might get funky and decide that the if-expression
below is not an if-expression. Details of how this can happen is largely
unknown, but it's easy to prevent so we will just go forward with that.

Fix #14591
2020-06-08 08:15:10 +02:00
Clyybber
52841dba09 Fix #14568 (#14583)
* Fix #14568
* Add testcase
* Fix bogus test
* Adapt other failing tests
* Declarations are always first writes
2020-06-07 23:32:41 +02:00
Andreas Rumpf
754a196d47 fixes #14315 (#14594) 2020-06-07 23:29:26 +02:00
Andreas Rumpf
419dbd573d fixes #14118 (#14595) 2020-06-07 20:11:42 +02:00
Andreas Rumpf
66c50c2ffc implement the 'bind' statement for generics, it was an oversight that this was never implemented (#14584) 2020-06-07 09:55:56 +02:00
lbartoletti
51b71e35f2 Fix link to "rebuilding the compiler" (#14567) 2020-06-06 21:53:18 +02:00
Andreas Rumpf
32083c7ff8 more precise analysis about 'observable stores' [backport:1.2] (#14582) 2020-06-06 21:28:46 +02:00
Leorize
4fdf9cb808 wrappers/openssl: defer loading SSL_CTX_set_ciphersuites 2020-06-06 21:11:53 +02:00
Leorize
6b2d8bfc8b net: also set TLSv1.3 cipher suites 2020-06-06 21:11:53 +02:00
Leorize
3cd74c6408 wrappers/openssl: mark casts as gcsafe
Nim will pretend that these proc are not gcsafe if they are not marked.
2020-06-06 21:11:53 +02:00
Leorize
b323bccd81 wrappers/openssl: enable SSL_CTX_set_ecdh_auto for LibreSSL
This procedure is not no-op for older LibreSSL, and the ABI is kept for
newer versions, so there's no harm in enabling it unconditionally for
all LibreSSL versions.
2020-06-06 21:11:53 +02:00
Leorize
e80a23f4d2 net: revert compatibility changes for Windows
This reverts commit d53a6355f3 and
688b1f250e.
2020-06-06 21:11:53 +02:00
Leorize
d406f588d8 wrappers/openssl: the version number comes from the utility library
Previously we loaded the SSL library for this, but that's not where the
symbol resides.
2020-06-06 21:11:53 +02:00
Leorize
0ca069b4f8 net: use CiphersOld list for Windows
The default DLLs shipped are too old, switch to CiphersOld list to
ensure compatibility.

This commit should be reverted before any future release.
2020-06-06 21:11:53 +02:00
Leorize
279438f1df net: don't call set_ecdh_auto for super old OpenSSL
And the fun thing is that currently we use a super old OpenSSL on
Windows.
2020-06-06 21:11:53 +02:00
Leorize
b5b191af4b wrappers/openssl: fix SSL_CTX_set_mode
Follow up of 794042080b
2020-06-06 21:11:53 +02:00
Leorize
61d4fbce4f wrappers/openssl: getOpenSSLVersion is gcsafe
Yet another weird {.gcsafe.} triggering when it shouldn't.
2020-06-06 21:11:53 +02:00
Leorize
6c0f86c486 net: enable automatic EC curve selection for OpenSSL 1.0.2
This setting is required for servers running OpenSSL < 1.1.0 to support
EC-based secure ciphers that is now part of the default cipher list.
2020-06-06 21:11:53 +02:00
Leorize
9278e785bd wrappers/openssl: fix SSL_CTX_ctrl signature 2020-06-06 21:11:53 +02:00
Leorize
e4e3d99ee2 asyncnet: clear SSL error queue before performing I/O
Follow up of 476be6cc27
2020-06-06 21:11:53 +02:00
Leorize
256841cf2c changelog.md: clarify that only the default has changed [ci-skip] 2020-06-06 21:11:53 +02:00
Leorize
1715935846 ssl_config_parser: refactor for sanity reasons 2020-06-06 21:11:53 +02:00
Leorize
3d4d3f4ac2 untestable/thttpclient_ssl: some tests are no longer broken
With the changes to the default cipher suites, certain tests are no
longer broken and are acting as they should.
2020-06-06 21:11:53 +02:00
Leorize
23cc4091d9 untestable/thttpclient_ssl: move incomplete-chain to dubious_broken
It's unsure why this test fail for macOS, but it doesn't hurt if it's
not passing.
2020-06-06 21:11:53 +02:00
Leorize
1fb2a58674 net: use a secure cipher list by default
Previously, the `net` module use the blanket "ALL" as the default cipher
list. This list may contain security ciphers that are weak and/or outdated
according to the current standard.

This commit introduces a new module `ssl_config` that contains the
latest OpenSSL configurations as recommended by Mozilla OpSec, and
make the `net` module use the cipher list targeting `intermediate`
compatibility level as the default.
2020-06-06 21:11:53 +02:00
Leorize
6cb94b5da6 asyncnet, net: clear openssl error queue before performing I/O
Per SSL_get_error(3):

  The current thread's error queue must be empty before the TLS/SSL I/O
  operation is attempted, or SSL_get_error() will not work reliably.

There has been records of not clearing the error queue causing weird SSL
errors when there shouldn't be any, see:

https://github.com/openssl/openssl/issues/11889
2020-06-06 21:11:53 +02:00
Leorize
f243f9aeb5 openssl: fix erroneous function signatures
Now matches the declaration in openssl/err.h
2020-06-06 21:11:53 +02:00
Leorize
78982b52f0 net: don't clear error queue unless shutdown() will be performed 2020-06-06 21:11:53 +02:00
Leorize
19ccce2617 Revert "net: don't clear all errors on close"
You're supposed to clear the error queue before any I/O operations. Per
SSL_get_error(3) man page.

This reverts commit ee3ed37300.
2020-06-06 21:11:53 +02:00
Leorize
44d0b4bdfd thttpclient_ssl: be less specific
The error we're looking for is "certificate verify failed". The routine
that reports this will be different between openssl versions, so it
makes no sense to track the routine name as well.
2020-06-06 21:11:53 +02:00
Leorize
d06e6eec79 net: don't clear all errors on close
Closing a socket clears the error queue of the entire thread, which
seems to be a bit too invasive.

Also I don't find any reason in the PR that added this.
2020-06-06 21:11:53 +02:00
Leorize
65b350f112 untestable/thttpclient_ssl: fix macos 2020-06-06 21:11:53 +02:00
Leorize
df91f61e20 untestable/thttpclient_ssl: fix 10000-sans test 2020-06-06 21:11:53 +02:00
Leorize
19ccc5fd8d untestable/thttpclient_ssl: catch errors caused by the bad catergory
Previously the errors caused by `SSL_shutdown()` masked these, so now we
catch them.
2020-06-06 21:11:53 +02:00
Leorize
82092b3bb7 asyncnet, net: call SSL_shutdown only when connection established
This commit prevents "SSL_shutdown while in init" errors from happening.

See https://github.com/openssl/openssl/issues/710#issuecomment-253897666
2020-06-06 21:11:53 +02:00
Timothee Cour
61f2f1f5c5 fix #14576 addr of param (including for lent) now works with nim js (#14577)
* fix #14576 addr(param) now works in nim js

* workaround https://github.com/nim-lang/Nim/issues/14578
2020-06-06 20:15:24 +02:00
Araq
336f1e63d0 reorder.nim: fixes the indentation 2020-06-06 20:08:57 +02:00
Zed
ea761419ad Fix asynchttpserver newline breaking content-length (#14565) [backport] 2020-06-06 12:20:11 +02:00
Timothee Cour
d573581eb7 remove isMainModule from json,os,sequtils (#14572)
* move json.isMainModule => tjson

* move isMainModule => tos,tsequtils
2020-06-06 11:50:46 +02:00
Danil Yarantsev
b19ad22b90 Fix #14570 (#14571)
* Fix #14570
2020-06-06 09:31:19 +02:00
Timothee Cour
7cdf470269 refs #14545 fix snippet errors: avoid showing confusing errors when they are expected (#14569) 2020-06-05 19:04:39 -07:00
Araq
0824fdd061 fixes #14562 2020-06-05 16:15:13 +02:00
PMunch
7cb4ef26ad Improve JSON serialisation of strtabs (#14549)
This creates a more compact serialisation of strtabs that is more in
line with the normal tables.
2020-06-05 10:54:38 +02:00
alaviss
c1ca06b452 tfdleak: fix flakyness on Windows (#14550)
* tfdleak_multiple: introduce stress tester for tfdleak

Imported from #14548 and tweaked for consumption by testament.

This test seems to be really good at bringing out the flakyness of
tfdleadk.

Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>

* tfdleak: increase accuracy of the test on Windows

This commit implements a new testing strategy for Windows:
1. We duplicate the handle that will be tested and enable inheritance.
   This duplicate will serve as a reference handle.
2. In addition to checking whether the handle is valid, we also verify
   whether the handle is the same as the reference. This gives us
   complete certainty on whether the handle in question is inherited
   from the parent.
   A side effect is that this uses Windows 10+ APIs. But since
   this is just for the test, we don't have to be picky about it.

Ideally we would want to do something like this for other POSIX-based
system, but most of them lack a facility to do this, and as of writing
there isn't any false positive for them, so we won't need the additional
checks.

MemFile.fHandle will also no longer be tested, as this handle defaults
to being invalid.

Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>
2020-06-04 13:25:38 +02:00
Timothee Cour
01f6e505c8 bug fixes with sfMainModule, hints, mainPackageNotes, mainPackageId, hintSuccessX (#14555)
* SuccessX `out` now works with --compileOnly and jsonscript; fix bugs in jsonscript
* several bug fixes; eg: `nim doc lib/system/io` now is sane
* dummy edit to force docs CI
2020-06-04 10:40:17 +02:00
Timothee Cour
4ba34522f6 [cleanup] docgen: remove docOutdir now that outDir is always set (#14554) 2020-06-03 19:20:41 -07:00
alaviss
55f0df164b io: correct signature for some win32 apis (#14551)
See https://github.com/nim-lang/Nim/pull/14550#issuecomment-637937649
2020-06-03 18:17:06 +02:00
Timothee Cour
4301a3da9d * honor --errorMax even for tools (eg drnim, nim doc) (#14546)
* fix a bug that prevented nim doc compiler/nim on windows
2020-06-02 18:54:33 +02:00
Timothee Cour
621384b8ef fix https://github.com/timotheecour/Nim/issues/266 retry on failure to avoid common 503 github errors (#14547) 2020-06-02 10:47:19 +02:00
cooldome
e5b64af831 Implement rendering of []=, {}, {}= braces (#14539)
* render curly braces
* fix typo
* fix test

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-06-01 19:56:17 +02:00
Timothee Cour
3cf88c2b49 walkDirRecFilter, update doc CI filter, compiler/index.nim for docs + various other fixes (#14501)
* update doc CI filter to include the files mostly likely to require doc rebuild
* remove code duplication in ./config/nimdoc.cfg; show link to compiler docs, various fixes
* walkDirRecFilter, factor nativeToUnixPath workaround
* glob for getRst2html
* docslocal: 40s to build all docs
* revert code dedup in github actions which did not work alas...
* fixups
2020-06-01 19:21:41 +02:00
Andreas Rumpf
75e579ff8e parser.nim: minor refactorings (#14540) 2020-06-01 19:04:28 +02:00
Danil Yarantsev
3698f197f1 Change severity of template instantiation message [backport] (#14526)
* Change severity of template instatiation msg

* Add a test

* Trailing newline argh
2020-06-01 17:07:01 +02:00
Frank Paulo Filho
4bb301dbe2 Make build_all.sh file executable (#14518) 2020-06-01 15:57:16 +02:00
Timothee Cour
0a27cca4b5 runnableExamples: correctly handle multiline string litterals (#14492)
* runnableExamples: correctly handle multiline string litterals

* address comments: improve doc comments + variable namings
2020-06-01 15:56:29 +02:00
Andreas Rumpf
0db148163b fixes --warningAsError implementation (#14538) 2020-06-01 15:41:14 +02:00
Danil Yarantsev
00ec43305e Fix compiles for nimsuggest [backport] (#14527)
* Handle nimsuggest in tryExpr
* Added test
2020-06-01 15:06:45 +02:00
Khronos
5900d8442c Fix a problem with extra build commands. (#14528)
When --compileOnly is on, extraCmds are not added to JsonBuildInstructions.

```
$ echo 'echo 123'>test.nim
$ nim c --debuginfo --nimcache:cache test
$ ls
cache test test.dSYM test.nim
$ tail -n3 cache/test.json
"extraCmds": ["dsymutil /Users/khronos31/src/tmp/test"],
"stdinInput": false
}
```

```
$ echo 'echo 123'>test.nim
$ nim c --debuginfo --nimcache:cache --compileOnly test
$ nim jsonscript --nimcache:cache test
$ ls
cache test test.nim
$ tail -n3 cache/test.json
"extraCmds": [],
"stdinInput": false
}
```
2020-06-01 14:06:25 +02:00
Ico Doornekamp
0489e76da7 manual: removed subjective phrase from 'macros' section (#14536)
Removed phrase "However, this is no real restriction because
Nim's syntax is flexible enough anyway." from the manual - I find it
very subjective, and I sometimes *do* find myself restricted by Nim's
syntax when writing DSLs
2020-06-01 14:02:17 +02:00
Andreas Rumpf
8710395a0f fixes #14514 [backport:1.2] (#14533) 2020-06-01 12:33:13 +02:00
Danil Yarantsev
5d0cf883c1 Disable unused warnings for error await template too (#14531) 2020-06-01 11:56:07 +02:00
Timothee Cour
004b0759c5 fix CI doc windows: style error in lib/std/time_t.nim (#14523) 2020-05-31 14:57:16 -07:00
Danil Yarantsev
5150186c68 Disable unused warnings for await in async macro (#14517)
* Disable unused warnings for await in async macro

* Remove used for the error template
2020-05-31 12:43:27 +02:00
Araq
177c7f96e9 spec: be explicit that NRVO will evolve further 2020-05-30 19:55:01 +02:00
Araq
984af3d64e document NVRO and exception handling 2020-05-30 19:50:11 +02:00
Andreas Rumpf
52c3633223 warn about observerable stores but don't prevent them for 1.2.2 [backport:1.2]; refs https://github.com/nim-lang/RFCs/issues/230 (#14510) 2020-05-30 19:38:51 +02:00
Andreas Rumpf
7ccc7d7e93 fixes #14498 [backport:1.2] (#14503) 2020-05-30 15:32:31 +02:00
Andreas Rumpf
3105909f88 fixes #14495 [backport:1.2] (#14496) 2020-05-29 23:35:57 +02:00
Timothee Cour
cb6eb5268f enable compiler docs with their own index+search (#14493)
* enable compiler docs (with its own index)
2020-05-29 22:11:41 +02:00
Timothee Cour
63d1a0289e fix #14421 items uses lent T (#14447)
* fix #14421 items uses lent T for seq + openArray
* add -d:nimWorkaround14447
* fix test
2020-05-29 17:10:59 +02:00
Timothee Cour
e646c16e06 hotfix doc comments for procs without body (#14494) 2020-05-29 05:30:36 -07:00
Andreas Rumpf
e31ac81899 more checking for --gc:arc, no need for valgrind (#14467)
* sigmatch: removed dead code
2020-05-29 12:08:17 +02:00
Neelesh Chandola
4c08e64e98 disallow typedesc in arrays & move existing checks to types.typeAllowedAux (#13261)
* disallow typedesc in arrays and move previous checks to types.typeAllowedAux
2020-05-29 11:48:15 +02:00
Timothee Cour
579456d520 fix #14485 (#14487) 2020-05-28 19:00:36 -07:00
Timothee Cour
e013ebc91a fix #8871 runnableExamples now preserves source code comments, litterals, and all formatting; other bug fix (#14439)
* fix #8871 runnableExamples now preserves source code comments, litterals, and all formatting
* remove orig deadcode from getAllRunnableExamplesImpl
* fix expected examples
* add test to close https://github.com/nim-lang/Nim/issues/14473
* correctly handle regular comments before 1st token inside runnableExamples
* add test to answer https://github.com/nim-lang/Nim/pull/14439#discussion_r431829199
* update tests
2020-05-28 20:46:06 +02:00
Timothee Cour
17d08ff71c close #14284 document semantics for start for re,nre; improve examples (#14483) 2020-05-28 20:43:36 +02:00
Timothee Cour
fe7a2d60f9 make it easier to figure out how to debug issues (#14477) 2020-05-28 01:19:12 -07:00
Kaushal Modi
e62ccaa4dc Propagate the outDir to rstgen to fix hrefs for modules in subdirs (#14479) 2020-05-28 00:13:24 -07:00
Andreas Rumpf
1fc40db984 drnim improvements (#14471) 2020-05-27 18:14:24 +02:00
Huy Doan
00fa7a5747 Add thiscall calling convention, mostly for hooking purpose (#14466)
* Add thiscall calling convention, mostly for hooking purpose
* add changelog and documentation
2020-05-27 16:24:47 +02:00
Ivan Bobev
cc65ae6011 Change UnpackError with UnpackDefect (#14457)
* Change `UnpackError` with `UnpackDefect`

The deprecation warning for `UnpackError` exception raised by some
`inline` procedures in the Nim standard library propagates to the user
code. If the user code has a requirement for building without warnings
this is a problem for the successful execution of the tests. In order
to resolve this, all occurrences of `UnpackError` in the Nim code base
are changed to `UnpackDefect`. Only the type alias is retained to not
break other people's user code since `UnpackError` is exported type.

* Remove the catching of `UnpackDefect`

Defect exceptions should not be cached, because they indicate problem in
the API usage. The code in `nimblesocket.nim` is rewritten to first
check whether there is a value set into the `knownDomain` variable from
the `Option` type before usage.
2020-05-27 08:34:13 +02:00
alaviss
0533c43547 Revert "niminst: use threaded compression when supported (#14455)" (#14462)
This reverts commit b749d58ea1.
2020-05-27 08:33:24 +02:00
Andreas Rumpf
dadc97d91e typo 2020-05-26 14:49:44 +02:00
alaviss
b749d58ea1 niminst: use threaded compression when supported (#14455) 2020-05-26 14:05:51 +02:00
Timothee Cour
38cb277653 docgen: mangling using _. instead of @@ to avoid issue (#14454) 2020-05-26 10:08:35 +02:00
Bung
2a4a43b05f add bindParams to db_sqlite (#14408)
* add bindParams to db_sqlite
* no need typeinfo
* remove extro spaces
* reduce bindParams to two branches,raise DbError
* Update lib/impure/db_sqlite.nim
* change bindParams to macro,accept varargs[untyped] as params
* change bind blob val to openArray[byte]
* remove unused err type
* explicitly using i32 param
* using import std/private/since
* SQLITE_OK to right hand

* bindParam val int using bindParam overload
* copy data by default
* change exec to template
* remove SqlPrepared procs unused varargs
* fix setupquery for prepared,reset first for exec prepared,add bindNull for literal nil

Co-authored-by: alaviss <leorize+oss@disroot.org>
2020-05-26 07:44:47 +02:00
Timothee Cour
55758920f4 docgen: fix #14448 show @@ as .. in href text (#14451) 2020-05-25 18:16:00 -07:00
Timothee Cour
acadda8da2 tnimblepathdollarfail.nim -> tests/nimble/tnimblepathdollar_fault to reduce false positives when searching for fail in CI logs (#14450) 2020-05-25 13:54:30 -07:00
Timothee Cour
f96555bd10 fix #9227 procs can now have multiple interleaved doc comments + runnableExamples and be docgen'd correctly (#14441)
* fix #9227 proc doc comments after 1st runnableExamples are not ignored anymore
2020-05-25 15:44:23 +02:00
cooldome
6635874a85 make get for options use lent T (#14442)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-05-25 15:31:02 +02:00
Timothee Cour
58282547f6 fix #6583, fix #14376, index+search now generated for all projects, many bug fixes with nim doc (#14324)
* refs #6583 fix nim doc output
* changelog
* change default for outDir when unspecified
* cleanups
* --project implies --index
2020-05-25 13:25:40 +02:00
Max Grender-Jones
cbfe9325c5 Add support for mktemps (#14347) 2020-05-25 12:18:35 +02:00
Andreas Rumpf
79e85cb0b5 manual.rst: updates [backport] (#14445) 2020-05-25 12:16:32 +02:00
Timothee Cour
a008f591e2 add test for define, undef (#14443) 2020-05-25 11:17:25 +02:00
treeform
acae3b02c7 Add clipPath to dom.nim. (#14435)
Just adds a single new css atribute, see: https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path .
2020-05-24 07:32:24 +02:00
hlaaftana
f70d01a7d5 fix repr(char) example assert (#14437) 2020-05-23 21:26:49 -07:00
genotrance
b012205b2e Fix #14057 - moveFile should overwrite on Windows (#14433) 2020-05-23 17:06:04 +01:00
Andreas Rumpf
c61f746629 avoid unsafe Nim features in preparation for --gc:arc (#14431) 2020-05-22 20:24:37 +02:00
Bung
6668b43409 add insert,tryInsert unify for postgres that need pk name (#14416)
* add insert,tryInsert unify for postgres that need pk name
* add ReadDbEffect to new procs
* add .since and changelog
* change since to 1.3
* Update lib/impure/db_postgres.nim

Co-authored-by: bung87 <crc32@qq.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
Co-authored-by: alaviss <leorize+oss@disroot.org>
2020-05-22 19:24:52 +02:00
Mildred Ki'Lya
7b3dcfde20 Add missing attributes and methods to JavaScript DOM (#14428)
- content attribute to access HTML template element:
  https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement/content

- ownerDocument to access the owning document from a DOM Node:
  https://developer.mozilla.org/en-US/docs/Web/API/Node/ownerDocument

- outerHTML to get/set the outer HTML representation of a Node:
  https://developer.mozilla.org/en-US/docs/Web/API/Node/ownerDocument

- createComment() to create comment Nodes:
  https://developer.mozilla.org/en-US/docs/Web/API/Document/createComment

- querySelector() and querySelectorAll() on Nodes:
  https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector
  https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll
2020-05-22 14:34:20 +02:00
Timothee Cour
0d0ea3a11e no more code duplication bw liMessage and rawMessage + several bug fixes (#14415)
* no more code duplication bw rawMessage and liMessage; fixes some bugs in rawMessage
* all compiler messages work with hint:msgorigin
2020-05-22 12:02:10 +02:00
Andreas Rumpf
f7b73e6bfd make malloc.nim consistent in style (#14427) 2020-05-22 09:55:10 +02:00
Timothee Cour
149251cab9 [cleanup] fix UnusedImport sempass2 compiler/semparallel.nim (#14426) 2020-05-21 23:28:47 -07:00
Andreas Rumpf
3eaa870c0a ARC/ORC: optimize s.setLen(0) to match the old runtime's behaviour (#14423) 2020-05-21 22:38:13 +02:00
Andreas Rumpf
ddee8a362a change the [Processing] messages into dots (#14418)
* change the [Processing] messages into dots

* better implementation

* maybe I should work on something else...
2020-05-21 22:36:34 +02:00
Andreas Rumpf
063229a301 fixes a bug reported in https://forum.nim-lang.org/t/6361 (#14422) 2020-05-21 22:18:58 +02:00
Mamy Ratsimbazafy
f71f8b0239 The whole options module should be inline (#14417) [backport:1.2]
* The whole options module should be inline

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

* Remove lent annotation (failing at compiletime)
2020-05-21 17:52:40 +02:00
Timothee Cour
5caaa4bf6f fix #14404 foldr had the classic multiple evaluation bug (#14413) 2020-05-21 11:01:43 +02:00
Timothee Cour
e600ddc555 fix comment from e909486e5c (r39287564) (#14412) 2020-05-20 18:34:14 -07:00
Clyybber
6969a468ce Remove #PRTEMP leftover comment 2020-05-20 13:04:52 +02:00
Clyybber
7fe4c66f35 Small improvements for string and char repr with gc:arc (#14400)
* Small improvements for string and char repr with gc:arc

* Fix test
2020-05-20 12:54:04 +02:00
Timothee Cour
3d20f14193 fix #10731 ; runnableExamples "-b:cpp --run:off": code works (#14384)
* runnableExamples "-b:cpp -r:off": code
2020-05-20 09:45:34 +02:00
alaviss
4ae341353d asyncdispatch, asyncnet: add inheritance control (#14362)
* asyncdispatch, asyncnet: add inheritance control

* asyncnet, asyncdispatch: cleanup
2020-05-20 09:42:55 +02:00
Danil Yarantsev
1450924b1e Fix some typos in the manual [backport] (#14399) 2020-05-20 09:28:47 +02:00
Andreas Rumpf
16003bffe1 fixes #14126 [backport:1.2] (#14390)
* fixes #14126 [backport:1.2]

* used more logic to optimize it further; updated Nimble version
2020-05-20 00:41:57 +02:00
Andreas Rumpf
b35d370d88 specialize genericReset (#14398)
* progress
* make tests green
* maybe we also want to reset pointers, dunno
* progress
* cleanup; fixes #13879 [backport:1.2]
2020-05-19 21:42:53 +02:00
Timothee Cour
e909486e5c trunner was not actually being tested in non-CTFFI mode; minor testament cleanups (#14377)
* use check
* trunner now works with cpp
* cleanup: move compiler/unittest_light => stdtest/unittest_light
* fix tests/readme.md
* remove deadcode references to rodfiles
* fix for windows
2020-05-19 09:41:31 +02:00
Ștefan Talpalaru
27741d6a5c fix #14364 (#14372) [backport:1.2]
Turn on the TLS emulation when using Boehm, since it doesn't scan the
real TLS.
2020-05-18 23:44:04 +02:00
Clyybber
ac65986aae Fix #14394 (#14395) 2020-05-18 17:43:06 +01:00
Timothee Cour
2627e1e945 refs #14369 improve docs for importcpp exceptions (#14391)
* refs #14369 improve docs for importcpp exceptions

* address comments
2020-05-18 17:10:30 +01:00
cooldome
810039ec0b docs:getCurrentException() and getCurrentExceptionMsg() are not available for imported exceptions (#14392) 2020-05-18 08:15:10 -07:00
Timothee Cour
5beed56d0a fix #14174 do not collapse pragma inside runnableExamples (#14385) 2020-05-18 11:03:34 +02:00
cooldome
bc42e9aa98 fix #14369 (#14386)
* fix #14369

* empty commit
2020-05-18 09:38:36 +02:00
Timothee Cour
b11ff518fa fix #12293 findNimStdLibCompileTime should not break with nimble install compiler (#14334)
* fix #12293 findNimStdLibCompileTime should not break with nimble install compiler

* address comment to unblock PR
2020-05-18 09:38:12 +02:00
Miran
69cc1ddc4d install gtk3 on osx for package testing (#14388) 2020-05-18 09:03:01 +02:00
Timothee Cour
51578be296 close #12746; minor cleanup (#14379) 2020-05-17 13:28:18 +02:00
Frank Schmitt
42e80829c7 docs: fix syntax error in hotCodeReloading example (fixes #14380) (#14381)
Co-authored-by: Frank Schmitt <frankschmitt@gmx.de>
2020-05-17 12:44:36 +02:00
John
40ac19572a add OpenBSD MAP_STACK for coroutines (#14353) 2020-05-16 21:56:52 +02:00
Andreas Rumpf
7f377da1d2 fixes #14370 (#14371) 2020-05-16 17:03:25 +02:00
Dominik Picheta
7361e2627b Emscripten: disable epoll (#14361)
Epoll is not supported by epoll.
2020-05-16 15:50:41 +02:00
Bung
390ff428f0 add SqlPrepared api fix #13559 (#14365)
Co-authored-by: bung87 <crc32@qq.com>
2020-05-16 15:50:04 +02:00
Timothee Cour
c777f2fb60 fix some issues with --backend (#14363)
* fix some issues with --backend
* fix https://github.com/timotheecour/Nim/issues/175; improve upon #14306
2020-05-16 13:09:18 +02:00
Bung
c32e1378eb docfix: fix wrong link in doc/manual.rst (#14367) 2020-05-16 03:04:39 -07:00
Kaushal Modi
bf0e1c696f Remove the uses of {.procvar.} pragma (#14359)
This pragma did nothing.

Ref:
- https://github.com/nim-lang/Nim/issues/2172#issuecomment-383276469
- https://github.com/nim-lang/Nim/issues/12975
2020-05-15 23:37:24 +02:00
Bung
ce0552c100 fix #9771 (#14357)
* fix #9771
* map SQLLEN SQLULEN
* fix proc params take TSqlLen

Co-authored-by: bung87 <crc32@qq.com>
2020-05-15 21:00:06 +02:00
Clyybber
9f78f116b2 New "ping-pong" DFA (#14322)
* New ping-pong analysis

* Add testcase for #13456

* Remove debugging leftover

* Unquote "unstructured controlflow"

* Fix typo

* Fix exponential complexity in edge cases

* Add sanity testcase

* Fix
2020-05-15 19:24:43 +01:00
PMunch
13cfaf5fd5 Improve nimeval, changes some defaults (#14351)
* Improve nimeval, changes some defaults

This improves nimeval to make it easier to use NimScript as an embedded
scripting languages. It does change some of the defaults, so in case
anything used the old version and depended on the old behaviour these
would have to be changed.

* Remove dependency on nimhcr for nimscript
2020-05-15 19:32:52 +02:00
Danil Yarantsev
105079e88a Speed up testing of some packages (#14358) 2020-05-15 16:26:03 +02:00
hlaaftana
80c360fceb fix #14350, cstrings in JS init as null (#14355)
* fix #14350, cstrings in JS init as null
2020-05-15 10:07:30 +02:00
Araq
278b4582f5 fixes #14340 2020-05-14 08:51:47 +02:00
Kaushal Modi
a2a3fa1039 Fail quickly if re or nre module is attempted to be compiled with js [backport] (#14341)
Fixes https://github.com/nim-lang/Nim/issues/14338 .
2020-05-14 07:27:57 +02:00
cooldome
5fb40af57e fix #14333 (#14336)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-05-13 23:57:05 +02:00
Andreas Rumpf
82870e0737 fixes #13998 [backport:1.2] 2020-05-13 23:56:40 +02:00
Araq
8a339d1178 fixes #13862 2020-05-13 23:56:40 +02:00
Andreas Rumpf
f3e17e7c77 fixes #13104 [backport] 2020-05-13 22:29:02 +02:00
Andreas Rumpf
79fe87500f fixes #13935 2020-05-13 22:17:38 +02:00
Timothee Cour
3573a4f9c1 no more guessing where compiler msgs came from (#14317) 2020-05-13 17:19:44 +02:00
Araq
a3719df8b3 fixes #14331 2020-05-13 14:29:53 +02:00
Timothee Cour
041ee92bba osproc.execCmdEx now takes an optional input for stdin, env, workingDir (#14211)
* `osproc.execCmdEx` now takes an optional `input` for stdin

* execCmdEx now also takes an optional ``workingDir` and `env`
2020-05-13 13:45:36 +02:00
Timothee Cour
1648f1dd99 fix #14320 (tasyncawait.nim is recently very flaky) + avoid hardcoding service ports everywhere + flakyAssert (#14327)
* hotfix #14320 tasyncawait.nim is recently very flaky
* fix #14327
* add flakyAssert
2020-05-13 11:05:47 +02:00
PMunch
9acbf99efb Allow let to not have value when using importc (#14258)
* Allow let to not have value when using importc

This allows a let statement with the `{.importc.}` pragma to not be
initialised with a value. This allows us to declare C constants as Nim
lets without putting the value in the Nim code (which can lead to
errors, and requires us to go looking for the value). Fixes #14253

* Proper fix and documentation + changelog entry

* Improve testcase with one from timotheecour

* Add test to verify it working with macros
2020-05-12 20:28:18 +02:00
Araq
82f008158c cycle collector: make it threadsafe 2020-05-12 20:13:06 +02:00
b3liever
09ea8f9cf8 fix detecting closure env for nested asts (#14326)
Co-authored-by: b3liever <b3liever@yandex.com>
2020-05-12 20:09:56 +02:00
Timothee Cour
dddfbcf211 close #13071 by adding test: nim cpp -r --gc:arc` segfaults on caught AssertionError (#14323) 2020-05-12 19:19:31 +02:00
Timothee Cour
de74362213 fix #14314 do not analyze importc procs for effects (#14319) 2020-05-12 16:19:03 +02:00
Andreas Rumpf
06dfd31612 fixes #13881
* fixes #13881
* documented changed requirements for system.onThreadDestruction
* destructors.rst: update the documentation
2020-05-12 15:46:24 +02:00
cooldome
4277ab470a fix one motr dicriminator bug 2020-05-12 12:45:34 +01:00
cooldome
dfae796ac3 fix test 2020-05-12 11:45:14 +01:00
cooldome
2d7ccf0928 fix #14312 2020-05-12 10:23:05 +01:00
Avahe Kellenberger
55446c05a4 Added a reference to ternary operators. (#14309)
`if expressions` are similar to ternary operators in other languages.
In order to make this easier to find in the manual, I've added a
sentence about it.
2020-05-12 08:28:10 +02:00
Timothee Cour
b8ec07f19e properly fixes #13758 so that import std/macros stays legal (#14291)
* properly fix https://github.com/nim-lang/Nim/issues/12389
* use --lib:lib in koch.nim.cfg instead
* third time is the charm
2020-05-12 08:27:47 +02:00
cooldome
a39123c93c fix #14219 (#14225)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-05-11 23:11:20 +02:00
Kaushal Modi
86669ef5b4 Make --backend:cpp|js work for :test: code-blocks as well (#14306)
Continues 9502e39b63

Ref:
- 9502e39b63 (commitcomment-39087584)
- https://github.com/nim-lang/Nim/pull/14278

Fixes https://github.com/nim-lang/Nim/issues/13129 .
2020-05-11 20:45:35 +02:00
slangmgh
76f7e95814 Fix #14289 (#14304) [backport] 2020-05-11 19:17:37 +02:00
Andreas Rumpf
0f344a70c9 fixes #13946 (#14302) 2020-05-11 19:12:40 +02:00
b3liever
a081b10b54 small refactoring (#14303)
Co-authored-by: Antonis <b3liever@yandex.com>
2020-05-11 19:12:25 +02:00
cooldome
fee71d466c fix #14294 (#14301)
* fix #14294

* fix orc as well

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-05-11 19:10:54 +02:00
Andreas Rumpf
03c146cd93 do not track 'raise Defect' in the .raises: [] clause anymore (#14298)
* do not track 'raise Defect' in the .raises: [] clause anymore

* --panics:on maps 'raise Defect' to an unrecoverable fatal error

* make tests green again

* update the documentation too
2020-05-11 16:25:56 +02:00
Antonis
517dd800f8 better error message 2020-05-11 15:39:44 +02:00
Antonis
3616b0698b fix closure env check 2020-05-11 15:39:44 +02:00
Antonis
73c9d2c9d7 Fix for --styleCheck:error 2020-05-11 15:39:44 +02:00
Jovial Joe Jayarson
14f76f721d refactor: renamed readme to readme.md (#14283) 2020-05-11 13:50:40 +02:00
Timothee Cour
9502e39b63 nim doc --backend:js, nim doc --doccmd:-d:foo, nim r --backend:js, --doccmd:skip + other improvements (#14278)
* `nim doc --backend:js|cpp...`
`nim doc --doccmd:'-d:foo --threads:on'`
`nim r --backend:cpp...` (implies --run --usenimcache)
* --usenimcache works with all targets
* --docCmd:skip now skips compiling snippets; 50X speedup for doc/manual.rst
2020-05-11 12:01:18 +02:00
Timothee Cour
d11cb9d495 fix a critical bug in windows.osproc leading to resource leaks and blocking IO [backport] (#14296) 2020-05-11 11:14:21 +02:00
Andy Davidoff
8018449319 simple typo in locks.nim (#14297) 2020-05-11 02:59:31 -04:00
Timothee Cour
7c24250a57 diable nimx (CI failure) refs https://github.com/timotheecour/Nim/issues/167 (#14293) 2020-05-10 18:56:00 -04:00
Timothee Cour
dda6f3f6d4 nim doc -r main and nim rst2html -r main now call openDefaultBrowser (#14285) 2020-05-10 09:23:01 +02:00
Clyybber
8e93105606 Fix #14269 (#14286) 2020-05-09 18:22:25 +02:00
Timothee Cour
411be506a3 --hint:processing (+friends) is now supported and means --hint:processing:on, like all other bool flags (#14271) 2020-05-08 18:54:16 +02:00
Andreas Rumpf
ce16115e79 Merge pull request #14265 from alaviss/quickfix
nativesockets: add missing inheritable pass-through
2020-05-08 17:33:38 +02:00
Andreas Rumpf
bae8e95b73 fix root cause of https://github.com/dom96/choosenim/issues/193; config/config.nims should get installed (#14267) 2020-05-08 16:14:10 +02:00
Clyybber
4bd77cf045 Fix typo 2020-05-08 16:13:53 +02:00
Timothee Cour
363b7ff3b8 fix https://github.com/nim-lang/Nim/issues/14275 querySetting(nimcacheDir) works even if implicitly set (#14277) 2020-05-08 16:13:07 +02:00
Clyybber
120ea906fb Fix #14270 and add testcases (#14276) 2020-05-08 15:54:34 +02:00
hlaaftana
de27910ab7 make from an operator (#14241) 2020-05-08 07:54:46 +02:00
Timothee Cour
ee15437aed fix root cause of https://github.com/dom96/choosenim/issues/193; config/config.nims should get installed 2020-05-07 15:01:46 -07:00
cooldome
5fa7d374c4 fix #14243 (#14257)
* fix #14243

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-05-07 22:15:25 +02:00
alaviss
83435fe696 tslow_tables: wait for an additional 2 seconds (#14266)
This test runtime tends to hover around the 5s mark depending on how
loaded the system currently is. This causes the test to fail a lot
during CI, per analytics:
https://dev.azure.com/nim-lang/Nim/_test/analytics?definitionId=1&contextType=build

Give the test an extra 2 seconds to account for unrelated overhead.
2020-05-07 22:07:08 +02:00
Leorize
73a42ce941 nativesockets: add missing inheritable pass-through 2020-05-07 14:43:53 -05:00
Clyybber
42db75c970 Fix the DFA for "unstructured controlflow" (#14263)
* Fix the DFA for "unstructured controlflow"

* Add testcase from #14233
2020-05-07 21:41:55 +02:00
alaviss
1a1e9986a3 net: remove more erroneous set constructions (#14252) [backport]
Refs #13764
2020-05-07 13:37:54 +02:00
Miran
5a9b3c27c1 Split testing important packages into two jobs (#14256)
* split testing packages in two separate jobs
* speed-up the slowest tests
* special treatment for two packages
2020-05-07 10:08:05 +02:00
cooldome
0d8507cd3d fix #14236 (#14250)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-05-07 00:13:59 +02:00
cooldome
6dba06f9e6 fixes #14244 (#14248)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-05-06 20:43:18 +02:00
awr1
b70b8a7cdd Fix runnable examples for bitops (#14247) 2020-05-06 19:29:36 +02:00
Andreas Rumpf
c64db68f0b added a new feature: --cc:env so that you can use any C compiler as long as it works like GCC 2020-05-06 18:41:24 +02:00
Andreas Rumpf
1b2b32169a cleanup the CC setting, only leave in there what is at least semi-officially supported 2020-05-06 18:41:24 +02:00
Timothee Cour
330b3c4453 fix regression: -d:nimHasLibFFI was not being tested anymore (#14234)
* * fix regression: -d:nimHasLibFFI was not being tested anymore,
in part because testament was silently treating some errors as easy to overlook messages
* turned that message into an error
* -d:nimHasLibFFI is now being tested with nim cpp
* use correct signatures for importc procs
* workaround for openbsd to unblock ctffi testing
2020-05-06 17:16:54 +02:00
awr1
b8e6ea7547 Added bitslice operations for bitops (#14016)
* added bit operations based on bit slices, clarified documentation, made non-mutating versions of mask ops
* Added since annotations, some runnable examples
* Added mask()/masked() functions, changed internal workings of mask ops to use new bit* funcs
* Changelog updated for new bitops improvements
* Reorganization, added runnable examples
* Documentation adjustments
* Add incltrl for since annotation
* Fix masked() impl
* Fix mask() return type
* Don't call toUnsigned on already unsigned types
* Remove improper `var T` for flipMasked()
* Fix return types for flipMasked()
* Slight syntactic cleanup for *masked ops
* Added tests for bitslice operations, new mask() operation, non-mutating mask ops
* Fix setmasked() var T issue
* More comprehensive tests
* Fix runnable example for bitsliced()
* Fix runnable example for mask()
2020-05-06 12:21:49 +02:00
Oscar Nihlgård
48e7775ad1 Make the fields of times.DateTime private (#14197)
* Make the fields of `times.DateTime` private

* PR fixes
2020-05-06 12:20:34 +02:00
Timothee Cour
c28a057a6b fix js stacktraces, unify all file,line,col formatting into a single function (#14230)
* fix https://github.com/timotheecour/Nim/issues/135 ; unify all file,line,col formatting into a single function
2020-05-05 14:56:15 +02:00
hlaaftana
6b7b5fb4fa Clarify JS cstring len (#14184) 2020-05-05 10:34:37 +02:00
cooldome
eefada8a88 fix #14217 (#14218)
* fix #14217

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-05-05 07:26:32 +02:00
Andreas Rumpf
64e839d5fd fixes #14209 [backport:1.2] (#14213)
* fixes #14209 [backport:1.2]
* improve stability
2020-05-05 00:48:13 +02:00
cooldome
e86a6d24d5 vcc fix (#14222)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-05-04 19:42:29 +02:00
wltsmrz
c817e85f4c Linux updates (#14170)
* Add posix_memalign()

* Add linux-specific open() flags

O_TMPFILE: since Linux 3.11
O_PATH: since Linux 2.6.39
O_NOATIME: since Linux 2.6.8
O_DIRECT: since Linux 2.4.10

* Fix Stat type

* Fix POSIX AF_INET* const generation
2020-05-04 19:23:49 +02:00
PMunch
44f377ff5e Add procedures to read RSA keys from BIO format (#14223) 2020-05-04 19:23:11 +02:00
Timothee Cour
a23302ef56 fix https://github.com/timotheecour/Nim/issues/152: avoid writing spurious ^[[0m to stderr when callStyledWriteLineStderr not called (#14214)
* fix https://github.com/timotheecour/Nim/issues/152 `^[[0m` is inserted in stderr for `echo code | nim c -`

* resetAttributes not even needed, already handled in styledWriteLine

* simplify tests in tests/trunner.nim thanks to this fix
2020-05-04 15:07:32 +02:00
Tristram Oaten
927737975c Re-enabling INim (#14215) 2020-05-04 15:07:04 +02:00
rockcavera
603010f8c9 Fixes net.recvFrom to work correctly with IPv6 (#14131)
* added high level sendTo and recvFrom to std/asyncnet; tests were also added.
* add .since annotation, a changelog entry and fixed to standard library style guide.
* fixes net.recvFrom to work correctly with IPv6
* raise if domain is not AF_INET or AF_INET6
* renamed template to adaptRecvFromToDomain()
2020-05-04 11:54:08 +02:00
Timothee Cour
f115e40e6a echo cmd | nim r - -arg1 -arg2 now works (#14210) 2020-05-04 11:27:59 +02:00
Andreas Rumpf
a73d403901 sequtils refactoring: prefer typeof over type (#14212) 2020-05-04 11:18:29 +02:00
Andreas Rumpf
b6fb609e0d destructors: don't produce stupid code for 'cast' (#14208) [backport:1.2]
* destructors: don't produce stupid code for 'cast'

* fixes #14207
2020-05-04 07:43:22 +02:00
hlaaftana
3e060cfb0a => supports pragmas & names (+ changed behavior) (#14200)
* => supports pragmas & names (+ changed behavior)

(x, y: int) is now parsed as (x: int, y: int) instead of
(x: auto, y: int) inside => and ->.

* fix pragma check

* fixes, use since & LHS of -> supports pragmas
2020-05-03 10:22:49 +02:00
slangmgh
b56432bd8a fix #14203 (#14204) 2020-05-03 09:50:08 +02:00
slangmgh
d5c014e59b Fix #14151 (#14205) [backport] 2020-05-03 09:47:21 +02:00
slangmgh
b447ff7860 Fix #14201 (#14202) 2020-05-03 09:46:42 +02:00
Andreas Rumpf
49b28f1997 fixes #14136 (#14198) 2020-05-03 00:12:52 +02:00
hlaaftana
fbc97e712a move since from inclrtl to std/private/since (#14188)
* move since from inclrtl to std/private/since
* move since import in system below for HCR
2020-05-02 23:51:59 +02:00
Dien Tran
3be669be32 Move generated tex file to doc to correct location (#14191) 2020-05-02 23:49:08 +02:00
Araq
ff1c0bae4c update tests that tested for the 'discard' error messages 2020-05-02 22:31:19 +02:00
Araq
7f1d2489ad improve the 'has to be discarded' error message 2020-05-02 22:31:19 +02:00
Araq
87ac28d19a fixes #14159 [backport:1.2] 2020-05-02 22:31:19 +02:00
Araq
4301a7bdf0 fixes #14177 2020-05-02 22:31:19 +02:00
Araq
7bac6f5f9a don't close #14142 2020-05-02 22:31:19 +02:00
Araq
8e04ef3c0f closes #14142 2020-05-02 22:31:19 +02:00
Araq
15f54728ef fixes a bug encountered when running 'nim check posix_haiku.nim' 2020-05-02 22:31:19 +02:00
hlaaftana
f50377986a exp. features now in correct manual, closes #11932 (#14195) 2020-05-02 22:30:08 +02:00
Kaushal Modi
0880f118d3 Document that proc named fooTask is created for every foo task [backport] (#14187)
Ref: https://irclogs.nim-lang.org/01-05-2020.html#15:18:03
2020-05-02 17:50:27 +02:00
Clyybber
83547ec769 Make unreachable else in case statements a warning instead of an error (#14190)
* Fix #14019 by making trailing else a warning

* Rename to UnreachableElse
2020-05-02 16:09:02 +02:00
Clyybber
1f1e4de3bc Make ./koch temp --gc:arc work (#14186) 2020-05-01 20:25:18 +02:00
Miran
9c33bcac5c change 'iff' to 'if' to stop "corrections" once and for all (#14182) 2020-05-01 15:54:03 +02:00
hlaaftana
9b01c6cf48 discardable async procs are now an error (#14176)
* add discard warning in manual
2020-05-01 09:49:13 +02:00
Andreas Rumpf
d5fc35c968 arc: do not unload globals when building a library [backport:1.2] (#14180) 2020-05-01 09:15:46 +02:00
rockcavera
33e9ac7cd3 fix sendTo and recvFrom in asyncnet (#14154)
* added high level sendTo and recvFrom to std/asyncnet; tests were also added.

* add .since annotation, a changelog entry and fixed to standard library style guide.

* Improved asserts msgs and added notes for use with UDP sockets

* pointers removed in parameters and fixes

* added .since annotation

* minor fixes
2020-04-30 22:50:37 +02:00
Araq
6b39b47abc hotfix: make tcompilerapi green again 2020-04-30 22:48:10 +02:00
Andreas Rumpf
89be5be03e fixes #13698 [backport:1.2] (#14175) 2020-04-30 22:45:02 +02:00
Araq
3d2459bdc0 fixes the regression #12860 caused; hotfix 2020-04-30 20:23:53 +02:00
Andreas Rumpf
cf3e0008b9 fixes #13986 [backport:1.2] (#14173) 2020-04-30 19:32:03 +02:00
hlaaftana
0aefebb728 JS unittest stacktrace fix, cleanup js repr and inclrtl includes (#14168) 2020-04-30 17:04:53 +01:00
narimiran
4d799f8820 test even more packages 2020-04-30 13:03:48 +02:00
narimiran
d844d10e8e [ci skip] clean-up CI badges 2020-04-30 10:19:18 +02:00
narimiran
f1068c01a8 [ci skip] prevent fail-fast on packages CI 2020-04-30 10:11:18 +02:00
Andreas Rumpf
cc60caedb3 fixes #14054 [backport:1.2] (#14061)
* fixes #14054

* make tests green again

* more tests are green

* maybe now
2020-04-30 06:48:57 +02:00
Clyybber
d6e1b5c070 Fix #14160 (#14161)
* Fix #14160

* Add testcase
2020-04-30 02:01:07 +02:00
Araq
bd57f0cd32 fixes another silly arc/orc bug [backport:1.2] 2020-04-29 22:14:01 +02:00
Andreas Rumpf
d9e907c0e2 fixes #14079 [backport:1.2] (#14163) 2020-04-29 21:58:59 +02:00
hlaaftana
707367e1ca many bugfixes for js (#14158)
* many bugfixes for js

fixes #12672, fixes #14153, closes #14123, closes #11331, fixes #11783, fixes #13966, fixes #14087, fixes #14117, closes #12256.

mostly fixes the fact that it was allowed to assign to newly created temp variables. additionally attempts to get rid of null initialized seqs/strings (though they might pop up here and there); this simplifies a lot of things and makes code size smaller. even if null seqs/strings pop up here and there it's still better than all those bugs existing.

* formatting fixes

* CI fixes

* more CI fixes
2020-04-29 20:55:09 +02:00
Tristram Oaten
a297c016fa Remove travis ci badge (#14062) 2020-04-29 17:06:14 +02:00
hlaaftana
800ce5b950 Fix negative indexed arrays for JS, refs #13966 (#14152)
* Fix negative arrays for JS, refs #13966

* small extra fix: no need to .slice() cstring in JS
2020-04-29 08:59:08 +02:00
cooldome
3b5a504692 parseEnum_regression (#14150)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-28 19:56:50 +02:00
Jacek Sieka
7d6cbf290a Error -> Defect for defects (#13908)
* Error -> Defect for defects

The distinction between Error and Defect is subjective,
context-dependent and somewhat arbitrary, so when looking at an
exception, it's hard to guess what it is - this happens often when
looking at a `raises` list _without_ opening the corresponding
definition and digging through layers of inheritance.

With the help of a little consistency in naming, it's at least possible
to start disentangling the two error types and the standard lib can set
a good example here.
2020-04-28 19:56:01 +02:00
hlaaftana
cd9af6b804 StringStream & more stdlib modules support for JS/NimScript (#14095)
* StringStream & more stdlib modules support for JS/NimScript

* change back pegs test in line with #14134
2020-04-28 19:44:52 +02:00
narimiran
d5ed4fba3e test packages with Github workflows 2020-04-28 18:14:34 +02:00
cooldome
289d48e5fe bug fix (#14149) [backport:1.2]
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-28 18:02:14 +02:00
narimiran
e63fc95bd4 fix tdistros test which was failing on Nightlies 2020-04-28 15:59:32 +02:00
hlaaftana
82fc66b607 Update grammar.txt with func and as (#14147) [backport] 2020-04-28 10:57:35 +02:00
Miran
e1dab59d46 add 14 more packages to 'important_packages' (#14141) 2020-04-28 07:28:48 +02:00
Andreas Rumpf
065a6af2de fixes a critical =trace generation bug (see test case) (#14140) 2020-04-27 22:20:14 +02:00
PMunch
2f1aad0264 Add RSA key reading and encrypt/decrypt to openssl (#14137)
This adds the procedures to read RSA keys and encrypt/decrypt messages
with both public and private keys.
2020-04-27 21:01:56 +02:00
Neelesh Chandola
d38853c504 Undefine paramCount & paramStr in nimscript.nim for *.nims (#12860)
* Remove `paramStr` and `paramCount` from implicitly imported nimscript.nim
* Update changelog.md
* Update stable nimble commit hash

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-04-27 19:16:40 +02:00
Timothee Cour
a3a317b76d $ now works for unsigned intergers with nim js (#14122)
* $(unsigned) now works for js
* move NimMajor+friends closer to NimVersion according as per reviewer feedback
2020-04-27 19:15:17 +02:00
PMunch
0e6eb96a5f Fix #14066 issue with stringifying incomplete types (#14135) 2020-04-27 18:43:02 +02:00
Timothee Cour
bb982c644b $(a: float) now works consistently in nim js, avoiding printing floats as ints (#14134)
* fix https://github.com/timotheecour/Nim/issues/133; $(a: float) works in nim js like in other backends

* fix tests

* fix test for windows that prints 1.1e17 differently than other OS
2020-04-27 17:33:03 +02:00
Oscar Nihlgård
664cb2c0be Remove some deprecated procs from std/times (#14129) 2020-04-27 14:42:29 +02:00
Timothee Cour
b8d7a98265 fix #14132 dsymutil should not be called on static libraries (#14133) [backport:1.2] 2020-04-27 12:39:27 +02:00
Andreas Rumpf
dedb04fa9e new implementations for --gc:orc (#14121)
* cycle collector: new implementation
* cycle collector: make self-adaptive based on its previous effectiveness
* cycle collector: added Lins's jump stack to improve traversal from 3*N to 2*N
* cycle collector: make tests green
* API extensions and bugfixes
* code cleanup and use --gc:orc for tasyncawait
2020-04-27 11:57:26 +02:00
cooldome
eaedd0cb94 add FileReader Web API to js dom (#14105)
* add FileReader to js dom
* minor improvement
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-27 00:08:11 +02:00
Timothee Cour
9384f7ad35 since now takes an optional patch, eg: since: (1, 3, 1) (#14124)
add tests for tinclrtl
2020-04-26 14:55:25 +02:00
rockcavera
d23446c6ba added high level sendTo and recvFrom to std/asyncnet (UDP functionality) (#14109)
* added high level sendTo and recvFrom to std/asyncnet; tests were also added.

* add .since annotation, a changelog entry and fixed to standard library style guide.

* Improved asserts msgs and added notes for use with UDP sockets
2020-04-26 10:16:10 +02:00
hlaaftana
76ffa4fa25 fixes #14112, tests for #12892, #12671, #11697 (#14125) 2020-04-26 10:12:16 +02:00
hlaaftana
31ba27590c small docs fix in typetraits (#14108) 2020-04-25 20:35:20 +02:00
Alexander Ivanov
56584414f3 Make await a template (#12085)
* Make await a template
* Generate await inside async/multisync
2020-04-25 20:27:03 +02:00
Christopher Dunn
caf30e7cb5 Faster readStr() (#14099)
* Faster readStr()

* https://github.com/nim-lang/Nim/issues/13857

* Add .since annotation and add to changelog

* Private, un-sinced proc for csource bootstrapping
2020-04-25 20:19:11 +02:00
Viktor Kirilov
018e297d66 HCR: properly handling complex const objects in the codegen - fixes #13915 (#14115) 2020-04-25 20:17:33 +02:00
Jae Yang
362c8964bf Fixes #14110 (#14111)
Fixes jsffi usage example in doc
2020-04-25 20:00:24 +02:00
cooldome
13fa338ada implement (#14114)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-25 19:59:56 +02:00
Euan
f3eeb3f921 Fix #14088 and #14089 on NetBSD (#14104)
* Set path to libSDL for NetBSD.

* Disable SFML test on NetBSD
2020-04-24 14:30:41 +02:00
Timothee Cour
706de1a566 add CI badges for CI github actions ssl+docs 2020-04-24 11:10:14 +01:00
Timothee Cour
d5b7e9902c fix nim CI; fix local testament (#14102) 2020-04-24 10:24:30 +02:00
Phil Krylov
d5d3594457 Add critbits.commonPrefixLen (#14072)
* Add critbits.commonPrefixLen

* add inline and since annotations, as well as a changelog entry

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-04-24 09:31:30 +02:00
hlaaftana
b2141fc2a1 changed type() to typeof() in docs and error messages (#14084) 2020-04-24 09:22:12 +02:00
alaviss
dd5ccc3e5a testament: don't try to test nimgrep if it's not there [backport:1.2] (#14085)
One more compiler source-specific tackled
2020-04-24 09:20:33 +02:00
hlaaftana
dff007f66d Make JS not mangle to snake_case (#14086) 2020-04-24 09:19:54 +02:00
Euan
123f9fb77a Fix #14091 and #14093 - test failures on NetBSD (#14096) 2020-04-24 09:18:44 +02:00
Timothee Cour
f07f07eef9 [ci skip] changelog conflicts are a thing of the past (#14098) 2020-04-24 09:16:20 +02:00
Timothee Cour
b18b1b0302 add CI badges for azure-pipelines for devel, 1.0, 1.2 branches (#14101) 2020-04-24 09:08:27 +02:00
Clyybber
eca8f1d79f Add tests for #8481, #6490 and #4061 (#14083) 2020-04-23 19:52:33 +02:00
Timothee Cour
66db9de714 CT sizeof(+friends) for {.importc, completeStruct.} types, enable ABI static checks (#13926)
* -d:checkabi obsolete (ABI check now enforced); add `addTypeHeader` helper
* cleanups
* import sizeof at CT for {.completeType.}
* address comments; revert default enabling of -d:checkAbi for now
* mimportc_size_check.nim => msizeof5.nim; merge mabi_check.nim into msizeof5.nim; refactor
* all pragmas in errmsgs should be written: '.importc' (un-ambiguous and less verbose than {.importc.})
2020-04-23 11:24:09 +02:00
Timothee Cour
5c534b2943 new cmd: nim r main [args...] to compile & run, saving binary under $nimcache/main (#13382)
* implement `nim r main` to compile and run, saving binary to $nimcache
* remove outFileAbs for now
2020-04-23 10:02:18 +02:00
alaviss
4b43d42b98 testament: don't rely on Nim source structure [backport:1.2] (#14077)
It's also just faster to get the current file name instead of scanning
the PATH.
2020-04-23 09:26:06 +02:00
Euan
0b4a475f2e Ref #14075 - enable two tests which seem to now be passing locally on FreeBSD. (#14076) 2020-04-22 23:35:22 +01:00
Keithcat1
d27bc03b21 Add LTO support for most compilers and do some VCC fixes (#14013)
* Added LTO in nim.cfg, added /link in extccomp.nim and other fixes

* Fix line endings

* Fix line endings, for real this time. Almost certainly. Like, 95% certain.

* Removed /MD from extccom.nim VCC comiler
2020-04-22 23:56:43 +02:00
Hiroki Noda
6cfe2e0c3d Set O_NONBLOCK flag atomically (#13934)
These flags were added in Linux 2.6.27, I'm not sure Nim's minimal
support Linux version.
2020-04-22 20:24:45 +02:00
Bung
e1cc0219de fix #14064 xmltree should allow create text node with raw text(non-es… (#14070)
* fix #14064 xmltree should allow create text node with raw text(non-escaped) eg. html style element's text

* change xnRawText to VerbatimText,newRawText to newVerbatimText ,add since anotation

* change changelog_1_2_0.md latest date

* move change log

Co-authored-by: bung87 <crc32@qq.com>
2020-04-22 19:46:55 +02:00
Chris Heller
6c0c882509 Make debugSend/debugRecv procs public. Fixes #12189 (#12190)
* Make debugSend/debugRecv procs public. Fixes #12189

* Make checkReply proc public. Part of #12189

* Add doc comments for debugSend,debugRecv and checkReply
2020-04-22 17:45:31 +02:00
wonderix
5571d48c32 Add the ability to pass title case headers to an HTTP server (#13968)
* Add the ability to pass title case headers to an HTTP server

* Remove unnecessary type spec of titleCase

* Replace convert member proc by isTitleCase

Co-authored-by: wonderix <wonderix@googlemail.com>
2020-04-22 17:43:39 +02:00
Andreas Rumpf
269a458d74 cycle collector (#14071)
* figured out the wrong cycle trace proc problem
* cycle collector/break refactorings and minor improvements
2020-04-22 17:34:35 +02:00
hlaaftana
01523b2b58 change some Exceptions to CatchableError or Defect, fixes #10288 (#14069) 2020-04-22 16:49:41 +02:00
Miran
5c26a83a4a use newer nodejs on Azure Pipelines (#14065) 2020-04-22 11:38:33 +02:00
Vindaar
d42c5a575d base parseEnum on a case statement, fixes #14030 (#14046)
* base `parseEnum` on a case statement, fixes #14030

* apply simplifactions / clean up, remove `norm` node, use strVal

* export `normalize` in json.nim

* cmp using nimIdentNormalize, error at CT if ambiguous enum found

`nimIdentNormalize` provided by @cooldome.

We track all names of the branches we have created so far and error if
a duplicate is found.

Dummy change to make github react...

* fix docstring of `nimIdentNormalize`

* make `typ` arg `typedesc`, add lineinfo, call norm. only once
2020-04-22 09:41:56 +01:00
Hessam Mehr
c3f4b93060 Treat zig like clang/gcc wrt integer arithmetic. (#13957) 2020-04-22 08:31:24 +02:00
alaviss
22418ce8fb tools/finish: don't quote path with space (#14058) [backport]
Path with spaces should be added as is, quoting them makes utilities
treat the quotes as part of the path. This makes `nim` unable to be used
from the command line even if it appears to be added to user's Path
environment variable.

Even more confusing, Windows 10's PATH editor shows the path without any
quotes, you only see them when you use "Edit text". Took me a good 15
minutes to figure out why couldn't I run `nim` despite it being in Path.
2020-04-22 07:51:18 +02:00
Timothee Cour
eb6f523733 fix globalOptions (#14059) 2020-04-22 07:50:38 +02:00
Arnaud Moura
dc40fb805f Fix OS detection in a docker container (#13172)
* Support detection in docker container.
* Get only ID information in os-release.
* Add test to distros module.
* Fix Linux OS detection in Windows.
* Fix OS detection for FreeBSD and OpenBSD.
2020-04-22 07:49:42 +02:00
Andy Davidoff
9604a5a97a fix typo (#14063) 2020-04-21 23:23:15 -04:00
Timothee Cour
7ce0358351 fix #13222: make relativePath more robust and flexible (#13451)
* * relativePath(foo) now works
* relativePath(rel, abs) and relativePath(abs, rel) now work (fixes #13222)
* relativePath, absolutePath, getCurrentDir now available in more targets (eg: vm, nodejs etc)
* fix bug: isAbsolutePath now works with -d:js; add tests
* workaround https://github.com/nim-lang/Nim/issues/13469
* remove `relativePath(path)` overload for now
* add back changelog after rebase
2020-04-21 23:53:55 +02:00
Araq
dd24004fab cleanup PR #14048 2020-04-21 23:27:19 +02:00
Andreas Rumpf
1b6c4ed2ba fixes #14052 [backport:1.2] (#14055) 2020-04-21 23:19:34 +02:00
hlaaftana
5608a4e57b Add deques.peekFirst/Last(var Deque[T]) -> var T (#13542)
* Add deques.peekFirst/Last(var Deque[T]) -> var T
* Add changelog entry for deques.peekFirst/Last var T overloads
* Add since annotation to peekFirst/peekLast

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-04-21 22:09:19 +02:00
Arnaud Moura
cb2b9bd797 Add package install command for FreeBSD and OpenBSD. (#14051) 2020-04-21 22:07:19 +02:00
cooldome
5db0bb744c Replace enum fields idents with syms (#14048)
* replace enum fields idents with syms
* Trigger build

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-21 20:12:32 +02:00
Oscar Nihlgård
218cbf0e09 Times refactorings (#13949) 2020-04-21 17:07:37 +02:00
Euan
7828199827 #12103 - CI for OpenBSD (#12105)
* Working on OpenBSD CI
* Condense steps into 2 steps to make output easier to follow.
* Move up one directory after csources build.
* Remove FreeBSD build manifest and add OpenBSD test ignores for coroutines and hot code reloading.
* If runCI fails, run the test results script.
* Add email trigger for build failure
* Remove .git from repository URL
* Disable SFML test on OpenBSD
* Disable tgetaddrinfo on OpenBSD as only UDP and TCP protocols are supported.
* Remove getFilePermissions as it causes CI test failures with NimScript.
* Set clang as cc in nim.cfg and use gmake to build csources.
* Add getCurrentDir to nimscript.
* Remove duplicate getCurrentDir and check for not weirdTarget.
* Add CI badge for OpenBSD.
* Disable tests which allocate lots of memory for OpenBSD.
* Use `CORO_BACKEND_SETJMP` on OpenBSD rather than ucontext.
* Simplify building of koch
* Disable t8657 on OpenBSD. See issue #13760.
* Fix #12142 - tarray_of_channels fails on OpenBSD
* Disable thhtpclient_ssl and tosprocterminate on OpenBSD. These tests can be enabled at a later date after fixing them.
* Install libffi.
* Set path to libc for openbsd.
* Disable tevalffi for now.
* Remove tevalffi.nim.
* Use ncpuonline sysctl rather than ncpu.
* Disable tacceptcloserace and tasynchttpserver on OpenBSD.
* Enable tacceptcloserace and tasynchttpserver.
* Fix #13775 as suggested by @alaviss - use /bin/cat on OpenBSD rather than /bin/sh.
* Enable test on OpenBSD.
* Disable tflowvar on OpenBSD.
2020-04-21 15:05:21 +02:00
treeform
89e6a7ab48 Fix the getSelection method. (#13632) 2020-04-21 14:57:19 +02:00
Rory O’Kane
b8b0e9b21d docs: move not nil to the experimental page (#14027)
When I heard that this feature existed, and found the 2018 changelog entry that said `not nil` was made experimental (https://github.com/nim-lang/Nim/blob/devel/changelogs/changelog_0_19_0.md#changes-affecting-backwards-compatibility), I looked for `not nil` documentation in https://nim-lang.org/docs/manual_experimental.html. When I didn’t find it there, I initially assumed the feature had no documentation. This change moves the documentation to where readers will expect it.

As well as moving the text to another file, I added instructions for enabling the experimental feature and tweaked some wording.
2020-04-21 14:54:43 +02:00
Judd
04c326569b fix mapIt issues #12625 & #12639 (#14041)
* fix mapIt issues #12625 & #12639:

1. fallback to call `map` when the result of `op` is a closure;
2. use `items(s)` in the for loop.

* fix test errors.

* add comments and InType is moved.

* fix ident.
2020-04-21 14:50:16 +02:00
Tristram Oaten
1a44b7e3ce New runnableExample for newAsyncHttpClient() (#14045) 2020-04-21 14:47:06 +02:00
alaviss
7beed44fc9 asyncdispatch: export Callback (#14042) [backport]
This let us see the definition of `Callback` in docs, which is required
to even make use of asyncdispatch.

Ref #13539.
2020-04-21 11:21:36 +02:00
hlaaftana
3fe3db3c0d clarify tuples and objects in manual, fixes #12486 (#14044) 2020-04-21 11:21:12 +02:00
Tristram Oaten
42a64245f8 Fix broken async httpclient example
As the async httpclient is almost certainly the first async example beginners will want to try, we OWE it to them to give them a real example.

Example repeated here for clarity:

```nim
import asyncdispatch, httpclient

proc asyncProc(): Future[string] {.async.} =
  var client = newAsyncHttpClient()
  return await client.getContent("http://example.com")

echo waitFor asyncProc()
```

This is my first Nim contribution, please let me know if the code is right. (it runs on my machine, but may not be the best example)
2020-04-21 00:00:30 +01:00
Andreas Rumpf
67d71bb76d fixes #14038 2020-04-20 23:44:29 +02:00
alaviss
1bdc30bdb1 Make file descriptors from stdlib non-inheritable by default (#13201)
* io: make file descriptors non-inheritable by default

This prevents file descriptors/handles leakage to child processes
that might cause issues like running out of file descriptors, or potential
security issues like leaking a file descriptor to a restricted file.

While this breaks backward compatibility, I'm rather certain that not
many programs (if any) actually make use of this implementation detail.
A new API `setInheritable` is provided for the few that actually want to
use this functionality.

* io: disable inheritance at file creation time for supported platforms

Some platforms provide extension to fopen-family of functions to allow
for disabling descriptor inheritance atomically during File creation.
This guards against possible leaks when a child process is spawned
before we managed to disable the file descriptor inheritance
(ie. in a multi-threaded program).

* net, nativesockets: make sockets non inheritable by default

With this commit, sockets will no longer leak to child processes when
you don't want it to. Should solves a lot of "address in use" that might
occur when your server has just restarted.

All APIs that create sockets in these modules now expose a `inheritable`
flag that allow users to toggle inheritance for the resulting sockets.
An implementation of `setInheritance()` is also provided for SocketHandle.

While atomically disabling inheritance at creation time is supported on
Windows, it's only implemented by native winsock2, which is too much for
now. This support can be implemented in a future patch.

* posix: add F_DUPFD_CLOEXEC

This command duplicates file descriptor with close-on-exec flag set.

Defined in POSIX.1-2008.

* ioselectors_kqueue: don't leak file descriptors

File descriptors internally used by ioselectors on BSD/OSX are now
shielded from leakage.

* posix: add O_CLOEXEC

This flag allows file descriptors to be open() with close-on-exec flag
set atomically.

This flag is specified in POSIX.1-2008

* tfdleak: test for selectors leakage

Also simplified the test by using handle-type agnostic APIs to test for
validity.

* ioselectors_epoll: mark all fd created close-on-exec

File descriptors from ioselectors should no longer leaks on Linux.

* tfdleak: don't check for selector leakage on Windows

The getFd proc for ioselectors_select returns a hardcoded -1

* io: add NoInheritFlag at compile time

* io: add support for ioctl-based close-on-exec

This allows for the flag to be set/unset in one syscall. While the
performance gains might be negliable, we have one less failure point
to deal with.

* tfdleak: add a test for setInheritable

* stdlib: add nimInheritHandles to restore old behaviors

* memfiles: make file handle not inheritable by default for posix

* io: setInheritable now operates on OS file handle

On Windows, the native handle is the only thing that's inheritable, thus
we can assume that users of this function will already have the handle
available to them. This also allows users to pass down file descriptors
from memfiles on Windows with ease, should that be desired.

With this, nativesockets.setInheritable can be made much simpler.

* changelog: clarify

* nativesockets: document setInheritable return value

* posix_utils: atomically disable fd inheritance for mkstemp
2020-04-20 17:09:59 +02:00
Clyybber
6bd279c978 Fix #13972 (#14034) 2020-04-20 17:06:44 +02:00
cooldome
65c5367dc1 Fixes #14014 (#14029)
* add test

* improve test

* progress

* fix #14014

* fix bug

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-20 15:57:36 +02:00
Jasper Jenkins
ba0af0f827 allow generic typedesc field access (#12220)
Co-authored-by: Clyybber <darkmine956@gmail.com>
2020-04-20 15:36:57 +02:00
Lưu Danh, Hiếu
4476d8a2e0 Update code example to match new sdl2.nim syntax (#13924)
* Update code example to match new sdl2.nim syntax

Signed-off-by: Hieu Luu Danh <hieu@vivu.asia>

* Modify on recommendation of @alaviss

- Removed trailing whitespaces
- Detailed how to compile libnimhcr and libnimrtl
- Fixed some logic in example code

* Modify following recommendations of @alaviss

- Rewording so that it conforms to Windows/Linux/MacOS

Signed-off-by: Hieu Luu Danh <hieu@vivu.asia>
2020-04-20 14:49:05 +02:00
awr1
59aeaa1c98 Make bitand, bitor, bitxor varargs-friendly (#13985)
* made bitand, bitor, bitxor varargs friendly
* changed new bitops to macros
* changed macro signature for consistency (this technically doesn't matter)
* added tests
* removed redundant assert
* fix literal
2020-04-20 14:48:37 +02:00
Araq
59f1462b95 remove the nilChecks switch; refs #11570 2020-04-20 14:44:54 +02:00
Araq
4d1149cffd fix for asm statement; refs #12650 2020-04-20 14:44:54 +02:00
Araq
17f222613a refactor system.$ for objects a little; refs #13398 2020-04-20 14:44:54 +02:00
Timothee Cour
b2720317fa add --experimental:vmopsDanger; add generic conversion for vmops (#13813)
* add --experimental:vmopsDanger; vmops cleanups
2020-04-20 12:00:00 +02:00
alaviss
77834f0fda compiler/suggest: highlight squashed operators (#11796)
The operator fetching proc is greedy, so operators such as `%*` in
expression `%*{}` can't be highlighted.

This commit fixes that.
2020-04-20 11:54:53 +02:00
Araq
e6cf11351d unicode: minor documention improvement 2020-04-20 08:42:08 +02:00
Andreas Rumpf
242d39d27f fixes #12834 (#14017) 2020-04-19 14:42:45 +02:00
Andreas Rumpf
73eff1f457 fixes #12741 (#14005)
* fixes #12741
* updated tests
2020-04-19 11:59:01 +02:00
Andreas Rumpf
9874981e75 fixes #14001 (#14004) 2020-04-19 10:01:04 +02:00
Arne Döring
4005f0d0e4 forward type alignment information to seqs (#12430) 2020-04-19 07:52:01 +02:00
Andreas Rumpf
a8f030fea2 drnim: phi nodes for 'if' statements (#13990) 2020-04-19 02:41:16 +02:00
jiro
f1ee817627 Add runnableExamples to critbits module (#13994)
* doc: critbit: add runnableExamples

* doc: critbit: change to upper
2020-04-18 20:06:20 +02:00
hlaaftana
f46803b225 Fix unused warning for $ for empty tuple/objects (#13991) 2020-04-18 17:41:03 +02:00
Timothee Cour
e3919b658f fix https://github.com/nim-lang/RFCs/issues/211: var a: DateTime compiles and is usable (#14002) [backport:1.2]
* fix https://github.com/nim-lang/RFCs/issues/211: `var a: DateTime` works
* assertValidDate checks for sentinel month
2020-04-18 16:22:03 +02:00
cooldome
d839eb9352 fix #14007 (#14012) [backport]
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-18 16:15:17 +02:00
cooldome
f10689d3d4 fixes #14003 (#14006) [backport:1.2]
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-17 13:23:04 +02:00
cooldome
d3b0132061 Step2: fixes #13781, fixes #13805 (#13897)
* Fix sym owner in wrapper proc
* threadpool changes
* revert lowerings
* add newFastMoveStmt
* try fixing test by switching to cpp

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-16 23:27:08 +02:00
cooldome
9295251e68 Implements RFCs #209 (#13995)
* add test
* add changelod entry
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-16 21:04:05 +02:00
awr1
b6f99409a9 added extended msg for failed library loads w/ incorrect DLL formats (#13950)
* added extended msg for failed library loads w/ incorrect DLL formats

* missing colon

* fix GetLastError()

* make GetLastError() available for windows console apps

* remove premature nullchar if outputting extra message

* if-protect nullchar detection

* better fix for message box code
2020-04-16 20:23:54 +02:00
Miran
06e0c75ba9 make fuzzy search a bit less fuzzy (#13996) [backport:1.2] 2020-04-16 20:22:32 +02:00
Timothee Cour
6914de0d8d fix newDomParser (#13981) 2020-04-16 08:59:54 +02:00
Adam Weber
d72808520b Grammar correction in backends.rst (#13989)
I hate to be the guy that submits a couple grammatical/spelling corrections.
2020-04-16 00:39:44 -04:00
Andreas Rumpf
60ec5c89c5 added a .since annotation to hashIdentity 2020-04-15 23:35:10 +02:00
c-blake
a0b33f9408 Add hashWangYi1 (#13823)
* Unwind just the "pseudorandom probing" (whole hash-code-keyed variable
stride double hashing) part of recent sets & tables changes (which has
still been causing bugs over a month later (e.g., two days ago
https://github.com/nim-lang/Nim/issues/13794) as well as still having
several "figure this out" implementation question comments in them (see
just diffs of this PR).

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

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

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

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

* Fix `data.len` -> `dataLen` problem.

* This is an alternate resolution to https://github.com/nim-lang/Nim/issues/13393
(which arguably could be resolved outside the stdlib).

Add version1 of Wang Yi's hash specialized to 8 byte integers.  This gives
simple help to users having trouble with overly colliding hash(key)s.  I.e.,
  A) `import hashes; proc hash(x: myInt): Hash = hashWangYi1(int(x))`
      in the instantiation context of a `HashSet` or `Table`
or
  B) more globally, compile with `nim c -d:hashWangYi1`.

No hash can be all things to all use cases, but this one is A) vetted to
scramble well by the SMHasher test suite (a necessarily limited but far
more thorough test than prior proposals here), B) only a few ALU ops on
many common CPUs, and C) possesses an easy via "grade school multi-digit
multiplication" fall back for weaker deployment contexts.

Some people might want to stampede ahead unbridled, but my view is that a
good plan is to
  A) include this in the stdlib for a release or three to let people try it
     on various key sets nim-core could realistically never access/test
     (maybe mentioning it in the changelog so people actually try it out),
  B) have them report problems (if any),
  C) if all seems good, make the stdlib more novice friendly by adding
     `hashIdentity(x)=x` and changing the default `hash() = hashWangYi1`
     with some `when defined` rearranging so users can `-d:hashIdentity`
     if they want the old behavior back.
This plan is compatible with any number of competing integer hashes if
people want to add them.  I would strongly recommend they all *at least*
pass the SMHasher suite since the idea here is to become more friendly to
novices who do not generally understand hashing failure modes.

* Re-organize to work around `when nimvm` limitations; Add some tests; Add
a changelog.md entry.

* Add less than 64-bit CPU when fork.

* Fix decl instead of call typo.

* First attempt at fixing range error on 32-bit platforms; Still do the
arithmetic in doubled up 64-bit, but truncate the hash to the lower
32-bits, but then still return `uint64` to be the same.  So, type
correct but truncated hash value.  Update `thashes.nim` as well.

* A second try at making 32-bit mode CI work.

* Use a more systematic identifier convention than Wang Yi's code.

* Fix test that was wrong for as long as `toHashSet` used `rightSize` (a
very long time, I think).  `$a`/`$b` depend on iteration order which
varies with table range reduced hash order which varies with range for
some `hash()`.  With 3 elements, 3!=6 is small and we've just gotten
lucky with past experimental `hash()` changes.  An alternate fix here
would be to not stringify but use the HashSet operators, but it is not
clear that doesn't alter the "spirit" of the test.

* Fix another stringified test depending upon hash order.

* Oops - revert the string-keyed test.

* Fix another stringify test depending on hash order.

* Add a better than always zero `defined(js)` branch.

* It turns out to be easy to just work all in `BigInt` inside JS and thus
guarantee the same low order bits of output hashes (for `isSafeInteger`
input numbers).  Since `hashWangYi1` output bits are equally random in
all their bits, this means that tables will be safely scrambled for table
sizes up to 2**32 or 4 gigaentries which is probably fine, as long as the
integer keys are all < 2**53 (also likely fine).  (I'm unsure why the
infidelity with C/C++ back ends cut off is 32, not 53 bits.)

Since HashSet & Table only use the low order bits, a quick corollary of
this is that `$` on most int-keyed sets/tables will be the same in all
the various back ends which seems a nice-to-have trait.

* These string hash tests fail for me locally.  Maybe this is what causes
the CI hang for testament pcat collections?

* Oops. That failure was from me manually patching string hash in hashes.  Revert.

* Import more test improvements from https://github.com/nim-lang/Nim/pull/13410

* Fix bug where I swapped order when reverting the test.  Ack.

* Oh, just accept either order like more and more hash tests.

* Iterate in the same order.

* `return` inside `emit` made us skip `popFrame` causing weird troubles.

* Oops - do Windows branch also.

* `nimV1hash` -> multiply-mnemonic, type-scoped `nimIntHash1` (mnemonic
resolutions are "1 == identity", 1 for Nim Version 1, 1 for
first/simplest/fastest in a series of possibilities.  Should be very
easy to remember.)

* Re-organize `when nimvm` logic to be a strict `when`-`else`.

* Merge other changes.

* Lift constants to a common area.

* Fall back to identity hash when `BigInt` is unavailable.

* Increase timeout slightly (probably just real-time perturbation of CI
system performance).
2020-04-15 20:11:18 +02:00
Andreas Rumpf
3a2697dd73 drnim: tiny progress (#13882)
* drnim: tiny progress
* refactoring complete
* drnim: prove .ensures annotations
* Moved code around to avoid code duplication
* drnim: first implementation of the 'old' property
* drnim: be precise about the assignment statement
* first implementation of --assumeUnique
* progress on forall/exists handling
2020-04-15 20:03:25 +02:00
Miran
04b6e9cf3e add timezones package to important_packages (#13987) 2020-04-15 17:33:16 +02:00
Timothee Cour
4764220cfb Fix https://github.com/inim-repl/INim/issues/66 (#13984) 2020-04-15 13:07:18 +02:00
Timothee Cour
2c93d1684e enable important_pkg on OSX (#13954)
* enable important_pkg on OSX

* disable some important_packages on OSX

* fixup

* enable nigui by installing dependency
2020-04-14 15:00:35 +02:00
Timothee Cour
10eabec6d4 fix #12864 static params were mutating arg types during sigmatch; fix #12713 ; refs #13529 (#13976)
* fix #12864 static params were mutating arg types during sigmatch

* fix test

* fix StaticParam

* also fixes #12713; added test case
2020-04-14 15:00:02 +02:00
Juan Carlos
c269964860 Add Data URI Base64, implements RFC-2397 (#13759)
* Add Data URI Base64, implements RFC-2397

* Add Data URI Base64, implements RFC-2397

* Add Data URI Base64, implements RFC-2397

* https://github.com/nim-lang/Nim/pull/13759#issuecomment-611498420

* https://github.com/nim-lang/Nim/pull/13759#issuecomment-611498420

* ReSync changelog

* https://github.com/nim-lang/Nim/pull/13759#issuecomment-611498420

Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>
2020-04-13 14:15:45 +01:00
Juan Carlos
0a84219b3e Add jsdomparser (#13920)
* Add jsdomparser

* Add jsdomparser

* Add jsdomparser

* https://github.com/nim-lang/Nim/pull/13920#issuecomment-610727142

* https://github.com/nim-lang/Nim/pull/13920#issuecomment-610727142

* https://github.com/nim-lang/Nim/pull/13920#issuecomment-610727142

* https://github.com/nim-lang/Nim/pull/13920#discussion_r405932909

* https://github.com/nim-lang/Nim/pull/13920#discussion_r406502592
2020-04-13 14:07:52 +01:00
Oscar Nihlgård
255698deee Fix semfold handling of {.str/int/bool-define.} (#13964) 2020-04-13 14:22:33 +02:00
jiro
40b64ccd7b Add runnableExamples to bitops module (#13951)
* doc: bitops: add runnableExamples

* doc: bitops: add notes to documentation comments of macros

* doc: bitops: add periods to documentation comments

* doc: bitops: add static

* Revert "doc: bitops: add static"

This reverts commit 595ee134ab.

* doc: bitops: add `var` to arguments of macros

* doc: bitops: remove examples of testBit
2020-04-13 14:21:45 +02:00
cooldome
8ba915e449 error msg for #13864 (#13962)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-13 14:17:22 +02:00
Timothee Cour
814f150184 fix #13848: make var result work with nim cpp (#13959)
* fix #13848

* add exhaustive tests for var result
2020-04-13 14:16:06 +02:00
narimiran
2ef39081e1 minor fixes in 1.2 changelog [ci skip] 2020-04-13 08:12:27 +02:00
genotrance
35b046373a Improve #12920 fix (#13958) 2020-04-12 21:08:16 +02:00
Juan Carlos
7238b968f3 Make unused code into actual test, replace echo with doassert (#13952) 2020-04-11 22:16:26 +02:00
alaviss
5f6962337d osproc: added a better version of waitForExit for Haiku (#13938)
Also modified tosprocterminate to verify waitForExit implementations.
2020-04-10 09:34:52 +02:00
alaviss
cc3f5d21b2 posix: add full Haiku support (#13931)
* posix: add full Haiku support

This commit provides a posix_haiku derived from posix_other, with types
following Haiku's definition. This fixes cases where the compiler
generates type check for the wrong types (ie. checks where generated for
an int-derived type but it's actually implemented as an uint instead).

* tools/kochdocs: welcome posix_haiku to the blacklist
2020-04-09 15:56:08 +02:00
cooldome
7b582fd6a6 fixes #13863 (#13929)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-08 19:51:23 +02:00
Hessam Mehr
bff742cd8b Add support for zig cc as C compiler. (#13757) 2020-04-08 15:24:14 +02:00
Dominik Picheta
350ee0308a Fixes issues with dynamic loading OpenSSL. Fixes #13903. (#13919) [backport]
This fixes at least a couple of issues:

* Procs loaded from the DLL being used even when the pointer is nil.
* The actual issue (#13903) which appeared to cause stack corruption on
  Android 7.1.1 with OpenSSL 1.1.1f. The change that fixed this was the
  move to loading the procs in `sslSym`.
2020-04-08 14:37:00 +02:00
Miran
3dc8068075 Test packages on Linux (#13921)
* test important packages on Linux

* enable chronos
2020-04-08 14:34:08 +02:00
cooldome
b4e9f8e814 fix ICE in isUnresolvedSym (#13925)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-08 13:16:25 +01:00
cooldome
f86fc5316a fix #13909 (#13914) [backport:1.2]
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-08 11:28:09 +02:00
Timothee Cour
95fd8ae93c fix #13902 distinct uint64 type corruption on 32-bit with borrow (#13907) [backport:1.2]
* fix #13902 distinct uint64 type corruption on 32-bit with borrow

Co-authored-by: Timothee Cour <timothee.cour2+lightsail@gmail.com>
2020-04-08 09:56:16 +02:00
narimiran
3036ec9c44 fix #13894, httpclient hang on Http204 2020-04-07 22:21:39 +01:00
cooldome
c835c8c4e7 fix #13910 (#13917)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-07 19:40:14 +02:00
Timothee Cour
ab5e26c53c fix some codegen bugs: NIM_BOOL, NIM_STATIC_ASSERT, --passc:-std=... (etc) (#13798)
* fix cgen bool D20200328T203812
* --passc:std=c++17 (etc) now works instead of silently ignored
* document caveats for NIM_NIL
2020-04-07 15:17:30 +02:00
Nicolai Søborg
b41931bf67 json doc: Note about Option and reserved keywords (#13895) 2020-04-07 15:14:25 +02:00
Arne Döring
37692baf49 fix #13739 (#13742) 2020-04-07 14:42:59 +02:00
Clyybber
92c4aad205 Fix #13889 with testcase (#13896) [backport]
* Fix https://github.com/nim-lang/Nim/issues/13889

* Add testcase

* Reduce test time

Co-authored-by: Elie Zedeck RANDRIAMIANDRIRAY <elie.zedeck@gmail.com>
2020-04-06 16:25:24 +02:00
Clyybber
1e25e16c88 Fix #13872 (#13898) 2020-04-06 14:35:27 +01:00
Timothee Cour
e6d870896b openDefaultBrowser now works on OSX (#13892) [backport] 2020-04-06 08:26:12 +02:00
Timothee Cour
f1fd3ef7f4 fix https://github.com/timotheecour/Nim/issues/88 (#13865) [backport:1.2] 2020-04-06 00:24:35 +02:00
supakeen
87847150bf Add barebones asynchttpserver tests (#13883)
* Add isNil check to custom Content-Length.

Related to #13866.

* Setup barebones asynchttpserver tests.
2020-04-05 21:16:13 +02:00
Hiroki Noda
b6814be653 doc: fix comment for repr*(x: char): string (#13873)
replace `$` with `repr`.
2020-04-05 16:44:55 +02:00
Timothee Cour
29734b73ff add nimPath to nim dump (#13876)
* add nimPath to nim dump

* rename
2020-04-05 16:44:34 +02:00
cooldome
6d4f07f2ea Fix sym owner in wrapper proc (#13878)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-04-05 16:44:15 +02:00
supakeen
09ca19208f Add isNil check to custom Content-Length. (#13867) [backport:1.2]
Related to #13866.
2020-04-05 09:02:30 +02:00
alaviss
813ed358bf asyncdispatch: get rid of erroneous set constructions (#13877)
Ref #13764
2020-04-05 08:39:43 +02:00
Andreas Rumpf
a890aa75aa finally de-deprecate the .define and .undef pragmas 2020-04-04 23:12:24 +02:00
Andreas Rumpf
9c46927fad new feature: ability to turn specific warnings to errors 2020-04-04 22:56:03 +02:00
narimiran
ed44e524b0 bump devel version to 1.3.1 2020-04-03 21:28:11 +02:00
Alexander Ivanov
cec320b569 Remove my wrongly written mangled-related code, not needed anymore (#13858) 2020-04-03 20:22:03 +02:00
967 changed files with 43944 additions and 17720 deletions

34
.builds/openbsd_0.yml Normal file
View File

@@ -0,0 +1,34 @@
## do not edit directly; auto-generated by `nim r tools/ci_generate.nim`
image: openbsd/latest
packages:
- gmake
- sqlite3
- node
- boehm-gc
- pcre
- sfml
- sdl2
- libffi
sources:
- https://github.com/nim-lang/Nim
environment:
NIM_TESTAMENT_BATCH: "0_3"
CC: /usr/bin/clang
tasks:
- setup: |
cd Nim
git clone --depth 1 -q https://github.com/nim-lang/csources_v1.git csources
gmake -C csources -j $(sysctl -n hw.ncpuonline)
bin/nim c koch
echo 'export PATH=$HOME/Nim/bin:$PATH' >> $HOME/.buildenv
- test: |
cd Nim
if ! ./koch runCI; then
nim c -r tools/ci_testresults.nim
exit 1
fi
triggers:
- action: email
condition: failure
to: Andreas Rumpf <rumpf_a@web.de>

34
.builds/openbsd_1.yml Normal file
View File

@@ -0,0 +1,34 @@
## do not edit directly; auto-generated by `nim r tools/ci_generate.nim`
image: openbsd/latest
packages:
- gmake
- sqlite3
- node
- boehm-gc
- pcre
- sfml
- sdl2
- libffi
sources:
- https://github.com/nim-lang/Nim
environment:
NIM_TESTAMENT_BATCH: "1_3"
CC: /usr/bin/clang
tasks:
- setup: |
cd Nim
git clone --depth 1 -q https://github.com/nim-lang/csources_v1.git csources
gmake -C csources -j $(sysctl -n hw.ncpuonline)
bin/nim c koch
echo 'export PATH=$HOME/Nim/bin:$PATH' >> $HOME/.buildenv
- test: |
cd Nim
if ! ./koch runCI; then
nim c -r tools/ci_testresults.nim
exit 1
fi
triggers:
- action: email
condition: failure
to: Andreas Rumpf <rumpf_a@web.de>

34
.builds/openbsd_2.yml Normal file
View File

@@ -0,0 +1,34 @@
## do not edit directly; auto-generated by `nim r tools/ci_generate.nim`
image: openbsd/latest
packages:
- gmake
- sqlite3
- node
- boehm-gc
- pcre
- sfml
- sdl2
- libffi
sources:
- https://github.com/nim-lang/Nim
environment:
NIM_TESTAMENT_BATCH: "2_3"
CC: /usr/bin/clang
tasks:
- setup: |
cd Nim
git clone --depth 1 -q https://github.com/nim-lang/csources_v1.git csources
gmake -C csources -j $(sysctl -n hw.ncpuonline)
bin/nim c koch
echo 'export PATH=$HOME/Nim/bin:$PATH' >> $HOME/.buildenv
- test: |
cd Nim
if ! ./koch runCI; then
nim c -r tools/ci_testresults.nim
exit 1
fi
triggers:
- action: email
condition: failure
to: Andreas Rumpf <rumpf_a@web.de>

View File

@@ -12,9 +12,14 @@ Function `echo` outputs the wrong string.
### Example
```nim
echo "Hello World!"
# This code should be a minimum reproducible example:
# try to simplify and minimize as much as possible. If it's a compiler
# issue, try to minimize further by removing any imports if possible.
```
### Current Output
please check whether the problem still exists in git head before posting,
see [rebuilding the compiler](https://nim-lang.github.io/Nim/intern.html#rebuilding-the-compiler).
```
Hola mundo!
```
@@ -29,12 +34,18 @@ Hello World!
* In file xyz there is a call that might be the cause of it.
### Additional Information
If it's a regression, you can help us by identifying which version introduced
the bug, see [Bisecting for regressions](https://nim-lang.github.io/Nim/intern.html#bisecting-for-regressions),
or at least try known past releases (eg `choosenim 1.2.0`).
If it's a pre-existing compiler bug, see [Debugging the compiler](https://nim-lang.github.io/Nim/intern.html#debugging-the-compiler)
which should give more context on a compiler crash.
* It was working in version a.b.c
* Issue #abc is related, but different because of ...
* This issue is blocking my project xyz
```
$ nim -v
Nim Compiler Version 0.1.2
# make sure to include the git hash if not using a tagged release
```

69
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,69 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 365
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 30
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- ARC
- bounty
- Codegen
- Crash
- Generics
- High Priority
- Macros
- Next release
- Showstopper
- Static[T]
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: false
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This pull request has been automatically marked as stale because it has not had
recent activity.
If you think it is still a valid PR, please rebase it on the latest devel;
otherwise it will be closed. Thank you for your contributions.
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Comment to post when closing a stale Issue or Pull Request.
# closeComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 20
# Limit to only `issues` or `pulls`
only: pulls
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed

View File

@@ -1,22 +1,37 @@
name: Nim Docs CI
on:
push:
# Run only on changes on these files
paths:
- 'lib/**.nim'
- 'compiler/docgen.nim'
- 'compiler/renderverbatim.nim'
- 'config/nimdoc.cfg'
- 'doc/**.rst'
- 'doc/nimdoc.css'
- 'lib/**.nim'
- 'nimdoc/testproject/expected/testproject.html'
- 'tools/dochack/dochack.nim'
- 'tools/kochdocs.nim'
- '.github/workflows/ci_docs.yml'
- 'koch.nim'
pull_request:
# Run only on changes on these files.
paths:
- 'compiler/docgen.nim'
- 'compiler/renderverbatim.nim'
- 'config/nimdoc.cfg'
- 'doc/**.rst'
- 'doc/nimdoc.css'
- 'lib/**.nim'
- 'nimdoc/testproject/expected/testproject.html'
- 'tools/dochack/dochack.nim'
- 'tools/kochdocs.nim'
- '.github/workflows/ci_docs.yml'
pull_request:
# Run only on changes on these files
paths:
- 'lib/**.nim'
- 'doc/**.rst'
- '.github/workflows/ci_docs.yml'
jobs:
build:
if: |
!contains(format('{0} {1}', github.event.head_commit.message, github.event.pull_request.title), '[skip ci]')
strategy:
fail-fast: false
matrix:
@@ -111,17 +126,14 @@ jobs:
shell: bash
run: ./koch boot -d:release
- name: 'Clone fusion'
shell: bash
run: ./koch fusion
- name: 'Build documentation'
shell: bash
run: ./koch doc --git.commit:devel
- name: 'Prepare documentation for deployment'
if: |
github.event_name == 'push' && github.ref == 'refs/heads/devel' &&
matrix.target == 'linux'
shell: bash
run: cp -f doc/html/{overview,index}.html
- name: 'Publish documentation to Github Pages'
if: |
github.event_name == 'push' && github.ref == 'refs/heads/devel' &&

85
.github/workflows/ci_packages.yml vendored Normal file
View File

@@ -0,0 +1,85 @@
name: Packages CI
on: [push, pull_request]
jobs:
build:
if: |
!contains(format('{0} {1}', github.event.head_commit.message, github.event.pull_request.title), '[skip ci]')
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, macos-11]
cpu: [amd64]
pkg: [1, 2]
name: '${{ matrix.os }} (pkg: ${{ matrix.pkg }})'
runs-on: ${{ matrix.os }}
env:
NIM_TEST_PACKAGES: ${{ matrix.pkg }}
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: 'Checkout csources'
uses: actions/checkout@v2
with:
repository: nim-lang/csources
path: csources
- name: 'Install node.js 12.x'
uses: actions/setup-node@v1
with:
node-version: '12.x'
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
run: |
sudo apt-fast update -qq
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends -yq \
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev \
valgrind libc6-dbg libblas-dev xorg-dev
- name: 'Install dependencies (macOS)'
if: runner.os == 'macOS'
run: brew install boehmgc make sfml gtk+3
- name: 'Install dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash
run: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64.7z -o dist/mingw64.7z
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
7z x dist/mingw64.7z -odist
7z x dist/dlls.zip -obin
echo "${{ github.workspace }}/dist/mingw64/bin" >> "${GITHUB_PATH}"
- name: 'Add build binaries to PATH'
shell: bash
run: echo "${{ github.workspace }}/bin" >> "${GITHUB_PATH}"
- name: 'Build csources'
shell: bash
run: |
ncpu=
case '${{ runner.os }}' in
'Linux')
ncpu=$(nproc)
;;
'macOS')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu='${{ matrix.cpu }}'
- name: 'Build koch'
shell: bash
run: nim c koch
- name: 'Run CI'
shell: bash
run: ./koch runCI
- name: 'Show failed tests'
if: failure()
shell: bash
run: nim c -r tools/ci_testresults.nim

View File

@@ -12,6 +12,8 @@ on:
jobs:
build:
if: |
!contains(format('{0} {1}', github.event.head_commit.message, github.event.pull_request.title), '[skip ci]')
strategy:
fail-fast: false
matrix:

8
.gitignore vendored
View File

@@ -66,6 +66,7 @@ testament.db
/tests/**/*.js
/csources
/dist/
/lib/fusion
# Private directories and files (IDEs)
.*/
@@ -82,6 +83,8 @@ megatest.nim
/outputExpected.txt
/outputGotten.txt
/t15148.txt
/tests/vm/tfile_rw.txt
/lib/pure/*.js
@@ -92,7 +95,8 @@ megatest.nim
# ignore debug dirs generated by dsymutil on OSX
*.dSYM
nimdoc.out.css
# for `nim c -r nimdoc/tester` etc; this can be in multiple places
htmldocs
## these are not needed anymore unless checkout old older versions
nimdoc.out.css

View File

@@ -22,7 +22,7 @@ addons:
- valgrind
before_script:
- git clone --depth 1 https://github.com/nim-lang/csources.git
- git clone --depth 1 https://github.com/nim-lang/csources_v1.git csources
- export PATH="$PWD/bin${PATH:+:$PATH}"
- make -C csources -j 2 LD=$CC ucpu=$CPU

View File

@@ -27,17 +27,19 @@ jobs:
vmImage: 'macOS-11'
CPU: amd64
NIM_COMPILE_TO_CPP: true
Windows_amd64:
Windows_amd64_batch0_3:
vmImage: 'windows-2019'
CPU: amd64
Linux_amd64_pkg:
vmImage: 'ubuntu-18.04'
# see also: `NIM_TEST_PACKAGES`
NIM_TESTAMENT_BATCH: "0_3"
Windows_amd64_batch1_3:
vmImage: 'windows-2019'
CPU: amd64
NIM_TEST_PACKAGES: true
OSX_amd64_pkg:
vmImage: 'macOS-10.15'
NIM_TESTAMENT_BATCH: "1_3"
Windows_amd64_batch2_3:
vmImage: 'windows-2019'
CPU: amd64
NIM_TEST_PACKAGES: true
NIM_TESTAMENT_BATCH: "2_3"
pool:
vmImage: $(vmImage)
@@ -105,7 +107,7 @@ jobs:
displayName: 'Install dependencies (i386 Linux)'
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'i386'))
- bash: brew install boehmgc make sfml gtk+3
- bash: brew install boehmgc make sfml
displayName: 'Install dependencies (OSX)'
condition: eq(variables['Agent.OS'], 'Darwin')

View File

@@ -5,17 +5,15 @@ set -e
which nim > /dev/null || (echo "nim not in PATH"; exit 1)
which gdb > /dev/null || (echo "gdb not in PATH"; exit 1)
which readlink > /dev/null || (echo "readlink not in PATH."; exit 1)
if [[ "$(uname -s)" == "Darwin" ]]; then
which greadlink > /dev/null || (echo "readlink not in PATH. Please install coreutils from homebrew."; exit 1)
READLINK=greadlink
if [[ "$(uname -s)" == "Darwin" || "(uname -s)" == *"BSD" ]]; then
NIM_SYSROOT=$(dirname $(dirname $(readlink -f $(which nim))))
else
which readlink > /dev/null || (echo "readlink not in PATH."; exit 1)
READLINK=readlink
NIM_SYSROOT=$(dirname $(dirname $(readlink -e $(which nim))))
fi
# Find out where the pretty printer Python module is
NIM_SYSROOT=$(dirname $(dirname $($READLINK -e $(which nim))))
GDB_PYTHON_MODULE_PATH="$NIM_SYSROOT/tools/nim-gdb.py"
# Run GDB with the additional arguments that load the pretty printers

BIN
build.out

Binary file not shown.

4
build_all.sh Normal file → Executable file
View File

@@ -1,7 +1,7 @@
#! /bin/sh
# build development version of the compiler; can be rerun safely.
# arguments can be passed, eg `--os freebsd`
# arguments can be passed, e.g. `--os freebsd`
set -u # error on undefined variables
set -e # exit on first error
@@ -24,7 +24,7 @@ build_nim_csources(){
# avoid changing dir in case of failure
(
if [ $# -ne 0 ]; then
# some args were passed (eg: `--cpu i386`), need to call build.sh
# some args were passed (e.g.: `--cpu i386`), need to call build.sh
build_nim_csources_via_script "$@"
else
# no args, use multiple Make jobs (5X faster on 16 cores: 10s instead of 50s)

View File

@@ -1,7 +1,14 @@
# v1.4.0 - yyyy-mm-dd
# v1.6.x - yyyy-mm-dd
## Changes affecting backward compatibility
- The configuration subsystem now allows for `-d:release` and `-d:danger` to work as expected.
The downside is that these defines now have custom logic that doesn't apply for
other defines.
## Standard library additions and changes
- Added support for parenthesized expressions in `strformat`
@@ -11,127 +18,6 @@
- Make custom op in macros.quote work for all statements.
For `net` and `nativesockets`, an `inheritable` flag has been added to all
`proc`s that create sockets, allowing the user to control whether the
resulting socket is inheritable. This flag is provided to ease the writing of
multi-process servers, where sockets inheritance is desired.
For a transistion period, define `nimInheritHandles` to enable file handle
inheritance by default. This flag does **not** affect the `selectors` module
due to the differing semantics between operating systems.
`system.setInheritable` and `nativesockets.setInheritable` is also introduced
for setting file handle or socket inheritance. Not all platform have these
`proc`s defined.
- The file descriptors created for internal bookkeeping by `ioselector_kqueue`
and `ioselector_epoll` will no longer be leaked to child processes.
- `strutils.formatFloat` with `precision = 0` has been restored to the version
1 behaviour that produces a trailing dot, e.g. `formatFloat(3.14159, precision = 0)`
is now `3.`, not `3`.
- `critbits` adds `commonPrefixLen`.
- `relativePath(rel, abs)` and `relativePath(abs, rel)` used to silently give wrong results
(see #13222); instead they now use `getCurrentDir` to resolve those cases,
and this can now throw in edge cases where `getCurrentDir` throws.
`relativePath` also now works for js with `-d:nodejs`.
- JavaScript and NimScript standard library changes: `streams.StringStream` is
now supported in JavaScript, with the limitation that any buffer `pointer`s
used must be castable to `ptr string`, any incompatible pointer type will not
work. The `lexbase` and `streams` modules used to fail to compile on
NimScript due to a bug, but this has been fixed.
The following modules now compile on both JS and NimScript: `parsecsv`,
`parsecfg`, `parsesql`, `xmlparser`, `htmlparser` and `ropes`. Additionally
supported for JS is `cstrutils.startsWith` and `cstrutils.endsWith`, for
NimScript: `json`, `parsejson`, `strtabs` and `unidecode`.
- Added `streams.readStr` and `streams.peekStr` overloads to
accept an existing string to modify, which avoids memory
allocations, similar to `streams.readLine` (#13857).
- Added high-level `asyncnet.sendTo` and `asyncnet.recvFrom`. UDP functionality.
- `paramCount` & `paramStr` are now defined in os.nim instead of nimscript.nim for nimscript/nimble.
- `dollars.$` now works for unsigned ints with `nim js`
- Improvements to the `bitops` module, including bitslices, non-mutating versions
of the original masking functions, `mask`/`masked`, and varargs support for
`bitand`, `bitor`, and `bitxor`.
- `sugar.=>` and `sugar.->` changes: Previously `(x, y: int)` was transformed
into `(x: auto, y: int)`, it now becomes `(x: int, y: int)` in consistency
with regular proc definitions (although you cannot use semicolons).
Pragmas and using a name are now allowed on the lefthand side of `=>`. Here
is an aggregate example of these changes:
```nim
import sugar
foo(x, y: int) {.noSideEffect.} => x + y
# is transformed into
proc foo(x: int, y: int): auto {.noSideEffect.} = x + y
```
- The fields of `times.DateTime` are now private, and are accessed with getters and deprecated setters.
- The `times` module now handles the default value for `DateTime` more consistently. Most procs raise an assertion error when given
an uninitialized `DateTime`, the exceptions are `==` and `$` (which returns `"Uninitialized DateTime"`). The proc `times.isInitialized`
has been added which can be used to check if a `DateTime` has been initialized.
- Fix a bug where calling `close` on io streams in osproc.startProcess was a noop and led to
hangs if a process had both reads from stdin and writes (eg to stdout).
- The callback that is passed to `system.onThreadDestruction` must now be `.raises: []`.
- The callback that is assigned to `system.onUnhandledException` must now be `.gcsafe`.
- `osproc.execCmdEx` now takes an optional `input` for stdin, `workingDir` and `env`
parameters.
- Added a `ssl_config` module containing lists of secure ciphers as recommended by
[Mozilla OpSec](https://wiki.mozilla.org/Security/Server_Side_TLS)
- `net.newContext` now defaults to the list of ciphers targeting
["Intermediate compatibility"](https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29)
per Mozilla's recommendation instead of `ALL`. This change should protect
users from the use of weak and insecure ciphers while still provides
adequate compatibility with the majority of the Internet.
- A new module `std/jsonutils` with hookable `jsonTo,toJson,fromJson` operations for json
serialization/deserialization of custom types was added.
- A new proc `heapqueue.find[T](heap: HeapQueue[T], x: T): int` to get index of element ``x``
was added.
- Added `rstgen.rstToLatex` convenience proc for `renderRstToOut` and `initRstGenerator`
with `outLatex` output.
- Added `os.normalizeExe`, e.g.: `koch` => `./koch`.
- `macros.newLit` now preserves named vs unnamed tuples; use `-d:nimHasWorkaround14720`
to keep old behavior.
- Added `random.gauss`, that uses the ratio of uniforms method of sampling from a Gaussian distribution.
- Added `typetraits.elementType` to get element type of an iterable.
- `typetraits.$` changes: `$(int,)` is now `"(int,)"` instead of `"(int)"`;
`$tuple[]` is now `"tuple[]"` instead of `"tuple"`;
`$((int, float), int)` is now `"((int, float), int)"` instead of `"(tuple of (int, float), int)"`
- Added `macros.extractDocCommentsAndRunnables` helper
- `strformat.fmt` and `strformat.&` support `= specifier`. `fmt"{expr=}"` now
expands to `fmt"expr={expr}"`.
- deprecations: `os.existsDir` => `dirExists`, `os.existsFile` => `fileExists`
- Added `jsre` module, [Regular Expressions for the JavaScript target.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
- Made `maxLines` argument `Positive` in `logging.newRollingFileLogger`,
because negative values will result in a new file being created for each logged
line which doesn't make sense.
- Changed `log` in `logging` to use proper log level on JavaScript target,
e.g. `debug` uses `console.debug`, `info` uses `console.info`, `warn` uses `console.warn`, etc.
- Tables, HashSets, SharedTables and deques don't require anymore that the passed
initial size must be a power of two - this is done internally.
Proc `rightSize` for Tables and HashSets is deprecated, as it is not needed anymore.
`CountTable.inc` takes `val: int` again not `val: Positive`; I.e. it can "count down" again.
- Removed deprecated symbols from `macros` module, deprecated as far back as `0.15`.
- On Windows the SSL library now checks for valid certificates.
It uses the `cacert.pem` file for this purpose which was extracted
from `https://curl.se/ca/cacert.pem`. Besides
@@ -141,214 +27,53 @@
- Make `{.requiresInit.}` pragma to work for `distinct` types.
- Added a macros `enumLen` for returning the number of items in an enum to the
`typetraits.nim` module.
- `prelude` now works with the JavaScript target.
- Added `ioutils` module containing `duplicate` and `duplicateTo` to duplicate `FileHandle` using C function `dup` and `dup2`.
- The JSON module can now handle integer literals and floating point literals of arbitrary length and precision.
Numbers that do not fit the underlying `BiggestInt` or `BiggestFloat` fields are kept as string literals and
one can use external BigNum libraries to handle these. The `parseFloat` family of functions also has now optional
`rawIntegers` and `rawFloats` parameters that can be used to enforce that all integer or float literals remain
in the "raw" string form so that client code can easily treat small and large numbers uniformly.
- Added `randState` template that exposes the default random number generator. Useful for library authors.
- Added `asyncdispatch.activeDescriptors` that returns the number of currently
active async event handles/file descriptors
- Added `asyncdispatch.maxDescriptors` that returns the maximum number of
active async event handles/file descriptors.
- Added `getPort` to `asynchttpserver`.
- `--gc:orc` is now 10% faster than previously for common workloads. If
you have trouble with its changed behavior, compile with `-d:nimOldOrc`.
- `os.FileInfo` (returned by `getFileInfo`) now contains `blockSize`,
determining preferred I/O block size for this file object.
- Added a simpler to use `io.readChars` overload.
- Added `**` to jsffi.
- `writeStackTrace` is available in JS backend now.
- Added `decodeQuery` to `std/uri`.
- `strscans.scanf` now supports parsing single characters.
- `strscans.scanTuple` added which uses `strscans.scanf` internally,
returning a tuple which can be unpacked for easier usage of `scanf`.
- Added `setutils.toSet` that can take any iterable and convert it to a built-in `set`,
if the iterable yields a built-in settable type.
- Added `setutils.fullSet` which returns a full built-in `set` for a valid type.
- Added `setutils.complement` which returns the complement of a built-in `set`.
- Added `setutils.[]=`.
- Added `math.isNaN`.
- Added `jsbigints` module, arbitrary precision integers for JavaScript target.
- Added `math.copySign`.
- Added new operations for singly- and doubly linked lists: `lists.toSinglyLinkedList`
and `lists.toDoublyLinkedList` convert from `openArray`s; `lists.copy` implements
shallow copying; `lists.add` concatenates two lists - an O(1) variation that consumes
its argument, `addMoved`, is also supplied.
- Added `euclDiv` and `euclMod` to `math`.
- Added `httpcore.is1xx` and missing HTTP codes.
- Added `jsconsole.jsAssert` for JavaScript target.
- Added `posix_utils.osReleaseFile` to get system identification from `os-release` file on Linux and the BSDs.
https://www.freedesktop.org/software/systemd/man/os-release.html
- Added `socketstream` module that wraps sockets in the stream interface
- Added `sugar.dumpToString` which improves on `sugar.dump`.
- Added `math.signbit`.
- Removed the optional `longestMatch` parameter of the `critbits._WithPrefix` iterators (it never worked reliably)
- In `lists`: renamed `append` to `add` and retained `append` as an alias;
added `prepend` and `prependMoved` analogously to `add` and `addMoved`;
added `remove` for `SinglyLinkedList`s.
- Deprecated `any`. See https://github.com/nim-lang/RFCs/issues/281
- Added optional `options` argument to `copyFile`, `copyFileToDir`, and
`copyFileWithPermissions`. By default, on non-Windows OSes, symlinks are
followed (copy files symlinks point to); on Windows, `options` argument is
ignored and symlinks are skipped.
- On non-Windows OSes, `copyDir` and `copyDirWithPermissions` copy symlinks as
symlinks (instead of skipping them as it was before); on Windows symlinks are
skipped.
- On non-Windows OSes, `moveFile` and `moveDir` move symlinks as symlinks
(instead of skipping them sometimes as it was before).
- Added optional `followSymlinks` argument to `setFilePermissions`.
- Added `os.isAdmin` to tell whether the caller's process is a member of the
Administrators local group (on Windows) or a root (on POSIX).
- Added experimental `linenoise.readLineStatus` to get line and status (e.g. ctrl-D or ctrl-C).
- Added `compilesettings.SingleValueSetting.libPath`.
- `std/wrapnils` doesn't use `experimental:dotOperators` anymore, avoiding
issues like https://github.com/nim-lang/Nim/issues/13063 (which affected error messages)
for modules importing `std/wrapnils`.
Added `??.` macro which returns an `Option`.
- Added `math.frexp` overload procs. Deprecated `c_frexp`, use `frexp` instead.
- `parseopt.initOptParser` has been made available and `parseopt` has been
added back to `prelude` for all backends. Previously `initOptParser` was
unavailable if the `os` module did not have `paramCount` or `paramStr`,
but the use of these in `initOptParser` were conditionally to the runtime
arguments passed to it, so `initOptParser` has been changed to raise
`ValueError` when the real command line is not available. `parseopt` was
previously excluded from `prelude` for JS, as it could not be imported.
- Added `system.prepareStrMutation` for better support of low
level `moveMem`, `copyMem` operations for Orc's copy-on-write string
implementation.
- Added `std/strbasics` for high performance string operations.
Added `strip`, `setSlice`, `add(a: var string, b: openArray[char])`.
- Added to `wrapnils` an option-like API via `??.`, `isSome`, `get`.
- `std/options` changed `$some(3)` to `"some(3)"` instead of `"Some(3)"`
and `$none(int)` to `"none(int)"` instead of `"None[int]"`.
- Added `algorithm.merge`.
- Added `std/jsfetch` module [Fetch](https://developer.mozilla.org/docs/Web/API/Fetch_API) wrapper for JavaScript target.
- Added `std/jsheaders` module [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers) wrapper for JavaScript target.
- Added `std/jsformdata` module [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) wrapper for JavaScript target.
- `system.addEscapedChar` now renders `\r` as `\r` instead of `\c`, to be compatible
with most other languages.
- Removed support for named procs in `sugar.=>`.
- Added `jscore.debugger` to [call any available debugging functionality, such as breakpoints.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger).
- Added `std/channels`.
- Added `htmlgen.portal` for [making "SPA style" pages using HTML only](https://web.dev/hands-on-portals).
- Added `ZZZ` and `ZZZZ` patterns to `times.nim` `DateTime` parsing, to match time
zone offsets without colons, e.g. `UTC+7 -> +0700`.
- Added `jsconsole.dir`, `jsconsole.dirxml`, `jsconsole.timeStamp`.
- Added dollar `$` and `len` for `jsre.RegExp`.
- Added `std/tasks`.
- Added `hasDataBuffered` to `asyncnet`.
- Added `hasClosure` to `std/typetraits`.
- Added `std/tempfiles`.
- Added `genasts.genAst` that avoids the problems inherent with `quote do` and can
be used as a replacement.
- Added `copyWithin` [for `seq` and `array` for JavaScript targets](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin).
- Fixed premature garbage collection in asyncdispatch, when a stack trace override is in place.
## Language changes
- In newruntime it is now allowed to assign discriminator field without restrictions as long as case object doesn't have custom destructor. Discriminator value doesn't have to be a constant either. If you have custom destructor for case object and you do want to freely assign discriminator fields, it is recommended to refactor object into 2 objects like this:
- The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts
`wasMoved` calls where needed.
- The `=` hook is now called `=copy` for clarity. The old name `=` is still available so there
is no need to update your code. This change was backported to 1.2 too so you can use the
more readability `=copy` without loss of compatibility.
- `nimscript` now handles `except Exception as e`
- In the newruntime it is now allowed to assign to the discriminator field
without restrictions as long as case object doesn't have custom destructor.
The discriminator value doesn't have to be a constant either. If you have a
custom destructor for a case object and you do want to freely assign discriminator
fields, it is recommended to refactor object into 2 objects like this:
- The `cstring` doesn't support `[]=` operator in JS backend.
```nim
type
MyObj = object
case kind: bool
of true: y: ptr UncheckedArray[float]
of false: z: seq[int]
proc `=destroy`(x: MyObj) =
if x.kind and x.y != nil:
deallocShared(x.y)
x.y = nil
```
Refactor into:
```nim
type
MySubObj = object
val: ptr UncheckedArray[float]
MyObj = object
case kind: bool
of true: y: MySubObj
of false: z: seq[int]
proc `=destroy`(x: MySubObj) =
if x.val != nil:
deallocShared(x.val)
x.val = nil
```
## Compiler changes
- Added `unsafeIsolate` and `extract` to `std/isolation`.
- `--hint:CC` now goes to stderr (like all other hints) instead of stdout.
- json build instructions are now generated in `$nimcache/outFileBasename.json`
instead of `$nimcache/projectName.json`. This allows avoiding recompiling a given project
compiled with different options if the output file differs.
- `--usenimcache` (implied by `nim r main`) now generates an output file that includes a hash of
some of the compilation options, which allows caching generated binaries:
nim r main # recompiles
nim r -d:foo main # recompiles
nim r main # uses cached binary
nim r main arg1 arg2 # ditto (runtime arguments are irrelevant)
- The style checking of the compiler now supports a `--styleCheck:usages` switch. This switch
enforces that every symbol is written as it was declared, not enforcing
the official Nim style guide. To be enabled, this has to be combined either

View File

@@ -2,7 +2,6 @@
## Standard library additions and changes
- Added overloaded `strformat.fmt` macro that use specified characters as
delimiter instead of '{' and '}'.
- Added new procs in `tables.nim`: `OrderedTable.pop`, `CountTable.del`,
@@ -33,7 +32,7 @@
- Added `expectIdent` to the `macros` module.
- Added `os.isValidFilename` that returns `true` if `filename` argument is valid
for cross-platform use.
- Added `times.isLeapDay`
- Added `times.isLeapDay`.
- `base64` adds URL-Safe Base64, implements RFC-4648 Section-7.
- Added a new module, `std / compilesettings` for querying the compiler about
diverse configuration settings.
@@ -53,6 +52,8 @@
was designed for it. For example:
```nim
import std/with
type
Foo = object
col, pos: string
@@ -113,8 +114,6 @@ echo f
usage. The `$` operator can be used to obtain the string form of `HttpCode`
for comparison if desired.
- `std/oswalkdir` was buggy, it's now deprecated and reuses `std/os` procs.
- `net.newContext` now performs SSL Certificate checking on Linux and OSX.
Define `nimDisableCertificateValidation` to disable it globally.
- `os.walkDir` and `os.walkDirRec` now have new flag, `checkDir` (default: false).
If it is set to true, it will throw if input dir is invalid instead of a noop
(which is the default behaviour, as it was before this change),
@@ -128,8 +127,8 @@ echo f
of children nodes.
- `os.splitPath()` behavior synchronized with `os.splitFile()` to return "/"
as the dir component of `/root_sub_dir` instead of the empty string.
- The deprecated `lc` macro has been removed from `sugar`. It is now replaced with the
more powerful `collect` macro.
- The deprecated `lc` macro has been removed from `sugar`. It is now replaced
with the more powerful `collect` macro.
- `os.relativePath("foo", "foo")` is now `"."`, not `""`, as `""` means invalid
path and shouldn't be conflated with `"."`; use `-d:nimOldRelativePathBehavior`
to restore the old behavior.
@@ -138,25 +137,33 @@ echo f
Use `base64.encodeMime` instead.
### Breaking changes
- `net.newContext` now performs SSL Certificate checking on Linux and OSX.
Define `nimDisableCertificateValidation` to disable it globally.
## Language changes
- An `align` pragma can now be used for variables and object fields, similar
to the `alignas` declaration modifier in C/C++.
- `=sink` type bound operator is now optional. Compiler can now use combination
of `=destroy` and `copyMem` to move objects efficiently.
- The `=sink` type bound operator is now optional. The compiler can now use a
combination of `=destroy` and `copyMem` to move objects efficiently.
- Unsigned integer operators have been fixed to allow promotion of the first operand.
- Conversions to unsigned integers are unchecked at runtime, imitating earlier Nim
versions. The documentation was improved to acknowledge this special case.
See https://github.com/nim-lang/RFCs/issues/175 for more details.
- New syntax for lvalue references: `var b {.byaddr.} = expr` enabled by
- There is a new syntax for lvalue references: `var b {.byaddr.} = expr` enabled by
`import std/decls`.
- `var a {.foo.}: MyType = expr` now lowers to `foo(a, MyType, expr)` for
non-builtin pragmas, enabling things like lvalue references (see `decls.byaddr`).
## Compiler changes
- Generated JS code uses spaces, instead of mixed spaces and tabs.
- The generated JS code uses spaces, instead of mixing spaces and tabs.
- The Nim compiler now supports the ``--asm`` command option for easier
inspection of the produced assembler code.
- The Nim compiler now supports a new pragma called ``.localPassc`` to
@@ -192,10 +199,6 @@ echo f
with `-d:nimEmulateOverflowChecks`.
## Tool changes
- Nimpretty doesn't accept negative indentation argument anymore, because it was
breaking files.
## Bugfixes

View File

@@ -0,0 +1,874 @@
# v1.4.0 - 2020-10-16
## Standard library additions and changes
- Added some enhancements to `std/jsonutils` module.
* Added a possibility to deserialize JSON arrays directly to `HashSet` and
`OrderedSet` types and respectively to serialize those types to JSON arrays
via `jsonutils.fromJson` and `jsonutils.toJson` procedures.
* Added a possibility to deserialize JSON `null` objects to Nim option objects
and respectively to serialize Nim option object to JSON object if `isSome`
or to JSON null object if `isNone` via `jsonutils.fromJson` and
`jsonutils.toJson` procedures.
* Added a `Joptions` parameter to `jsonutils.fromJson` currently
containing two boolean options `allowExtraKeys` and `allowMissingKeys`.
- If `allowExtraKeys` is `true` Nim's object to which the JSON is parsed is
not required to have a field for every JSON key.
- If `allowMissingKeys` is `true` Nim's object to which JSON is parsed is
allowed to have fields without corresponding JSON keys.
- Added `bindParams`, `bindParam` to `db_sqlite` for binding parameters into a `SqlPrepared` statement.
- Added `tryInsert`,`insert` procs to `db_*` libs which accept primary key column name.
- Added `xmltree.newVerbatimText` support create `style`'s,`script`'s text.
- `uri` module now implements RFC-2397.
- Added [DOM Parser](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser)
to the `dom` module for the JavaScript target.
- The default hash for `Ordinal` has changed to something more bit-scrambling.
`import hashes; proc hash(x: myInt): Hash = hashIdentity(x)` recovers the old
one in an instantiation context while `-d:nimIntHash1` recovers it globally.
- `deques.peekFirst` and `deques.peekLast` now have `var Deque[T] -> var T` overloads.
- File handles created from high-level abstractions in the stdlib will no longer
be inherited by child processes. In particular, these modules are affected:
`asyncdispatch`, `asyncnet`, `system`, `nativesockets`, `net` and `selectors`.
For `asyncdispatch`, `asyncnet`, `net` and `nativesockets`, an `inheritable`
flag has been added to all `proc`s that create sockets, allowing the user to
control whether the resulting socket is inheritable. This flag is provided to
ease the writing of multi-process servers, where sockets inheritance is
desired.
For a transition period, define `nimInheritHandles` to enable file handle
inheritance by default. This flag does **not** affect the `selectors` module
due to the differing semantics between operating systems.
`asyncdispatch.setInheritable`, `system.setInheritable` and
`nativesockets.setInheritable` are also introduced for setting file handle or
socket inheritance. Not all platforms have these `proc`s defined.
- The file descriptors created for internal bookkeeping by `ioselector_kqueue`
and `ioselector_epoll` will no longer be leaked to child processes.
- `strutils.formatFloat` with `precision = 0` has been restored to the version
1 behaviour that produces a trailing dot, e.g. `formatFloat(3.14159, precision = 0)`
is now `3.`, not `3`.
- Added `commonPrefixLen` to `critbits`.
- `relativePath(rel, abs)` and `relativePath(abs, rel)` used to silently give wrong results
(see #13222); instead they now use `getCurrentDir` to resolve those cases,
and this can now throw in edge cases where `getCurrentDir` throws.
`relativePath` also now works for js with `-d:nodejs`.
- JavaScript and NimScript standard library changes: `streams.StringStream` is
now supported in JavaScript, with the limitation that any buffer `pointer`s
used must be castable to `ptr string`, any incompatible pointer type will not
work. The `lexbase` and `streams` modules used to fail to compile on
NimScript due to a bug, but this has been fixed.
The following modules now compile on both JS and NimScript: `parsecsv`,
`parsecfg`, `parsesql`, `xmlparser`, `htmlparser` and `ropes`. Additionally
supported for JS is `cstrutils.startsWith` and `cstrutils.endsWith`, for
NimScript: `json`, `parsejson`, `strtabs` and `unidecode`.
- Added `streams.readStr` and `streams.peekStr` overloads to
accept an existing string to modify, which avoids memory
allocations, similar to `streams.readLine` (#13857).
- Added high-level `asyncnet.sendTo` and `asyncnet.recvFrom` UDP functionality.
- `dollars.$` now works for unsigned ints with `nim js`.
- Improvements to the `bitops` module, including bitslices, non-mutating versions
of the original masking functions, `mask`/`masked`, and varargs support for
`bitand`, `bitor`, and `bitxor`.
- `sugar.=>` and `sugar.->` changes: Previously `(x, y: int)` was transformed
into `(x: auto, y: int)`, it now becomes `(x: int, y: int)` for consistency
with regular proc definitions (although you cannot use semicolons).
Pragmas and using a name are now allowed on the lefthand side of `=>`. Here
is an example of these changes:
```nim
import sugar
foo(x, y: int) {.noSideEffect.} => x + y
# is transformed into
proc foo(x: int, y: int): auto {.noSideEffect.} = x + y
```
- The fields of `times.DateTime` are now private, and are accessed with getters and deprecated setters.
- The `times` module now handles the default value for `DateTime` more consistently.
Most procs raise an assertion error when given
an uninitialized `DateTime`, the exceptions are `==` and `$` (which returns `"Uninitialized DateTime"`).
The proc `times.isInitialized` has been added which can be used to check if
a `DateTime` has been initialized.
- Fix a bug where calling `close` on io streams in `osproc.startProcess` was a noop and led to
hangs if a process had both reads from stdin and writes (e.g. to stdout).
- The callback that is passed to `system.onThreadDestruction` must now be `.raises: []`.
- The callback that is assigned to `system.onUnhandledException` must now be `.gcsafe`.
- `osproc.execCmdEx` now takes an optional `input` for stdin, `workingDir` and `env`
parameters.
- Added a `ssl_config` module containing lists of secure ciphers as recommended by
[Mozilla OpSec](https://wiki.mozilla.org/Security/Server_Side_TLS)
- `net.newContext` now defaults to the list of ciphers targeting
["Intermediate compatibility"](https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29)
per Mozilla's recommendation instead of `ALL`. This change should protect
users from the use of weak and insecure ciphers while still provides
adequate compatibility with the majority of the Internet.
- A new module `std/jsonutils` with hookable `jsonTo,toJson,fromJson` operations for json
serialization/deserialization of custom types was added.
- A new proc `heapqueue.find[T](heap: HeapQueue[T], x: T): int` to get index of element ``x``
was added.
- Added `rstgen.rstToLatex` a convenience proc for `renderRstToOut` and `initRstGenerator`.
- Added `os.normalizeExe`.
- `macros.newLit` now preserves named vs unnamed tuples.
- Added `random.gauss`, that uses the ratio of uniforms method of sampling from a Gaussian distribution.
- Added `typetraits.elementType` to get the element type of an iterable.
- `typetraits.$` changes: `$(int,)` is now `"(int,)"` instead of `"(int)"`;
`$tuple[]` is now `"tuple[]"` instead of `"tuple"`;
`$((int, float), int)` is now `"((int, float), int)"` instead of `"(tuple of (int, float), int)"`
- Added `macros.extractDocCommentsAndRunnables` helper.
- `strformat.fmt` and `strformat.&` support `specifier =`. `fmt"{expr=}"` now
expands to `fmt"expr={expr}"`.
- Deprecations: instead of `os.existsDir` use `dirExists`, instead of `os.existsFile` use `fileExists`.
- Added the `jsre` module, [Regular Expressions for the JavaScript target.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions).
- Made `maxLines` argument `Positive` in `logging.newRollingFileLogger`,
because negative values will result in a new file being created for each logged
line which doesn't make sense.
- Changed `log` in `logging` to use proper log level for JavaScript,
e.g. `debug` uses `console.debug`, `info` uses `console.info`, `warn` uses `console.warn`, etc.
- Tables, HashSets, SharedTables and deques don't require anymore that the passed
initial size must be a power of two - this is done internally.
Proc `rightSize` for Tables and HashSets is deprecated, as it is not needed anymore.
`CountTable.inc` takes `val: int` again not `val: Positive`; i.e. it can "count down" again.
- Removed deprecated symbols from `macros` module, some of which were deprecated already in `0.15`.
- Removed `sugar.distinctBase`, deprecated since `0.19`. Use `typetraits.distinctBase`.
- `asyncdispatch.PDispatcher.handles` is exported so that an external low-level libraries can access it.
- `std/with`, `sugar.dup` now support object field assignment expressions:
```nim
import std/with
type Foo = object
x, y: int
var foo = Foo()
with foo:
x = 10
y = 20
echo foo
```
- Proc `math.round` is no longer deprecated. The advice to use `strformat` instead
cannot be applied to every use case. The limitations and the (lack of) reliability
of `round` are well documented.
- Added `getprotobyname` to `winlean`. Added `getProtoByname` to `nativesockets` which returns a protocol code
from the database that matches the protocol `name`.
- Added missing attributes and methods to `dom.Navigator` like `deviceMemory`, `onLine`, `vibrate()`, etc.
- Added `strutils.indentation` and `strutils.dedent` which enable indented string literals:
```nim
import strutils
echo dedent """
This
is
cool!
"""
```
- Added `initUri(isIpv6: bool)` to `uri` module, now `uri` supports parsing ipv6 hostname.
- Added `readLines(p: Process)` to `osproc`.
- Added the below `toX` procs for collections. The usage is similar to procs such as
`sets.toHashSet` and `tables.toTable`. Previously, it was necessary to create the
respective empty collection and add items manually.
* `critbits.toCritBitTree`, which creates a `CritBitTree` from an `openArray` of
items or an `openArray` of pairs.
* `deques.toDeque`, which creates a `Deque` from an `openArray`.
* `heapqueue.toHeapQueue`, which creates a `HeapQueue` from an `openArray`.
* `intsets.toIntSet`, which creates an `IntSet` from an `openArray`.
- Added `progressInterval` argument to `asyncftpclient.newAsyncFtpClient` to control the interval
at which progress callbacks are called.
- Added `os.copyFileToDir`.
## Language changes
- The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts
`wasMoved` calls where needed.
- The `=` hook is now called `=copy` for clarity. The old name `=` is still available so there
is no need to update your code. This change was backported to 1.2 too so you can use the
more readable `=copy` without loss of compatibility.
- In the newruntime it is now allowed to assign to the discriminator field
without restrictions as long as the case object doesn't have a custom destructor.
The discriminator value doesn't have to be a constant either. If you have a
custom destructor for a case object and you do want to freely assign discriminator
fields, it is recommended to refactor the object into 2 objects like this:
```nim
type
MyObj = object
case kind: bool
of true: y: ptr UncheckedArray[float]
of false: z: seq[int]
proc `=destroy`(x: MyObj) =
if x.kind and x.y != nil:
deallocShared(x.y)
```
Refactor into:
```nim
type
MySubObj = object
val: ptr UncheckedArray[float]
MyObj = object
case kind: bool
of true: y: MySubObj
of false: z: seq[int]
proc `=destroy`(x: MySubObj) =
if x.val != nil:
deallocShared(x.val)
```
- `getImpl` on enum type symbols now returns field syms instead of idents. This helps
with writing typed macros. The old behavior for backwards compatibility can be restored
with `--useVersion:1.0`.
- The typed AST for proc headers will now have the arguments be syms instead of idents.
This helps with writing typed macros. The old behaviour for backwards compatibility can
be restored with `--useVersion:1.0`.
- ``let`` statements can now be used without a value if declared with
``importc``/``importcpp``/``importjs``/``importobjc``.
- The keyword `from` is now usable as an operator.
- Exceptions inheriting from `system.Defect` are no longer tracked with
the `.raises: []` exception tracking mechanism. This is more consistent with the
built-in operations. The following always used to compile (and still does):
```nim
proc mydiv(a, b): int {.raises: [].} =
a div b # can raise an DivByZeroDefect
```
Now also this compiles:
```nim
proc mydiv(a, b): int {.raises: [].} =
if b == 0: raise newException(DivByZeroDefect, "division by zero")
else: result = a div b
```
The reason for this is that `DivByZeroDefect` inherits from `Defect` and
with `--panics:on` `Defects` become unrecoverable errors.
- Added the `thiscall` calling convention as specified by Microsoft, mostly for hooking purposes.
- Deprecated the `{.unroll.}` pragma, because it was always ignored by the compiler anyway.
- Removed the deprecated `strutils.isNilOrWhitespace`.
- Removed the deprecated `sharedtables.initSharedTable`.
- Removed the deprecated `asyncdispatch.newAsyncNativeSocket`.
- Removed the deprecated `dom.releaseEvents` and `dom.captureEvents`.
- Removed `sharedlists.initSharedList`, was deprecated and produces undefined behaviour.
- There is a new experimental feature called "strictFuncs" which makes the definition of
`.noSideEffect` stricter. [See here](manual_experimental.html#stricts-funcs)
for more information.
- "for-loop macros" (see [the manual](manual.html#macros-for-loop-macros)) are no longer
an experimental feature. In other words, you don't have to write pragma
`{.experimental: "forLoopMacros".}` if you want to use them.
- Added the ``.noalias`` pragma. It is mapped to C's ``restrict`` keyword for the increased
performance this keyword can enable.
- `items` no longer compiles with enums with holes as its behavior was error prone, see #14004.
- `system.deepcopy` has to be enabled explicitly for `--gc:arc` and `--gc:orc` via
`--deepcopy:on`.
- Added the `std/effecttraits` module for introspection of the inferred effects.
We hope this enables `async` macros that are precise about the possible exceptions that
can be raised.
- The pragma blocks `{.gcsafe.}: ...` and `{.noSideEffect.}: ...` can now also be
written as `{.cast(gcsafe).}: ...` and `{.cast(noSideEffect).}: ...`. This is the new
preferred way of writing these, emphasizing their unsafe nature.
## Compiler changes
- Specific warnings can now be turned into errors via `--warningAsError[X]:on|off`.
- The `define` and `undef` pragmas have been de-deprecated.
- New command: `nim r main.nim [args...]` which compiles and runs main.nim, and implies `--usenimcache`
so that the output is saved to $nimcache/main$exeExt, using the same logic as `nim c -r` to
avoid recompilations when sources don't change.
Example:
```bash
nim r compiler/nim.nim --help # only compiled the first time
echo 'import os; echo getCurrentCompilerExe()' | nim r - # this works too
nim r compiler/nim.nim --fullhelp # no recompilation
nim r --nimcache:/tmp main # binary saved to /tmp/main
```
- `--hint:processing` is now supported and means `--hint:processing:on`
(likewise with other hints and warnings), which is consistent with all other bool flags.
(since 1.3.3).
- `nim doc -r main` and `nim rst2html -r main` now call `openDefaultBrowser`.
- Added the new hint `--hint:msgOrigin` will show where a compiler msg (hint|warning|error)
was generated; this helps in particular when it's non obvious where it came from
either because multiple locations generate the same message, or because the
message involves runtime formatting.
- Added the new flag `--backend:js|c|cpp|objc` (or -b:js etc), to change the backend; can be
used with any command (e.g. nim r, doc, check etc); safe to re-assign.
- Added the new flag `--doccmd:cmd` to pass additional flags for runnableExamples,
e.g.: `--doccmd:-d:foo --threads`
use `--doccmd:skip` to skip runnableExamples and rst test snippets.
- Added the new flag `--usenimcache` to output binary files to nimcache.
- `runnableExamples "-b:cpp -r:off": code` is now supported, allowing to override
how an example is compiled and run, for example to change the backend.
- `nim doc` now outputs under `$projectPath/htmldocs` when `--outdir` is unspecified
(with or without `--project`); passing `--project` now automatically generates
an index and enables search.
See [docgen](docgen.html#introduction-quick-start) for details.
- Removed the `--oldNewlines` switch.
- Removed the `--laxStrings` switch for mutating the internal zero terminator on strings.
- Removed the `--oldast` switch.
- Removed the `--oldgensym` switch.
- `$getType(untyped)` is now "untyped" instead of "expr", `$getType(typed)` is
now "typed" instead of "stmt".
- Sink inference is now disabled per default and has to enabled explicitly via
`--sinkInference:on`. *Note*: For the standard library sink inference remains
enabled. This change is most relevant for the `--gc:arc`, `--gc:orc` memory
management modes.
## Tool changes
- `nimsuggest` now returns both the forward declaration and the
implementation location upon a `def` query. Previously the behavior was
to return the forward declaration only.
## Bugfixes
- Fixed "repr() not available for uint{,8,16,32,64} under --gc:arc"
([#13872](https://github.com/nim-lang/Nim/issues/13872))
- Fixed "Critical: 1 completed Future, multiple await: Only 1 await will be awakened (the last one)"
([#13889](https://github.com/nim-lang/Nim/issues/13889))
- Fixed "crash on openarray interator with argument in stmtListExpr"
([#13739](https://github.com/nim-lang/Nim/issues/13739))
- Fixed "Some compilers on Windows don't work"
([#13910](https://github.com/nim-lang/Nim/issues/13910))
- Fixed "httpclient hangs if it recieves an HTTP 204 (No Content)"
([#13894](https://github.com/nim-lang/Nim/issues/13894))
- Fixed ""distinct uint64" type corruption on 32-bit, when using {.borrow.} operators"
([#13902](https://github.com/nim-lang/Nim/issues/13902))
- Fixed "Regression: impossible to use typed pragmas with proc types"
([#13909](https://github.com/nim-lang/Nim/issues/13909))
- Fixed "openssl wrapper corrupts stack on OpenSSL 1.1.1f + Android"
([#13903](https://github.com/nim-lang/Nim/issues/13903))
- Fixed "C compile error with --gc:arc on version 1.2.0 "unknown type name 'TGenericSeq'"
([#13863](https://github.com/nim-lang/Nim/issues/13863))
- Fixed "var return type for proc doesn't work at c++ backend"
([#13848](https://github.com/nim-lang/Nim/issues/13848))
- Fixed "TimeFormat() should raise an error but craches at compilation time"
([#12864](https://github.com/nim-lang/Nim/issues/12864))
- Fixed "gc:arc cannot fully support threadpool with FlowVar"
([#13781](https://github.com/nim-lang/Nim/issues/13781))
- Fixed "simple 'var openarray[char]' assignment crash when the openarray source is a local string and using gc:arc"
([#14003](https://github.com/nim-lang/Nim/issues/14003))
- Fixed "Cant use expressions with `when` in `type` sections."
([#14007](https://github.com/nim-lang/Nim/issues/14007))
- Fixed "`for a in MyEnum` gives incorrect results with enum with holes"
([#14001](https://github.com/nim-lang/Nim/issues/14001))
- Fixed "Trivial crash"
([#12741](https://github.com/nim-lang/Nim/issues/12741))
- Fixed "Enum with holes cannot be used as Table index"
([#12834](https://github.com/nim-lang/Nim/issues/12834))
- Fixed "spawn proc that uses typedesc crashes the compiler"
([#14014](https://github.com/nim-lang/Nim/issues/14014))
- Fixed "Docs Search `Results` box styling is not Dark Mode Friendly"
([#13972](https://github.com/nim-lang/Nim/issues/13972))
- Fixed "--gc:arc -d:useSysAssert undeclared identifier `cstderr` with newSeq"
([#14038](https://github.com/nim-lang/Nim/issues/14038))
- Fixed "issues in the manual"
([#12486](https://github.com/nim-lang/Nim/issues/12486))
- Fixed "Annoying warning: inherit from a more precise exception type like ValueError, IOError or OSError [InheritFromException]"
([#14052](https://github.com/nim-lang/Nim/issues/14052))
- Fixed "relativePath("foo", "/") and relativePath("/", "foo") is wrong"
([#13222](https://github.com/nim-lang/Nim/issues/13222))
- Fixed "[regression] `parseEnum` does not work anymore for enums with holes"
([#14030](https://github.com/nim-lang/Nim/issues/14030))
- Fixed "Exception types in the stdlib should inherit from `CatchableError` or `Defect`, not `Exception`"
([#10288](https://github.com/nim-lang/Nim/issues/10288))
- Fixed "Make debugSend and debugRecv procs public in smtp.nim"
([#12189](https://github.com/nim-lang/Nim/issues/12189))
- Fixed "xmltree need add raw text, when add style element"
([#14064](https://github.com/nim-lang/Nim/issues/14064))
- Fixed "raises requirement does not propagate to derived methods"
([#8481](https://github.com/nim-lang/Nim/issues/8481))
- Fixed "tests/stdlib/tgetaddrinfo.nim fails on NetBSD"
([#14091](https://github.com/nim-lang/Nim/issues/14091))
- Fixed "tests/niminaction/Chapter8/sdl/sdl_test.nim fails on NetBSD"
([#14088](https://github.com/nim-lang/Nim/issues/14088))
- Fixed "Incorrect escape sequence for example in jsffi library documentation"
([#14110](https://github.com/nim-lang/Nim/issues/14110))
- Fixed "HCR: Can not link exported const, in external library"
([#13915](https://github.com/nim-lang/Nim/issues/13915))
- Fixed "Cannot import std/unidecode"
([#14112](https://github.com/nim-lang/Nim/issues/14112))
- Fixed "macOS: dsymutil should not be called on static libraries"
([#14132](https://github.com/nim-lang/Nim/issues/14132))
- Fixed "nim jsondoc -o:doc.json filename.nim fails when sequences without a type are used"
([#14066](https://github.com/nim-lang/Nim/issues/14066))
- Fixed "algorithm.sortedByIt template corrupts tuple input under --gc:arc"
([#14079](https://github.com/nim-lang/Nim/issues/14079))
- Fixed "Invalid C code with lvalue conversion"
([#14160](https://github.com/nim-lang/Nim/issues/14160))
- Fixed "strformat: doc example fails"
([#14054](https://github.com/nim-lang/Nim/issues/14054))
- Fixed "Nim doc fail to run for nim 1.2.0 (nim 1.0.4 is ok)"
([#13986](https://github.com/nim-lang/Nim/issues/13986))
- Fixed "Exception when converting csize to clong"
([#13698](https://github.com/nim-lang/Nim/issues/13698))
- Fixed "[Documentation] overloading using named arguments works but is not documented"
([#11932](https://github.com/nim-lang/Nim/issues/11932))
- Fixed "import os + use of existsDir/dirExists/existsFile/fileExists/findExe in config.nims causes "ambiguous call' error"
([#14142](https://github.com/nim-lang/Nim/issues/14142))
- Fixed "import os + use of existsDir/dirExists/existsFile/fileExists/findExe in config.nims causes "ambiguous call' error"
([#14142](https://github.com/nim-lang/Nim/issues/14142))
- Fixed "runnableExamples doc gen crashes compiler with `except Exception as e` syntax"
([#14177](https://github.com/nim-lang/Nim/issues/14177))
- Fixed "[ARC] Segfault with cyclic references (?)"
([#14159](https://github.com/nim-lang/Nim/issues/14159))
- Fixed "Semcheck regression when accessing a static parameter in proc"
([#14136](https://github.com/nim-lang/Nim/issues/14136))
- Fixed "iterator walkDir doesn't work with -d:useWinAnsi"
([#14201](https://github.com/nim-lang/Nim/issues/14201))
- Fixed "cas is wrong for tcc"
([#14151](https://github.com/nim-lang/Nim/issues/14151))
- Fixed "proc execCmdEx doesn't work with -d:useWinAnsi"
([#14203](https://github.com/nim-lang/Nim/issues/14203))
- Fixed "Use -d:nimEmulateOverflowChecks by default?"
([#14209](https://github.com/nim-lang/Nim/issues/14209))
- Fixed "Old sequences with destructor objects bug"
([#14217](https://github.com/nim-lang/Nim/issues/14217))
- Fixed "[ARC] ICE when changing the discriminant of a return value"
([#14244](https://github.com/nim-lang/Nim/issues/14244))
- Fixed "[ARC] ICE with static objects"
([#14236](https://github.com/nim-lang/Nim/issues/14236))
- Fixed "[ARC] "internal error: environment misses: a" in a finalizer"
([#14243](https://github.com/nim-lang/Nim/issues/14243))
- Fixed "[ARC] compile failure using repr with object containing `ref seq[string]`"
([#14270](https://github.com/nim-lang/Nim/issues/14270))
- Fixed "[ARC] implicit move on last use happening on non-last use"
([#14269](https://github.com/nim-lang/Nim/issues/14269))
- Fixed "[ARC] Compiler crash with a recursive non-ref object variant"
([#14294](https://github.com/nim-lang/Nim/issues/14294))
- Fixed "htmlparser.parseHtml behaves differently using --gc:arc or --gc:orc"
([#13946](https://github.com/nim-lang/Nim/issues/13946))
- Fixed "Invalid return value of openProcess is NULL rather than INVALID_HANDLE_VALUE(-1) in windows"
([#14289](https://github.com/nim-lang/Nim/issues/14289))
- Fixed "ARC codegen bug with inline iterators"
([#14219](https://github.com/nim-lang/Nim/issues/14219))
- Fixed "Building koch on OpenBSD fails unless the Nim directory is in `$PATH`"
([#13758](https://github.com/nim-lang/Nim/issues/13758))
- Fixed "[gc:arc] case object assignment SIGSEGV: destroy not called for primitive type "
([#14312](https://github.com/nim-lang/Nim/issues/14312))
- Fixed "Crash when using thread and --gc:arc "
([#13881](https://github.com/nim-lang/Nim/issues/13881))
- Fixed "Getting "Warning: Cannot prove that 'result' is initialized" for an importcpp'd proc with `var T` return type"
([#14314](https://github.com/nim-lang/Nim/issues/14314))
- Fixed "`nim cpp -r --gc:arc` segfaults on caught AssertionError"
([#13071](https://github.com/nim-lang/Nim/issues/13071))
- Fixed "tests/async/tasyncawait.nim is recently very flaky"
([#14320](https://github.com/nim-lang/Nim/issues/14320))
- Fixed "Documentation nonexistent quitprocs module"
([#14331](https://github.com/nim-lang/Nim/issues/14331))
- Fixed "SIGSEV encountered when creating threads in a loop w/ --gc:arc"
([#13935](https://github.com/nim-lang/Nim/issues/13935))
- Fixed "nim-gdb is missing from all released packages"
([#13104](https://github.com/nim-lang/Nim/issues/13104))
- Fixed "sysAssert error with gc:arc on 3 line program"
([#13862](https://github.com/nim-lang/Nim/issues/13862))
- Fixed "compiler error with inline async proc and pragma"
([#13998](https://github.com/nim-lang/Nim/issues/13998))
- Fixed "[ARC] Compiler crash when adding to a seq[ref Object]"
([#14333](https://github.com/nim-lang/Nim/issues/14333))
- Fixed "nimvm: sysFatal: unhandled exception: 'sons' is not accessible using discriminant 'kind' of type 'TNode' [FieldError]"
([#14340](https://github.com/nim-lang/Nim/issues/14340))
- Fixed "[Regression] karax events are not firing "
([#14350](https://github.com/nim-lang/Nim/issues/14350))
- Fixed "odbcsql module has some wrong integer types"
([#9771](https://github.com/nim-lang/Nim/issues/9771))
- Fixed "db_sqlite needs sqlPrepared"
([#13559](https://github.com/nim-lang/Nim/issues/13559))
- Fixed "[Regression] `createThread` is not GC-safe"
([#14370](https://github.com/nim-lang/Nim/issues/14370))
- Fixed "Broken example on hot code reloading"
([#14380](https://github.com/nim-lang/Nim/issues/14380))
- Fixed "runnableExamples block with `except` on specified error fails with `nim doc`"
([#12746](https://github.com/nim-lang/Nim/issues/12746))
- Fixed "compiler as a library: findNimStdLibCompileTime fails to find system.nim"
([#12293](https://github.com/nim-lang/Nim/issues/12293))
- Fixed "5 bugs with importcpp exceptions"
([#14369](https://github.com/nim-lang/Nim/issues/14369))
- Fixed "Docs shouldn't collapse pragmas inside runnableExamples/code blocks"
([#14174](https://github.com/nim-lang/Nim/issues/14174))
- Fixed "Bad codegen/emit for hashes.hiXorLo in some contexts."
([#14394](https://github.com/nim-lang/Nim/issues/14394))
- Fixed "Boehm GC does not scan thread-local storage"
([#14364](https://github.com/nim-lang/Nim/issues/14364))
- Fixed "RVO not exception safe"
([#14126](https://github.com/nim-lang/Nim/issues/14126))
- Fixed "runnableExamples that are only compiled"
([#10731](https://github.com/nim-lang/Nim/issues/10731))
- Fixed "`foldr` raises IndexError when called on sequence"
([#14404](https://github.com/nim-lang/Nim/issues/14404))
- Fixed "moveFile does not overwrite destination file"
([#14057](https://github.com/nim-lang/Nim/issues/14057))
- Fixed "doc2 outputs in current work dir"
([#6583](https://github.com/nim-lang/Nim/issues/6583))
- Fixed "[docgen] proc doc comments silently omitted after 1st runnableExamples"
([#9227](https://github.com/nim-lang/Nim/issues/9227))
- Fixed "`nim doc --project` shows '@@/' instead of '../' for relative paths to submodules"
([#14448](https://github.com/nim-lang/Nim/issues/14448))
- Fixed "re, nre have wrong `start` semantics"
([#14284](https://github.com/nim-lang/Nim/issues/14284))
- Fixed "runnableExamples should preserve source code doc comments, strings, and (maybe) formatting"
([#8871](https://github.com/nim-lang/Nim/issues/8871))
- Fixed "`nim doc ..` fails when runnableExamples uses `$` [devel] [regression]"
([#14485](https://github.com/nim-lang/Nim/issues/14485))
- Fixed "`items` is 20%~30% slower than iteration via an index"
([#14421](https://github.com/nim-lang/Nim/issues/14421))
- Fixed "ARC: unreliable setLen "
([#14495](https://github.com/nim-lang/Nim/issues/14495))
- Fixed "lent is unsafe: after #14447 you can modify variables with "items" loop for sequences"
([#14498](https://github.com/nim-lang/Nim/issues/14498))
- Fixed "`var op = fn()` wrongly gives warning `ObservableStores` with `object of RootObj` type"
([#14514](https://github.com/nim-lang/Nim/issues/14514))
- Fixed "Compiler assertion"
([#14562](https://github.com/nim-lang/Nim/issues/14562))
- Fixed "Can't get `ord` of a value of a Range type in the JS backend "
([#14570](https://github.com/nim-lang/Nim/issues/14570))
- Fixed "js: can't take addr of param (including implicitly via `lent`)"
([#14576](https://github.com/nim-lang/Nim/issues/14576))
- Fixed "{.noinit.} ignored in for loop -> bad codegen for non-movable types"
([#14118](https://github.com/nim-lang/Nim/issues/14118))
- Fixed "generic destructor gives: `Error: unresolved generic parameter`"
([#14315](https://github.com/nim-lang/Nim/issues/14315))
- Fixed "Memory leak with arc gc"
([#14568](https://github.com/nim-lang/Nim/issues/14568))
- Fixed "escape analysis broken with `lent`"
([#14557](https://github.com/nim-lang/Nim/issues/14557))
- Fixed "`wrapWords` seems to ignore linebreaks when wrapping, leaving breaks in the wrong place"
([#14579](https://github.com/nim-lang/Nim/issues/14579))
- Fixed "`lent` gives wrong results with -d:release"
([#14578](https://github.com/nim-lang/Nim/issues/14578))
- Fixed "Nested await expressions regression: `await a(await expandValue())` doesnt compile"
([#14279](https://github.com/nim-lang/Nim/issues/14279))
- Fixed "windows CI docs fails with strange errors"
([#14545](https://github.com/nim-lang/Nim/issues/14545))
- Fixed "[CI] tests/async/tioselectors.nim flaky test for freebsd + OSX CI"
([#13166](https://github.com/nim-lang/Nim/issues/13166))
- Fixed "seq.setLen sometimes doesn't zero memory"
([#14655](https://github.com/nim-lang/Nim/issues/14655))
- Fixed "`nim dump` is roughly 100x slower in 1.3 versus 1.2"
([#14179](https://github.com/nim-lang/Nim/issues/14179))
- Fixed "Regression: devel docgen cannot generate document for method"
([#14691](https://github.com/nim-lang/Nim/issues/14691))
- Fixed "recently flaky tests/async/t7758.nim"
([#14685](https://github.com/nim-lang/Nim/issues/14685))
- Fixed "Bind no longer working in generic procs."
([#11811](https://github.com/nim-lang/Nim/issues/11811))
- Fixed "The pegs module doesn't work with generics!"
([#14718](https://github.com/nim-lang/Nim/issues/14718))
- Fixed "Defer is not properly working for asynchronous procedures."
([#13899](https://github.com/nim-lang/Nim/issues/13899))
- Fixed "Add an ARC test with threads in a loop"
([#14690](https://github.com/nim-lang/Nim/issues/14690))
- Fixed "[goto exceptions] {.noReturn.} pragma is not detected in a case expression"
([#14458](https://github.com/nim-lang/Nim/issues/14458))
- Fixed "[exceptions:goto] C compiler error with dynlib pragma calling a proc"
([#14240](https://github.com/nim-lang/Nim/issues/14240))
- Fixed "Cannot borrow var float64 in infix assignment"
([#14440](https://github.com/nim-lang/Nim/issues/14440))
- Fixed "lib/pure/memfiles.nim: compilation error with --taintMode:on"
([#14760](https://github.com/nim-lang/Nim/issues/14760))
- Fixed "newWideCString allocates a multiple of the memory needed"
([#14750](https://github.com/nim-lang/Nim/issues/14750))
- Fixed "Nim source archive install: 'install.sh' fails with error: cp: cannot stat 'bin/nim-gdb': No such file or directory"
([#14748](https://github.com/nim-lang/Nim/issues/14748))
- Fixed "`nim cpp -r tests/exception/t9657` hangs"
([#10343](https://github.com/nim-lang/Nim/issues/10343))
- Fixed "Detect tool fails on FreeBSD"
([#14715](https://github.com/nim-lang/Nim/issues/14715))
- Fixed "compiler crash: `findUnresolvedStatic` "
([#14802](https://github.com/nim-lang/Nim/issues/14802))
- Fixed "seq namespace (?) regression"
([#4796](https://github.com/nim-lang/Nim/issues/4796))
- Fixed "Possible out of bounds string access in std/colors parseColor and isColor"
([#14839](https://github.com/nim-lang/Nim/issues/14839))
- Fixed "compile error on latest devel with orc and ssl"
([#14647](https://github.com/nim-lang/Nim/issues/14647))
- Fixed "[minor] `$` wrong for type tuple"
([#13432](https://github.com/nim-lang/Nim/issues/13432))
- Fixed "Documentation missing on devel asyncftpclient"
([#14846](https://github.com/nim-lang/Nim/issues/14846))
- Fixed "nimpretty is confused with a trailing comma in enum definition"
([#14401](https://github.com/nim-lang/Nim/issues/14401))
- Fixed "Output arguments get ignored when compiling with --app:staticlib"
([#12745](https://github.com/nim-lang/Nim/issues/12745))
- Fixed "[ARC] destructive move destroys the object too early"
([#14396](https://github.com/nim-lang/Nim/issues/14396))
- Fixed "highlite.getNextToken() crashes if the buffer string is "echo "\"""
([#14830](https://github.com/nim-lang/Nim/issues/14830))
- Fixed "Memory corruption with --gc:arc with a seq of objects with an empty body."
([#14472](https://github.com/nim-lang/Nim/issues/14472))
- Fixed "Stropped identifiers don't work as field names in tuple literals"
([#14911](https://github.com/nim-lang/Nim/issues/14911))
- Fixed "Please revert my commit"
([#14930](https://github.com/nim-lang/Nim/issues/14930))
- Fixed "[ARC] C compiler error with inline iterators and imports"
([#14864](https://github.com/nim-lang/Nim/issues/14864))
- Fixed "AsyncHttpClient segfaults with gc:orc, possibly memory corruption"
([#14402](https://github.com/nim-lang/Nim/issues/14402))
- Fixed "[ARC] Template with a block evaluating to a GC'd value results in a compiler crash"
([#14899](https://github.com/nim-lang/Nim/issues/14899))
- Fixed "[ARC] Weird issue with if expressions and templates"
([#14900](https://github.com/nim-lang/Nim/issues/14900))
- Fixed "xmlparser does not compile on devel"
([#14805](https://github.com/nim-lang/Nim/issues/14805))
- Fixed "returning lent T from a var T param gives codegen errors or SIGSEGV"
([#14878](https://github.com/nim-lang/Nim/issues/14878))
- Fixed "[ARC] Weird issue with if expressions and templates"
([#14900](https://github.com/nim-lang/Nim/issues/14900))
- Fixed "threads:on + gc:orc + unittest = C compiler errors"
([#14865](https://github.com/nim-lang/Nim/issues/14865))
- Fixed "mitems, mpairs doesn't work at compile time anymore"
([#12129](https://github.com/nim-lang/Nim/issues/12129))
- Fixed "strange result from executing code in const expression"
([#10465](https://github.com/nim-lang/Nim/issues/10465))
- Fixed "Same warning printed 3 times"
([#11009](https://github.com/nim-lang/Nim/issues/11009))
- Fixed "type alias for generic typeclass doesn't work"
([#4668](https://github.com/nim-lang/Nim/issues/4668))
- Fixed "exceptions:goto Bug devel codegen lvalue NIM_FALSE=NIM_FALSE"
([#14925](https://github.com/nim-lang/Nim/issues/14925))
- Fixed "the --useVersion:1.0 no longer works in devel"
([#14912](https://github.com/nim-lang/Nim/issues/14912))
- Fixed "template declaration of iterator doesn't compile"
([#4722](https://github.com/nim-lang/Nim/issues/4722))
- Fixed "Compiler crash on type inheritance with static generic parameter and equality check"
([#12571](https://github.com/nim-lang/Nim/issues/12571))
- Fixed "Nim crashes while handling a cast in async circumstances."
([#13815](https://github.com/nim-lang/Nim/issues/13815))
- Fixed "[ARC] Internal compiler error when calling an iterator from an inline proc "
([#14383](https://github.com/nim-lang/Nim/issues/14383))
- Fixed ""Cannot instantiate" error when template uses generic type"
([#5926](https://github.com/nim-lang/Nim/issues/5926))
- Fixed "Different raises behaviour for newTerminal between Linux and Windows"
([#12759](https://github.com/nim-lang/Nim/issues/12759))
- Fixed "Expand on a type (that defines a proc type) in error message "
([#6608](https://github.com/nim-lang/Nim/issues/6608))
- Fixed "unittest require quits program with an exit code of 0"
([#14475](https://github.com/nim-lang/Nim/issues/14475))
- Fixed "Range type: Generics vs concrete type, semcheck difference."
([#8426](https://github.com/nim-lang/Nim/issues/8426))
- Fixed "[Macro] Type mismatch when parameter name is the same as a field"
([#13253](https://github.com/nim-lang/Nim/issues/13253))
- Fixed "Generic instantiation failure when converting a sequence of circular generic types to strings"
([#10396](https://github.com/nim-lang/Nim/issues/10396))
- Fixed "initOptParser ignores argument after value option with empty value."
([#13086](https://github.com/nim-lang/Nim/issues/13086))
- Fixed "[ARC] proc with both explicit and implicit return results in a C compiler error"
([#14985](https://github.com/nim-lang/Nim/issues/14985))
- Fixed "Alias type forgets implicit generic params depending on order"
([#14990](https://github.com/nim-lang/Nim/issues/14990))
- Fixed "[ARC] sequtils.insert has different behaviour between ARC/refc"
([#14994](https://github.com/nim-lang/Nim/issues/14994))
- Fixed "The documentation for "hot code reloading" references a non-existent npm package"
([#13621](https://github.com/nim-lang/Nim/issues/13621))
- Fixed "existsDir deprecated but breaking `dir` undeclared"
([#15006](https://github.com/nim-lang/Nim/issues/15006))
- Fixed "uri.decodeUrl crashes on incorrectly formatted input"
([#14082](https://github.com/nim-lang/Nim/issues/14082))
- Fixed "testament incorrectly reports time for tests, leading to wrong conclusions"
([#14822](https://github.com/nim-lang/Nim/issues/14822))
- Fixed "Calling peekChar with Stream returned from osproc.outputStream generate runtime error"
([#14906](https://github.com/nim-lang/Nim/issues/14906))
- Fixed "localPassC pragma should come *after* other flags"
([#14194](https://github.com/nim-lang/Nim/issues/14194))
- Fixed ""Could not load" dynamic library at runtime because of hidden dependency"
([#2408](https://github.com/nim-lang/Nim/issues/2408))
- Fixed "--gc:arc generate invalid code for {.global.} (`«nimErr_» in NIM_UNLIKELY`)"
([#14480](https://github.com/nim-lang/Nim/issues/14480))
- Fixed "Using `^` from stdlib/math along with converters gives a match for types that aren't SomeNumber"
([#15033](https://github.com/nim-lang/Nim/issues/15033))
- Fixed "[ARC] Weird exception behaviour from doAssertRaises"
([#15026](https://github.com/nim-lang/Nim/issues/15026))
- Fixed "[ARC] Compiler crash declaring a finalizer proc directly in 'new'"
([#15044](https://github.com/nim-lang/Nim/issues/15044))
- Fixed "[ARC] C compiler error when creating a var of a const seq"
([#15036](https://github.com/nim-lang/Nim/issues/15036))
- Fixed "code with named arguments in proc of winim/com can not been compiled"
([#15056](https://github.com/nim-lang/Nim/issues/15056))
- Fixed "javascript backend produces javascript code with syntax error in object syntax"
([#14534](https://github.com/nim-lang/Nim/issues/14534))
- Fixed "--gc:arc should be ignored in JS mode."
([#14684](https://github.com/nim-lang/Nim/issues/14684))
- Fixed "arc: C compilation error with imported global code using a closure iterator"
([#12990](https://github.com/nim-lang/Nim/issues/12990))
- Fixed "[ARC] Crash when modifying a string with mitems iterator"
([#15052](https://github.com/nim-lang/Nim/issues/15052))
- Fixed "[ARC] SIGSEGV when calling a closure as a tuple field in a seq"
([#15038](https://github.com/nim-lang/Nim/issues/15038))
- Fixed "pass varargs[seq[T]] to iterator give empty seq "
([#12576](https://github.com/nim-lang/Nim/issues/12576))
- Fixed "Compiler crashes when using string as object variant selector with else branch"
([#14189](https://github.com/nim-lang/Nim/issues/14189))
- Fixed "JS compiler error related to implicit return and return var type"
([#11354](https://github.com/nim-lang/Nim/issues/11354))
- Fixed "`nkRecWhen` causes internalAssert in semConstructFields"
([#14698](https://github.com/nim-lang/Nim/issues/14698))
- Fixed "Memory leaks with async (closure iterators?) under ORC"
([#15076](https://github.com/nim-lang/Nim/issues/15076))
- Fixed "strutil.insertSep() fails on negative numbers"
([#11352](https://github.com/nim-lang/Nim/issues/11352))
- Fixed "Constructing a uint64 range on a 32-bit machine leads to incorrect codegen"
([#14616](https://github.com/nim-lang/Nim/issues/14616))
- Fixed "heapqueue pushpop() proc doesn't compile"
([#14139](https://github.com/nim-lang/Nim/issues/14139))
- Fixed "[ARC] SIGSEGV when trying to swap in a literal/const string"
([#15112](https://github.com/nim-lang/Nim/issues/15112))
- Fixed "Defer and --gc:arc"
([#15071](https://github.com/nim-lang/Nim/issues/15071))
- Fixed "internal error: compiler/semobjconstr.nim(324, 20) example"
([#15111](https://github.com/nim-lang/Nim/issues/15111))
- Fixed "[ARC] Sequence "disappears" with a table inside of a table with an object variant"
([#15122](https://github.com/nim-lang/Nim/issues/15122))
- Fixed "[ARC] SIGSEGV with tuple assignment caused by cursor inference"
([#15130](https://github.com/nim-lang/Nim/issues/15130))
- Fixed "Issue with --gc:arc at compile time"
([#15129](https://github.com/nim-lang/Nim/issues/15129))
- Fixed "Writing an empty string to an AsyncFile raises an IndexDefect"
([#15148](https://github.com/nim-lang/Nim/issues/15148))
- Fixed "Compiler is confused about call convention of function with nested closure"
([#5688](https://github.com/nim-lang/Nim/issues/5688))
- Fixed "Nil check on each field fails in generic function"
([#15101](https://github.com/nim-lang/Nim/issues/15101))
- Fixed "{.nimcall.} convention won't avoid the creation of closures"
([#8473](https://github.com/nim-lang/Nim/issues/8473))
- Fixed "smtp.nim(161, 40) Error: type mismatch: got <typeof(nil)> but expected 'SslContext = void'"
([#15177](https://github.com/nim-lang/Nim/issues/15177))
- Fixed "[strscans] scanf doesn't match a single character with $+ if it's the end of the string"
([#15064](https://github.com/nim-lang/Nim/issues/15064))
- Fixed "Crash and incorrect return values when using readPasswordFromStdin on Windows."
([#15207](https://github.com/nim-lang/Nim/issues/15207))
- Fixed "Possible capture error with fieldPairs and genericParams"
([#15221](https://github.com/nim-lang/Nim/issues/15221))
- Fixed "The StmtList processing of template parameters can lead to unexpected errors"
([#5691](https://github.com/nim-lang/Nim/issues/5691))
- Fixed "[ARC] C compiler error when passing a var openArray to a sink openArray"
([#15035](https://github.com/nim-lang/Nim/issues/15035))
- Fixed "Inconsistent unsigned -> signed RangeDefect usage across integer sizes"
([#15210](https://github.com/nim-lang/Nim/issues/15210))
- Fixed "toHex results in RangeDefect exception when used with large uint64"
([#15257](https://github.com/nim-lang/Nim/issues/15257))
- Fixed "Arc sink arg crash"
([#15238](https://github.com/nim-lang/Nim/issues/15238))
- Fixed "SQL escape in db_mysql is not enough"
([#15219](https://github.com/nim-lang/Nim/issues/15219))
- Fixed "Mixing 'return' with expressions is allowed in 1.2"
([#15280](https://github.com/nim-lang/Nim/issues/15280))
- Fixed "os.getFileInfo() causes ICE with --gc:arc on Windows"
([#15286](https://github.com/nim-lang/Nim/issues/15286))
- Fixed "[ARC] Sequence "disappears" with a table inside of a table with an object variant"
([#15122](https://github.com/nim-lang/Nim/issues/15122))
- Fixed "Documentation regression jsre module missing"
([#15183](https://github.com/nim-lang/Nim/issues/15183))
- Fixed "CountTable.smallest/largest() on empty table either asserts or gives bogus answer"
([#15021](https://github.com/nim-lang/Nim/issues/15021))
- Fixed "[Regression] Parser regression"
([#15305](https://github.com/nim-lang/Nim/issues/15305))
- Fixed "[ARC] SIGSEGV with tuple unpacking caused by cursor inference"
([#15147](https://github.com/nim-lang/Nim/issues/15147))
- Fixed "LwIP/FreeRTOS compile error - missing SIGPIPE and more "
([#15302](https://github.com/nim-lang/Nim/issues/15302))
- Fixed "Memory leaks with async (closure iterators?) under ORC"
([#15076](https://github.com/nim-lang/Nim/issues/15076))
- Fixed "Bug compiling with --gc:arg or --gc:orc"
([#15325](https://github.com/nim-lang/Nim/issues/15325))
- Fixed "memory corruption in tmarshall.nim"
([#9754](https://github.com/nim-lang/Nim/issues/9754))
- Fixed "typed macros break generic proc definitions"
([#15326](https://github.com/nim-lang/Nim/issues/15326))
- Fixed "nim doc2 ignores --docSeeSrcUrl parameter"
([#6071](https://github.com/nim-lang/Nim/issues/6071))
- Fixed "The decodeData Iterator from cgi module crash"
([#15369](https://github.com/nim-lang/Nim/issues/15369))
- Fixed "|| iterator generates invalid code when compiling with --debugger:native"
([#9710](https://github.com/nim-lang/Nim/issues/9710))
- Fixed "Wrong number of variables"
([#15360](https://github.com/nim-lang/Nim/issues/15360))
- Fixed "Coercions with distinct types should traverse pointer modifiers transparently."
([#7165](https://github.com/nim-lang/Nim/issues/7165))
- Fixed "Error with distinct generic TableRef"
([#6060](https://github.com/nim-lang/Nim/issues/6060))
- Fixed "Support images in nim docgen"
([#6430](https://github.com/nim-lang/Nim/issues/6430))
- Fixed "Regression. Double sem check for procs."
([#15389](https://github.com/nim-lang/Nim/issues/15389))
- Fixed "uri.nim url with literal ipv6 address is printed wrong, and cannot parsed again"
([#15333](https://github.com/nim-lang/Nim/issues/15333))
- Fixed "[ARC] Object variant gets corrupted with cursor inference"
([#15361](https://github.com/nim-lang/Nim/issues/15361))
- Fixed "`nim doc ..` compiler crash (regression 0.19.6 => 1.0)"
([#14474](https://github.com/nim-lang/Nim/issues/14474))
- Fixed "cannot borrow result; what it borrows from is potentially mutated"
([#15403](https://github.com/nim-lang/Nim/issues/15403))
- Fixed "memory corruption for seq.add(seq) with gc:arc and d:useMalloc "
([#14983](https://github.com/nim-lang/Nim/issues/14983))
- Fixed "DocGen HTML output appears improperly when encountering text immediately after/before inline monospace; in some cases won't compile"
([#11537](https://github.com/nim-lang/Nim/issues/11537))
- Fixed "Deepcopy in arc crashes"
([#15405](https://github.com/nim-lang/Nim/issues/15405))
- Fixed "pop pragma takes invalid input"
([#15430](https://github.com/nim-lang/Nim/issues/15430))
- Fixed "tests/stdlib/tgetprotobyname fails on NetBSD"
([#15452](https://github.com/nim-lang/Nim/issues/15452))
- Fixed "defer doesnt work with block, break and await"
([#15243](https://github.com/nim-lang/Nim/issues/15243))
- Fixed "tests/stdlib/tssl failing on NetBSD"
([#15493](https://github.com/nim-lang/Nim/issues/15493))
- Fixed "strictFuncs doesn't seem to catch simple ref mutation"
([#15508](https://github.com/nim-lang/Nim/issues/15508))
- Fixed "Sizeof of case object is incorrect. Showstopper"
([#15516](https://github.com/nim-lang/Nim/issues/15516))
- Fixed "[ARC] Internal error when trying to use a parallel for loop"
([#15512](https://github.com/nim-lang/Nim/issues/15512))
- Fixed "[ARC] Type-bound assign op is not being generated"
([#15510](https://github.com/nim-lang/Nim/issues/15510))
- Fixed "[ARC] Crash when adding openArray proc argument to a local seq"
([#15511](https://github.com/nim-lang/Nim/issues/15511))
- Fixed "VM: const case object gets some fields zeroed out at runtime"
([#13081](https://github.com/nim-lang/Nim/issues/13081))
- Fixed "regression(1.2.6 => devel): VM: const case object field access gives: 'sons' is not accessible"
([#15532](https://github.com/nim-lang/Nim/issues/15532))
- Fixed "Csources: huge size increase (x2.3) in 0.20"
([#12027](https://github.com/nim-lang/Nim/issues/12027))
- Fixed "Out of date error message for GC options"
([#15547](https://github.com/nim-lang/Nim/issues/15547))
- Fixed "dbQuote additional escape regression"
([#15560](https://github.com/nim-lang/Nim/issues/15560))

View File

@@ -17,21 +17,17 @@ export int128
type
TCallingConvention* = enum
ccDefault, # proc has no explicit calling convention
ccStdCall, # procedure is stdcall
ccCDecl, # cdecl
ccSafeCall, # safecall
ccSysCall, # system call
ccInline, # proc should be inlined
ccNoInline, # proc should not be inlined
ccFastCall, # fastcall (pass parameters in registers)
ccClosure, # proc has a closure
ccNoConvention # needed for generating proper C procs sometimes
const
CallingConvToStr*: array[TCallingConvention, string] = ["", "stdcall",
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall",
"closure", "noconv"]
ccNimCall = "nimcall" # nimcall, also the default
ccStdCall = "stdcall" # procedure is stdcall
ccCDecl = "cdecl" # cdecl
ccSafeCall = "safecall" # safecall
ccSysCall = "syscall" # system call
ccInline = "inline" # proc should be inlined
ccNoInline = "noinline" # proc should not be inlined
ccFastCall = "fastcall" # fastcall (pass parameters in registers)
ccThisCall = "thiscall" # thiscall (parameters are pushed right-to-left)
ccClosure = "closure" # proc has a closure
ccNoConvention = "noconv" # needed for generating proper C procs sometimes
type
TNodeKind* = enum # order is extremely important, because ranges are used
@@ -218,7 +214,7 @@ type
nkEnumFieldDef, # `ident = expr` in an enumeration
nkArgList, # argument list
nkPattern, # a special pattern; used for matching
nkHiddenTryStmt, # token used for interpretation
nkHiddenTryStmt, # a hidden try statement
nkClosure, # (prc, env)-pair (internally used for code gen)
nkGotoState, # used for the state machine (for iterators)
nkState, # give a label to a code section (for iterators)
@@ -229,7 +225,7 @@ type
TNodeKinds* = set[TNodeKind]
type
TSymFlag* = enum # 42 flags!
TSymFlag* = enum # 46 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
@@ -290,9 +286,11 @@ type
sfTemplateParam # symbol is a template parameter
sfCursor # variable/field is a cursor, see RFC 177 for details
sfInjectDestructors # whether the proc needs the 'injectdestructors' transformation
sfNeverRaises # proc can never raise an exception, not even OverflowError
sfNeverRaises # proc can never raise an exception, not even OverflowDefect
# or out-of-memory
sfUsedInFinallyOrExcept # symbol is used inside an 'except' or 'finally'
sfSingleUsedTemp # For temporaries that we know will only be used once
sfNoalias # 'noalias' annotation, means C's 'restrict'
TSymFlags* = set[TSymFlag]
@@ -311,10 +309,6 @@ const
# the compiler will avoid printing such names
# in user messages.
sfHoisted* = sfForward
# an expression was hoised to an anonymous variable.
# the flag is applied to the var/let symbol
sfNoForward* = sfRegister
# forward declarations are not required (per module)
sfReorder* = sfForward
@@ -433,8 +427,9 @@ type
# instantiation and prior to this it has the potential to
# be any type.
tyOpt
# Builtin optional type
tyOptDeprecated
# 'out' parameter. Comparable to a 'var' parameter but every
# path must assign a value to it before it can be read from.
tyVoid
# now different from tyEmpty, hurray!
@@ -554,6 +549,10 @@ type
# If it has one, t.destructor is not nil.
tfAcyclic # object type was annotated as .acyclic
tfIncompleteStruct # treat this type as if it had sizeof(pointer)
tfCompleteStruct
# (for importc types); type is fully specified, allowing to compute
# sizeof, alignof, offsetof at CT
tfExplicitCallConv
TTypeFlags* = set[TTypeFlag]
@@ -610,7 +609,7 @@ var
type
TMagic* = enum # symbols that require compiler magic:
mNone,
mDefined, mDefinedInScope, mCompiles, mArrGet, mArrPut, mAsgn,
mDefined, mDeclared, mDeclaredInScope, mCompiles, mArrGet, mArrPut, mAsgn,
mLow, mHigh, mSizeOf, mAlignOf, mOffsetOf, mTypeTrait,
mIs, mOf, mAddr, mType, mTypeOf,
mPlugin, mEcho, mShallowCopy, mSlurp, mStaticExec, mStatic,
@@ -653,8 +652,8 @@ type
mSwap, mIsNil, mArrToSeq,
mNewString, mNewStringOfCap, mParseBiggestFloat,
mMove, mWasMoved, mDestroy,
mDefault, mUnown, mAccessEnv, mReset,
mArray, mOpenArray, mRange, mSet, mSeq, mOpt, mVarargs,
mDefault, mUnown, mIsolate, mAccessEnv, mReset,
mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
mRef, mPtr, mVar, mDistinct, mVoid, mTuple,
mOrdinal,
mInt, mInt8, mInt16, mInt32, mInt64,
@@ -678,7 +677,7 @@ type
mNBindSym, mNCallSite,
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
mNHint, mNWarning, mNError,
mInstantiationInfo, mGetTypeInfo,
mInstantiationInfo, mGetTypeInfo, mGetTypeInfoV2,
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples,
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
mSymIsInstantiationOf, mNodeId
@@ -808,7 +807,7 @@ type
PInstantiation* = ref TInstantiation
TScope* = object
TScope* {.acyclic.} = object
depthLevel*: int
symbols*: TStrTable
parent*: PScope
@@ -872,7 +871,7 @@ type
annex*: PLib # additional fields (seldom used, so we use a
# reference to another object to save space)
when hasFFI:
cname*: string # resolved C declaration name in importc decl, eg:
cname*: string # resolved C declaration name in importc decl, e.g.:
# proc fun() {.importc: "$1aux".} => cname = funaux
constraint*: PNode # additional constraints like 'lit|result'; also
# misused for the codegenDecl pragma in the hope
@@ -1027,6 +1026,7 @@ const
nkFloatLiterals* = {nkFloatLit..nkFloat128Lit}
nkLambdaKinds* = {nkLambda, nkDo}
declarativeDefs* = {nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef, nkConverterDef}
routineDefs* = declarativeDefs + {nkMacroDef, nkTemplateDef}
procDefs* = nkLambdaKinds + declarativeDefs
nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice}
@@ -1114,12 +1114,49 @@ proc newNode*(kind: TNodeKind): PNode =
writeStackTrace()
inc gNodeId
proc newNodeI*(kind: TNodeKind, info: TLineInfo): PNode =
result = PNode(kind: kind, info: info)
when defined(useNodeIds):
result.id = gNodeId
if result.id == nodeIdToDebug:
echo "KIND ", result.kind
writeStackTrace()
inc gNodeId
proc newNodeI*(kind: TNodeKind, info: TLineInfo, children: int): PNode =
result = PNode(kind: kind, info: info)
if children > 0:
newSeq(result.sons, children)
when defined(useNodeIds):
result.id = gNodeId
if result.id == nodeIdToDebug:
echo "KIND ", result.kind
writeStackTrace()
inc gNodeId
proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode =
result = newNode(kind)
result.info = info
result.typ = typ
proc newTree*(kind: TNodeKind; children: varargs[PNode]): PNode =
result = newNode(kind)
if children.len > 0:
result.info = children[0].info
result.sons = @children
proc newTreeI*(kind: TNodeKind; info: TLineInfo; children: varargs[PNode]): PNode =
result = newNodeI(kind, info)
if children.len > 0:
result.info = children[0].info
result.sons = @children
proc newTreeIT*(kind: TNodeKind; info: TLineInfo; typ: PType; children: varargs[PNode]): PNode =
result = newNodeIT(kind, info, typ)
if children.len > 0:
result.info = children[0].info
result.sons = @children
template previouslyInferred*(t: PType): PType =
if t.sons.len > 1: t.lastSon else: nil
@@ -1220,43 +1257,6 @@ proc newSymNode*(sym: PSym, info: TLineInfo): PNode =
result.typ = sym.typ
result.info = info
proc newNodeI*(kind: TNodeKind, info: TLineInfo): PNode =
result = PNode(kind: kind, info: info)
when defined(useNodeIds):
result.id = gNodeId
if result.id == nodeIdToDebug:
echo "KIND ", result.kind
writeStackTrace()
inc gNodeId
proc newNodeI*(kind: TNodeKind, info: TLineInfo, children: int): PNode =
result = PNode(kind: kind, info: info)
if children > 0:
newSeq(result.sons, children)
when defined(useNodeIds):
result.id = gNodeId
if result.id == nodeIdToDebug:
echo "KIND ", result.kind
writeStackTrace()
inc gNodeId
proc newNode*(kind: TNodeKind, info: TLineInfo, sons: TNodeSeq = @[],
typ: PType = nil): PNode =
# XXX use shallowCopy here for ownership transfer:
result = PNode(kind: kind, info: info, typ: typ)
result.sons = sons
when defined(useNodeIds):
result.id = gNodeId
if result.id == nodeIdToDebug:
echo "KIND ", result.kind
writeStackTrace()
inc gNodeId
proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode =
result = newNode(kind)
result.info = info
result.typ = typ
proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode =
result = newNode(kind)
result.intVal = intVal
@@ -1289,7 +1289,7 @@ proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode =
of tyUInt16: result = newNode(nkUInt16Lit)
of tyUInt32: result = newNode(nkUInt32Lit)
of tyUInt64: result = newNode(nkUInt64Lit)
of tyBool,tyEnum:
of tyBool, tyEnum:
# XXX: does this really need to be the kind nkIntLit?
result = newNode(nkIntLit)
of tyStatic: # that's a pre-existing bug, will fix in another PR
@@ -1353,9 +1353,9 @@ proc newType*(kind: TTypeKind, owner: PSym): PType =
writeStackTrace()
proc mergeLoc(a: var TLoc, b: TLoc) =
if a.k == low(a.k): a.k = b.k
if a.storage == low(a.storage): a.storage = b.storage
a.flags = a.flags + b.flags
if a.k == low(typeof(a.k)): a.k = b.k
if a.storage == low(typeof(a.storage)): a.storage = b.storage
a.flags.incl b.flags
if a.lode == nil: a.lode = b.lode
if a.r == nil: a.r = b.r
@@ -1380,7 +1380,7 @@ proc assignType*(dest, src: PType) =
# this fixes 'type TLock = TSysLock':
if src.sym != nil:
if dest.sym != nil:
dest.sym.flags = dest.sym.flags + (src.sym.flags-{sfExported})
dest.sym.flags.incl src.sym.flags-{sfExported}
if dest.sym.annex == nil: dest.sym.annex = src.sym.annex
mergeLoc(dest.sym.loc, src.sym.loc)
else:
@@ -1399,9 +1399,6 @@ proc copyType*(t: PType, owner: PSym, keepId: bool): PType =
proc exactReplica*(t: PType): PType = copyType(t, t.owner, true)
template requiresInit*(t: PType): bool =
t.flags * {tfRequiresInit, tfNotNil} != {}
proc copySym*(s: PSym): PSym =
result = newSym(s.kind, s.name, s.owner, s.info, s.options)
#result.ast = nil # BUGFIX; was: s.ast which made problems
@@ -1415,6 +1412,7 @@ proc copySym*(s: PSym): PSym =
result.position = s.position
result.loc = s.loc
result.annex = s.annex # BUGFIX
result.constraint = s.constraint
if result.kind in {skVar, skLet, skField}:
result.guard = s.guard
result.bitsize = s.bitsize
@@ -1487,8 +1485,7 @@ proc isGCedMem*(t: PType): bool {.inline.} =
t.kind == tyProc and t.callConv == ccClosure
proc propagateToOwner*(owner, elem: PType; propagateHasAsgn = true) =
const HaveTheirOwnEmpty = {tySequence, tyOpt, tySet, tyPtr, tyRef, tyProc}
owner.flags = owner.flags + (elem.flags * {tfHasMeta, tfTriggersCompileTime})
owner.flags.incl elem.flags * {tfHasMeta, tfTriggersCompileTime}
if tfNotNil in elem.flags:
if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvocation}:
owner.flags.incl tfNotNil
@@ -1500,7 +1497,7 @@ proc propagateToOwner*(owner, elem: PType; propagateHasAsgn = true) =
if mask != {} and propagateHasAsgn:
let o2 = owner.skipTypes({tyGenericInst, tyAlias, tySink})
if o2.kind in {tyTuple, tyObject, tyArray,
tySequence, tyOpt, tySet, tyDistinct, tyOpenArray, tyVarargs}:
tySequence, tySet, tyDistinct, tyOpenArray, tyVarargs}:
o2.flags.incl mask
owner.flags.incl mask
@@ -1750,7 +1747,7 @@ proc isRoutine*(s: PSym): bool {.inline.} =
proc isCompileTimeProc*(s: PSym): bool {.inline.} =
result = s.kind == skMacro or
s.kind == skProc and sfCompileTime in s.flags
s.kind in {skProc, skFunc} and sfCompileTime in s.flags
proc isRunnableExamples*(n: PNode): bool =
# Templates and generics don't perform symbol lookups.
@@ -1779,7 +1776,7 @@ proc isAtom*(n: PNode): bool {.inline.} =
result = n.kind >= nkNone and n.kind <= nkNilLit
proc isEmptyType*(t: PType): bool {.inline.} =
## 'void' and 'stmt' types are often equivalent to 'nil' these days:
## 'void' and 'typed' types are often equivalent to 'nil' these days:
result = t == nil or t.kind in {tyVoid, tyTyped}
proc makeStmtList*(n: PNode): PNode =
@@ -1797,17 +1794,18 @@ proc skipStmtList*(n: PNode): PNode =
else:
result = n
proc toVar*(typ: PType): PType =
proc toVar*(typ: PType; kind: TTypeKind): PType =
## If ``typ`` is not a tyVar then it is converted into a `var <typ>` and
## returned. Otherwise ``typ`` is simply returned as-is.
result = typ
if typ.kind != tyVar:
result = newType(tyVar, typ.owner)
if typ.kind != kind:
result = newType(kind, typ.owner)
rawAddSon(result, typ)
proc toRef*(typ: PType): PType =
## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and
## returned. Otherwise ``typ`` is simply returned as-is.
result = typ
if typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject:
result = newType(tyRef, typ.owner)
rawAddSon(result, typ)
@@ -1834,8 +1832,14 @@ proc isImportedException*(t: PType; conf: ConfigRef): bool =
proc isInfixAs*(n: PNode): bool =
return n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.s == "as"
proc skipColon*(n: PNode): PNode =
result = n
if n.kind == nkExprColonExpr:
result = n[1]
proc findUnresolvedStatic*(n: PNode): PNode =
if n.kind == nkSym and n.typ.kind == tyStatic and n.typ.n == nil:
# n.typ == nil: see issue #14802
if n.kind == nkSym and n.typ != nil and n.typ.kind == tyStatic and n.typ.n == nil:
return n
for son in n:
@@ -1852,6 +1856,10 @@ when false:
if n[i].containsNil: return true
template hasDestructor*(t: PType): bool = {tfHasAsgn, tfHasOwned} * t.flags != {}
proc hasDisabledAsgn*(t: PType): bool =
t.attachedOps[attachedAsgn] != nil and sfError in t.attachedOps[attachedAsgn].flags
template incompleteType*(t: PType): bool =
t.sym != nil and {sfForward, sfNoForward} * t.sym.flags == {sfForward}
@@ -1929,3 +1937,6 @@ proc toHumanStr*(kind: TSymKind): string =
proc toHumanStr*(kind: TTypeKind): string =
## strips leading `tk`
result = toHumanStrImpl(kind, 2)
proc skipAddr*(n: PNode): PNode {.inline.} =
(if n.kind == nkHiddenAddr: n[0] else: n)

View File

@@ -110,14 +110,14 @@ proc iiTablePut*(t: var TIITable, key, val: int)
# implementation
proc skipConvAndClosure*(n: PNode): PNode =
proc skipConvCastAndClosure*(n: PNode): PNode =
result = n
while true:
case result.kind
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64,
nkClosure:
result = result[0]
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast:
result = result[1]
else: break
@@ -345,7 +345,7 @@ proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int,
result.addf("$N$1\"n\": $2", [istr, treeToYamlAux(conf, n.n, marker, indent + 2, maxRecDepth - 1)])
if card(n.flags) > 0:
result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
result.addf("$N$1\"callconv\": $2", [istr, makeYamlString(CallingConvToStr[n.callConv])])
result.addf("$N$1\"callconv\": $2", [istr, makeYamlString($n.callConv)])
result.addf("$N$1\"size\": $2", [istr, rope(n.size)])
result.addf("$N$1\"align\": $2", [istr, rope(n.align)])
result.addf("$N$1\"sons\": $2", [istr, sonsRope])
@@ -591,10 +591,17 @@ proc value(this: var DebugPrinter; value: PNode) =
if this.conf != nil:
this.key "info"
this.value $lineInfoToStr(this.conf, value.info)
if card(value.flags) > 0:
if value.flags != {}:
this.key "flags"
this.value value.flags
if value.typ != nil:
this.key "typ"
this.value value.typ.kind
else:
this.key "typ"
this.value "nil"
case value.kind
of nkCharLit..nkUInt64Lit:
this.key "intVal"

View File

@@ -16,7 +16,7 @@ const
Mhalf = M div 2
type
Node[Key, Val] = ref object
Node[Key, Val] {.acyclic.} = ref object
entries: int
keys: array[M, Key]
case isInternal: bool
@@ -79,6 +79,9 @@ proc insert[Key, Val](h: Node[Key, Val], key: Key, val: Val): Node[Key, Val] =
var j = 0
if not h.isInternal:
while j < h.entries:
if eq(key, h.keys[j]):
h.vals[j] = val
return
if less(key, h.keys[j]): break
inc j
for i in countdown(h.entries, j+1):
@@ -132,8 +135,7 @@ proc `$`[Key, Val](b: BTree[Key, Val]): string =
result = ""
toString(b.root, "", result)
proc hasNext*[Key, Val](b: BTree[Key, Val]; index: int): bool =
result = index < b.entries
proc hasNext*[Key, Val](b: BTree[Key, Val]; index: int): bool = index < b.entries
proc countSubTree[Key, Val](it: Node[Key, Val]): int =
if it.isInternal:
@@ -166,68 +168,3 @@ iterator pairs*[Key, Val](b: BTree[Key, Val]): (Key, Val) =
yield (k, v)
proc len*[Key, Val](b: BTree[Key, Val]): int {.inline.} = b.entries
when isMainModule:
import random, tables
proc main =
var st = initBTree[string, string]()
st.add("www.cs.princeton.edu", "abc")
st.add("www.princeton.edu", "128.112.128.15")
st.add("www.yale.edu", "130.132.143.21")
st.add("www.simpsons.com", "209.052.165.60")
st.add("www.apple.com", "17.112.152.32")
st.add("www.amazon.com", "207.171.182.16")
st.add("www.ebay.com", "66.135.192.87")
st.add("www.cnn.com", "64.236.16.20")
st.add("www.google.com", "216.239.41.99")
st.add("www.nytimes.com", "199.239.136.200")
st.add("www.microsoft.com", "207.126.99.140")
st.add("www.dell.com", "143.166.224.230")
st.add("www.slashdot.org", "66.35.250.151")
st.add("www.espn.com", "199.181.135.201")
st.add("www.weather.com", "63.111.66.11")
st.add("www.yahoo.com", "216.109.118.65")
assert st.getOrDefault("www.cs.princeton.edu") == "abc"
assert st.getOrDefault("www.harvardsucks.com") == ""
assert st.getOrDefault("www.simpsons.com") == "209.052.165.60"
assert st.getOrDefault("www.apple.com") == "17.112.152.32"
assert st.getOrDefault("www.ebay.com") == "66.135.192.87"
assert st.getOrDefault("www.dell.com") == "143.166.224.230"
assert(st.entries == 16)
for k, v in st:
echo k, ": ", v
when false:
var b2 = initBTree[string, string]()
const iters = 10_000
for i in 1..iters:
b2.add($i, $(iters - i))
for i in 1..iters:
let x = b2.getOrDefault($i)
if x != $(iters - i):
echo "got ", x, ", but expected ", iters - i
echo b2.entries
when true:
var b2 = initBTree[int, string]()
var t2 = initTable[int, string]()
const iters = 100_000
for i in 1..iters:
let x = rand(high(int))
if not t2.hasKey(x):
doAssert b2.getOrDefault(x).len == 0, " what, tree has this element " & $x
t2[x] = $x
b2.add(x, $x)
doAssert b2.entries == t2.len
echo "unique entries ", b2.entries
for k, v in t2:
doAssert $k == v
doAssert b2.getOrDefault(k) == $k
main()

View File

@@ -141,9 +141,61 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
proc genBoundsCheck(p: BProc; arr, a, b: TLoc)
proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
var a: TLoc
proc reifiedOpenArray(n: PNode): bool {.inline.} =
var x = n
while x.kind in {nkAddr, nkHiddenAddr, nkHiddenStdConv, nkHiddenDeref}:
x = x[0]
if x.kind == nkSym and x.sym.kind == skParam:
result = false
else:
result = true
proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope, Rope) =
var a, b, c: TLoc
initLocExpr(p, q[1], a)
initLocExpr(p, q[2], b)
initLocExpr(p, q[3], c)
# but first produce the required index checks:
if optBoundsCheck in p.options:
genBoundsCheck(p, a, b, c)
let ty = skipTypes(a.t, abstractVar+{tyPtr})
let dest = getTypeDesc(p.module, destType)
let lengthExpr = "($1)-($2)+1" % [rdLoc(c), rdLoc(b)]
case ty.kind
of tyArray:
let first = toInt64(firstOrd(p.config, ty))
if first == 0:
result = ("($3*)(($1)+($2))" % [rdLoc(a), rdLoc(b), dest],
lengthExpr)
else:
result = ("($4*)($1)+(($2)-($3))" %
[rdLoc(a), rdLoc(b), intLiteral(first), dest],
lengthExpr)
of tyOpenArray, tyVarargs:
if reifiedOpenArray(q[1]):
result = ("($3*)($1.Field0)+($2)" % [rdLoc(a), rdLoc(b), dest],
lengthExpr)
else:
result = ("($3*)($1)+($2)" % [rdLoc(a), rdLoc(b), dest],
lengthExpr)
of tyUncheckedArray, tyCString:
result = ("($3*)($1)+($2)" % [rdLoc(a), rdLoc(b), dest],
lengthExpr)
of tyString, tySequence:
let atyp = skipTypes(a.t, abstractInst)
if formalType.skipTypes(abstractInst).kind in {tyVar} and atyp.kind == tyString and
optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
if atyp.kind in {tyVar} and not compileToCpp(p.module):
result = ("($4*)(*$1)$3+($2)" % [rdLoc(a), rdLoc(b), dataField(p), dest],
lengthExpr)
else:
result = ("($4*)$1$3+($2)" % [rdLoc(a), rdLoc(b), dataField(p), dest],
lengthExpr)
else:
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
var q = skipConv(n)
var skipped = false
while q.kind == nkStmtListExpr and q.len > 0:
@@ -157,47 +209,26 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
for i in 0..<q.len-1:
genStmts(p, q[i])
q = q.lastSon
var b, c: TLoc
initLocExpr(p, q[1], a)
initLocExpr(p, q[2], b)
initLocExpr(p, q[3], c)
# but first produce the required index checks:
if optBoundsCheck in p.options:
genBoundsCheck(p, a, b, c)
let ty = skipTypes(a.t, abstractVar+{tyPtr})
let dest = getTypeDesc(p.module, n.typ[0])
case ty.kind
of tyArray:
let first = toInt64(firstOrd(p.config, ty))
if first == 0:
result = "($4*)(($1)+($2)), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
else:
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:
let atyp = skipTypes(a.t, abstractInst)
if formalType.skipTypes(abstractInst).kind == tyVar and atyp.kind == tyString and
optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
if atyp.kind == tyVar and not compileToCpp(p.module):
result = "($5*)(*$1)$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p), dest]
else:
result = "($5*)$1$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p), dest]
else:
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
let (x, y) = genOpenArraySlice(p, q, formalType, n.typ[0])
result = x & ", " & y
else:
initLocExpr(p, n, a)
var a: TLoc
initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n, a)
case skipTypes(a.t, abstractVar+{tyStatic}).kind
of tyOpenArray, tyVarargs:
result = "$1, $1Len_0" % [rdLoc(a)]
if reifiedOpenArray(n):
if a.t.kind in {tyVar, tyLent}:
result = "$1->Field0, $1->Field1" % [rdLoc(a)]
else:
result = "$1.Field0, $1.Field1" % [rdLoc(a)]
else:
result = "$1, $1Len_0" % [rdLoc(a)]
of tyString, tySequence:
let ntyp = skipTypes(n.typ, abstractInst)
if formalType.skipTypes(abstractInst).kind == tyVar and ntyp.kind == tyString and
if formalType.skipTypes(abstractInst).kind in {tyVar} and ntyp.kind == tyString and
optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
if ntyp.kind == tyVar and not compileToCpp(p.module):
if ntyp.kind in {tyVar} and not compileToCpp(p.module):
var t: TLoc
t.r = "(*$1)" % [a.rdLoc]
result = "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
@@ -217,22 +248,33 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
else: internalError(p.config, "openArrayLoc: " & typeToString(a.t))
proc genArgStringToCString(p: BProc, n: PNode): Rope {.inline.} =
proc withTmpIfNeeded(p: BProc, a: TLoc, needsTmp: bool): TLoc =
# Bug https://github.com/status-im/nimbus-eth2/issues/1549
# Aliasing is preferred over stack overflows.
# Also don't regress for non ARC-builds, too risky.
if needsTmp and a.lode.typ != nil and p.config.selectedGC in {gcArc, gcOrc} and
getSize(p.config, a.lode.typ) < 1024:
getTemp(p, a.lode.typ, result, needsInit=false)
genAssignment(p, result, a, {})
else:
result = a
proc genArgStringToCString(p: BProc, n: PNode, needsTmp: bool): Rope {.inline.} =
var a: TLoc
initLocExpr(p, n[0], a)
result = ropecg(p.module, "#nimToCStringConv($1)", [a.rdLoc])
ropecg(p.module, "#nimToCStringConv($1)", [withTmpIfNeeded(p, a, needsTmp).rdLoc])
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope =
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode, needsTmp = false): Rope =
var a: TLoc
if n.kind == nkStringToCString:
result = genArgStringToCString(p, n)
result = genArgStringToCString(p, n, needsTmp)
elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
var n = if n.kind != nkHiddenAddr: n else: n[0]
result = openArrayLoc(p, param.typ, n)
elif ccgIntroducedPtr(p.config, param, call[0].typ[0]):
initLocExpr(p, n, a)
result = addrLoc(p.config, a)
elif p.module.compileToCpp and param.typ.kind == tyVar and
result = addrLoc(p.config, withTmpIfNeeded(p, a, needsTmp))
elif p.module.compileToCpp and param.typ.kind in {tyVar} and
n.kind == nkHiddenAddr:
initLocExprSingleUse(p, n[0], a)
# if the proc is 'importc'ed but not 'importcpp'ed then 'var T' still
@@ -246,26 +288,85 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope =
result = rdLoc(a)
else:
initLocExprSingleUse(p, n, a)
result = rdLoc(a)
result = rdLoc(withTmpIfNeeded(p, a, needsTmp))
proc genArgNoParam(p: BProc, n: PNode): Rope =
proc genArgNoParam(p: BProc, n: PNode, needsTmp = false): Rope =
var a: TLoc
if n.kind == nkStringToCString:
result = genArgStringToCString(p, n)
result = genArgStringToCString(p, n, needsTmp)
else:
initLocExprSingleUse(p, n, a)
result = rdLoc(a)
result = rdLoc(withTmpIfNeeded(p, a, needsTmp))
template genParamLoop(params) {.dirty.} =
if i < typ.len:
assert(typ.n[i].kind == nkSym)
let paramType = typ.n[i]
if not paramType.typ.isCompileTimeOnly:
if params != nil: params.add(~", ")
params.add(genArg(p, ri[i], paramType.sym, ri))
from dfa import instrTargets, InstrTargetKind
proc potentialAlias(n: PNode, potentialWrites: seq[PNode]): bool =
for p in potentialWrites:
if instrTargets(p, n) != None:
return true
proc skipTrivialIndirections(n: PNode): PNode =
result = n
while true:
case result.kind
of {nkDerefExpr, nkHiddenDeref, nkAddr, nkHiddenAddr, nkObjDownConv, nkObjUpConv}:
result = result[0]
of {nkHiddenStdConv, nkHiddenSubConv}:
result = result[1]
else: break
proc getPotentialWrites(n: PNode, mutate = false): seq[PNode] =
case n.kind:
of nkLiterals, nkIdent: discard
of nkSym:
if mutate: result.add n
of nkAsgn, nkFastAsgn:
result.add getPotentialWrites(n[0], true)
result.add getPotentialWrites(n[1], mutate)
of nkAddr, nkHiddenAddr:
result.add getPotentialWrites(n[0], true)
of nkCallKinds: #TODO: Find out why in f += 1, f is a nkSym and not a nkHiddenAddr
for s in n.sons:
result.add getPotentialWrites(s, true)
else:
if params != nil: params.add(~", ")
params.add(genArgNoParam(p, ri[i]))
for s in n.sons:
result.add getPotentialWrites(s, mutate)
proc getPotentialReads(n: PNode): seq[PNode] =
case n.kind:
of nkLiterals, nkIdent: discard
of nkSym: result.add n
else:
for s in n.sons:
result.add getPotentialReads(s)
proc genParams(p: BProc, ri: PNode, typ: PType): Rope =
# We must generate temporaries in cases like #14396
# to keep the strict Left-To-Right evaluation
var needTmp = newSeq[bool](ri.len - 1)
var potentialWrites: seq[PNode]
for i in countdown(ri.len - 1, 1):
if ri[i].skipTrivialIndirections.kind == nkSym:
needTmp[i - 1] = potentialAlias(ri[i], potentialWrites)
else:
for n in getPotentialReads(ri[i]):
if not needTmp[i - 1]:
needTmp[i - 1] = potentialAlias(n, potentialWrites)
potentialWrites.add getPotentialWrites(ri[i])
if ri[i].kind == nkHiddenAddr:
# Optimization: don't use a temp, if we would only take the adress anyway
needTmp[i - 1] = false
for i in 1..<ri.len:
if i < typ.len:
assert(typ.n[i].kind == nkSym)
let paramType = typ.n[i]
if not paramType.typ.isCompileTimeOnly:
if result != nil: result.add(~", ")
result.add(genArg(p, ri[i], paramType.sym, ri, needTmp[i-1]))
else:
if result != nil: result.add(~", ")
result.add(genArgNoParam(p, ri[i], needTmp[i-1]))
proc addActualSuffixForHCR(res: var Rope, module: PSym, sym: PSym) =
if sym.flags * {sfImportc, sfNonReloadable} == {} and sym.loc.k == locProc and
@@ -276,13 +377,13 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var op: TLoc
# this is a hotspot in the compiler
initLocExpr(p, ri[0], op)
var params: Rope
# getUniqueType() is too expensive here:
var typ = skipTypes(ri[0].typ, abstractInstOwned)
assert(typ.kind == tyProc)
assert(typ.len == typ.n.len)
for i in 1..<ri.len:
genParamLoop(params)
var params = genParams(p, ri, typ)
var callee = rdLoc(op)
if p.hcrOn and ri[0].kind == nkSym:
callee.addActualSuffixForHCR(p.module.module, ri[0].sym)
@@ -290,23 +391,21 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
proc getRawProcType(p: BProc, t: PType): Rope =
result = getClosureType(p.module, t, clHalf)
proc addComma(r: Rope): Rope =
result = if r == nil: r else: r & ~", "
if r == nil: r else: r & ~", "
const PatProc = "$1.ClE_0? $1.ClP_0($3$1.ClE_0):(($4)($1.ClP_0))($2)"
const PatIter = "$1.ClP_0($3$1.ClE_0)" # we know the env exists
var op: TLoc
initLocExpr(p, ri[0], op)
var pl: Rope
var typ = skipTypes(ri[0].typ, abstractInst)
# getUniqueType() is too expensive here:
var typ = skipTypes(ri[0].typ, abstractInstOwned)
assert(typ.kind == tyProc)
for i in 1..<ri.len:
assert(typ.len == typ.n.len)
genParamLoop(pl)
assert(typ.len == typ.n.len)
var pl = genParams(p, ri, typ)
template genCallPattern {.dirty.} =
if tfIterator in typ.flags:
@@ -314,7 +413,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
else:
lineF(p, cpsStmts, PatProc & ";$n", [rdLoc(op), pl, pl.addComma, rawProc])
let rawProc = getRawProcType(p, typ)
let rawProc = getClosureType(p.module, typ, clHalf)
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
if typ[0] != nil:
if isInvalidReturnType(p.config, typ[0]):
@@ -372,7 +471,7 @@ proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
assert(paramType.kind == nkSym)
if paramType.typ.isCompileTimeOnly:
result = nil
elif typ[i].kind == tyVar and ri[i].kind == nkHiddenAddr:
elif typ[i].kind in {tyVar} and ri[i].kind == nkHiddenAddr:
result = genArgNoParam(p, ri[i][0])
else:
result = genArgNoParam(p, ri[i]) #, typ.n[i].sym)
@@ -449,7 +548,7 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
var ri = ri[i]
while ri.kind == nkObjDownConv: ri = ri[0]
let t = typ[i].skipTypes({tyGenericInst, tyAlias, tySink})
if t.kind == tyVar:
if t.kind in {tyVar}:
let x = if ri.kind == nkHiddenAddr: ri[0] else: ri
if x.typ.kind == tyPtr:
result = genArgNoParam(p, x)
@@ -644,18 +743,33 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
pl.add(~"];$n")
line(p, cpsStmts, pl)
proc genCall(p: BProc, e: PNode, d: var TLoc) =
if e[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
genClosureCall(p, nil, e, d)
elif e[0].kind == nkSym and sfInfixCall in e[0].sym.flags:
genInfixCall(p, nil, e, d)
elif e[0].kind == nkSym and sfNamedParamCall in e[0].sym.flags:
genNamedParamCall(p, e, d)
else:
genPrefixCall(p, nil, e, d)
postStmtActions(p)
proc notYetAlive(n: PNode): bool {.inline.} =
let r = getRoot(n)
result = r != nil and r.loc.lode == nil
proc isInactiveDestructorCall(p: BProc, e: PNode): bool =
#[ Consider this example.
var :tmpD_3281815
try:
if true:
return
let args_3280013 =
wasMoved_3281816(:tmpD_3281815)
`=_3280036`(:tmpD_3281815, [1])
:tmpD_3281815
finally:
`=destroy_3280027`(args_3280013)
We want to return early but the 'finally' section is traversed before
the 'let args = ...' statement. We exploit this to generate better
code for 'return'. ]#
result = e.len == 2 and e[0].kind == nkSym and
e[0].sym.name.s == "=destroy" and notYetAlive(e[1].skipAddr)
proc genAsgnCall(p: BProc, le, ri: PNode, d: var TLoc) =
if p.withinBlockLeaveActions > 0 and isInactiveDestructorCall(p, ri):
return
if ri[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
genClosureCall(p, le, ri, d)
elif ri[0].kind == nkSym and sfInfixCall in ri[0].sym.flags:
@@ -665,3 +779,5 @@ proc genAsgnCall(p: BProc, le, ri: PNode, d: var TLoc) =
else:
genPrefixCall(p, le, ri, d)
postStmtActions(p)
proc genCall(p: BProc, e: PNode, d: var TLoc) = genAsgnCall(p, nil, e, d)

View File

@@ -71,8 +71,10 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
p.module.s[cfsData].addf(
"static NIM_CONST $1 $2 = {NIM_NIL,NIM_NIL};$n",
[getTypeDesc(p.module, ty), result])
else:
elif k in {tyPointer, tyNil, tyProc}:
result = rope("NIM_NIL")
else:
result = "(($1) NIM_NIL)" % [getTypeDesc(p.module, ty)]
of nkStrLit..nkTripleStrLit:
let k = if ty == nil: tyString
else: skipTypes(ty, abstractVarRange + {tyStatic, tyUserTypeClass, tyUserTypeClassInst}).kind
@@ -126,9 +128,8 @@ proc genRawSetData(cs: TBitSet, size: int): Rope =
result = intLiteral(cast[BiggestInt](bitSetToWord(cs, size)))
proc genSetNode(p: BProc, n: PNode): Rope =
var cs: TBitSet
var size = int(getSize(p.config, n.typ))
toBitSet(p.config, n, cs)
let cs = toBitSet(p.config, n)
if size > 8:
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
result = p.module.tmpBase & rope(id)
@@ -141,6 +142,7 @@ proc genSetNode(p: BProc, n: PNode): Rope =
result = genRawSetData(cs, size)
proc getStorageLoc(n: PNode): TStorageLoc =
## deadcode
case n.kind
of nkSym:
case n.sym.kind
@@ -266,10 +268,38 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
[addrLoc(p.config, dest), addrLoc(p.config, src), rdLoc(dest)])
else:
linefmt(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfo(p.module, dest.t, dest.lode.info)])
[addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfoV1(p.module, dest.t, dest.lode.info)])
else:
linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfo(p.module, dest.t, dest.lode.info)])
[addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfoV1(p.module, dest.t, dest.lode.info)])
proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc) =
assert d.k != locNone
# getTemp(p, d.t, d)
case a.t.skipTypes(abstractVar).kind
of tyOpenArray, tyVarargs:
if reifiedOpenArray(a.lode):
linefmt(p, cpsStmts, "$1.Field0 = $2.Field0; $1.Field1 = $2.Field1;$n",
[rdLoc(d), a.rdLoc])
else:
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $2Len_0;$n",
[rdLoc(d), a.rdLoc])
of tySequence:
linefmt(p, cpsStmts, "$1.Field0 = $2$3; $1.Field1 = $4;$n",
[rdLoc(d), a.rdLoc, dataField(p), lenExpr(p, a)])
of tyArray:
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $3;$n",
[rdLoc(d), rdLoc(a), rope(lengthOrd(p.config, a.t))])
of tyString:
let etyp = skipTypes(a.t, abstractInst)
if etyp.kind in {tyVar} and optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
linefmt(p, cpsStmts, "$1.Field0 = $2$3; $1.Field1 = $4;$n",
[rdLoc(d), a.rdLoc, dataField(p), lenExpr(p, a)])
else:
internalError(p.config, a.lode.info, "cannot handle " & $a.t.kind)
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# This function replaces all other methods for generating
@@ -290,7 +320,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
else:
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
[addrLoc(p.config, dest), rdLoc(src),
genTypeInfo(p.module, dest.t, dest.lode.info)])
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
of tyString:
if optSeqDestructors in p.config.globalOptions:
genGenericAsgn(p, dest, src, flags)
@@ -349,11 +379,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
of tyOpenArray, tyVarargs:
# open arrays are always on the stack - really? What if a sequence is
# passed to an open array?
if containsGarbageCollectedRef(dest.t):
if reifiedOpenArray(dest.lode):
genOpenArrayConv(p, dest, src)
elif containsGarbageCollectedRef(dest.t):
linefmt(p, cpsStmts, # XXX: is this correct for arrays?
"#genericAssignOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
[addrLoc(p.config, dest), addrLoc(p.config, src),
genTypeInfo(p.module, dest.t, dest.lode.info)])
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
else:
linefmt(p, cpsStmts,
# bug #4799, keep the nimCopyMem for a while
@@ -361,7 +393,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
"$1 = $2;$n",
[rdLoc(dest), rdLoc(src)])
of tySet:
if mapType(p.config, ty) == ctArray:
if mapSetType(p.config, ty) == ctArray:
linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);$n",
[rdLoc(dest), rdLoc(src), getSize(p.config, dest.t)])
else:
@@ -395,18 +427,23 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) =
# XXX optimize this
linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
[addrLoc(p.config, dest), addrLocOrTemp(src),
genTypeInfo(p.module, dest.t, dest.lode.info)])
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
of tySequence, tyString:
linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n",
[addrLoc(p.config, dest), rdLoc(src),
genTypeInfo(p.module, dest.t, dest.lode.info)])
if optTinyRtti in p.config.globalOptions:
linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
[addrLoc(p.config, dest), addrLocOrTemp(src),
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
else:
linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n",
[addrLoc(p.config, dest), rdLoc(src),
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
of tyOpenArray, tyVarargs:
linefmt(p, cpsStmts,
"#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
[addrLoc(p.config, dest), addrLocOrTemp(src),
genTypeInfo(p.module, dest.t, dest.lode.info)])
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
of tySet:
if mapType(p.config, ty) == ctArray:
if mapSetType(p.config, ty) == ctArray:
linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);$n",
[rdLoc(dest), rdLoc(src), getSize(p.config, dest.t)])
else:
@@ -675,11 +712,11 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
proc isCppRef(p: BProc; typ: PType): bool {.inline.} =
result = p.module.compileToCpp and
skipTypes(typ, abstractInstOwned).kind == tyVar and
skipTypes(typ, abstractInstOwned).kind in {tyVar} and
tfVarIsPtr notin skipTypes(typ, abstractInstOwned).flags
proc genDeref(p: BProc, e: PNode, d: var TLoc) =
let mt = mapType(p.config, e[0].typ)
let mt = mapType(p.config, e[0].typ, mapTypeChooser(e[0]))
if mt in {ctArray, ctPtrToArray} and lfEnforceDeref notin d.flags:
# XXX the amount of hacks for C's arrays is incredible, maybe we should
# simply wrap them in a struct? --> Losing auto vectorization then?
@@ -692,7 +729,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) =
if typ.kind in {tyUserTypeClass, tyUserTypeClassInst} and typ.isResolvedUserTypeClass:
typ = typ.lastSon
typ = typ.skipTypes(abstractInstOwned)
if typ.kind == tyVar and tfVarIsPtr notin typ.flags and p.module.compileToCpp and e[0].kind == nkHiddenAddr:
if typ.kind in {tyVar} and tfVarIsPtr notin typ.flags and p.module.compileToCpp and e[0].kind == nkHiddenAddr:
initLocExprSingleUse(p, e[0][0], d)
return
else:
@@ -715,7 +752,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) =
else:
internalError(p.config, e.info, "genDeref " & $typ.kind)
elif p.module.compileToCpp:
if typ.kind == tyVar and tfVarIsPtr notin typ.flags and
if typ.kind in {tyVar} and tfVarIsPtr notin typ.flags and
e.kind == nkHiddenDeref:
putIntoDest(p, d, e, rdLoc(a), a.storage)
return
@@ -725,10 +762,21 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) =
# See tmissingderef. So we get rid of the deref instead. The codegen
# ends up using 'memcpy' for the array assignment,
# so the '&' and '*' cancel out:
putIntoDest(p, d, lodeTyp(a.t[0]), rdLoc(a), a.storage)
putIntoDest(p, d, e, rdLoc(a), a.storage)
else:
putIntoDest(p, d, e, "(*$1)" % [rdLoc(a)], a.storage)
proc cowBracket(p: BProc; n: PNode) =
if n.kind == nkBracketExpr and optSeqDestructors in p.config.globalOptions:
let strCandidate = n[0]
if strCandidate.typ.skipTypes(abstractInst).kind == tyString:
var a: TLoc
initLocExpr(p, strCandidate, a)
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
proc cow(p: BProc; n: PNode) {.inline.} =
if n.kind == nkHiddenAddr: cowBracket(p, n[0])
proc genAddr(p: BProc, e: PNode, d: var TLoc) =
# careful 'addr(myptrToArray)' needs to get the ampersand:
if e[0].typ.skipTypes(abstractInstOwned).kind in {tyRef, tyPtr}:
@@ -736,7 +784,7 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e[0], a)
putIntoDest(p, d, e, "&" & a.r, a.storage)
#Message(e.info, warnUser, "HERE NEW &")
elif mapType(p.config, e[0].typ) == ctArray or isCppRef(p, e.typ):
elif mapType(p.config, e[0].typ, mapTypeChooser(e[0])) == ctArray or isCppRef(p, e.typ):
expr(p, e[0], d)
else:
var a: TLoc
@@ -821,7 +869,7 @@ 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 msg = genFieldError(field, disc.sym)
let msg = genFieldDefect(field, disc.sym)
let strLit = genStringLiteral(p.module, newStrNode(nkStrLit, msg))
if op.magic == mNot:
linefmt(p, cpsStmts,
@@ -895,10 +943,16 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc) =
let ty = skipTypes(arr.t, abstractVarRange)
case ty.kind
of tyOpenArray, tyVarargs:
linefmt(p, cpsStmts,
"if ($2-$1 != -1 && " &
"((NU)($1) >= (NU)($3Len_0) || (NU)($2) >= (NU)($3Len_0))){ #raiseIndexError(); $4}$n",
[rdLoc(a), rdLoc(b), rdLoc(arr), raiseInstr(p)])
if reifiedOpenArray(arr.lode):
linefmt(p, cpsStmts,
"if ($2-$1 != -1 && " &
"((NU)($1) >= (NU)($3.Field1) || (NU)($2) >= (NU)($3.Field1))){ #raiseIndexError(); $4}$n",
[rdLoc(a), rdLoc(b), rdLoc(arr), raiseInstr(p)])
else:
linefmt(p, cpsStmts,
"if ($2-$1 != -1 && " &
"((NU)($1) >= (NU)($3Len_0) || (NU)($2) >= (NU)($3Len_0))){ #raiseIndexError(); $4}$n",
[rdLoc(a), rdLoc(b), rdLoc(arr), raiseInstr(p)])
of tyArray:
let first = intLiteral(firstOrd(p.config, ty))
linefmt(p, cpsStmts,
@@ -915,13 +969,22 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc) =
proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
var a, b: TLoc
initLocExpr(p, x, a)
initLocExpr(p, y, b) # emit range check:
if optBoundsCheck in p.options:
linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)){ #raiseIndexError2($1,$2Len_0-1); $3}$n",
[rdLoc(b), rdLoc(a), raiseInstr(p)]) # BUGFIX: ``>=`` and not ``>``!
inheritLocation(d, a)
putIntoDest(p, d, n,
ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
initLocExpr(p, y, b)
if not reifiedOpenArray(x):
# emit range check:
if optBoundsCheck in p.options:
linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)){ #raiseIndexError2($1,$2Len_0-1); $3}$n",
[rdLoc(b), rdLoc(a), raiseInstr(p)]) # BUGFIX: ``>=`` and not ``>``!
inheritLocation(d, a)
putIntoDest(p, d, n,
ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
else:
if optBoundsCheck in p.options:
linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2.Field1)){ #raiseIndexError2($1,$2.Field1-1); $3}$n",
[rdLoc(b), rdLoc(a), raiseInstr(p)]) # BUGFIX: ``>=`` and not ``>``!
inheritLocation(d, a)
putIntoDest(p, d, n,
ropecg(p.module, "$1.Field0[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
var a, b: TLoc
@@ -931,7 +994,7 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
if ty.kind in {tyRef, tyPtr}:
ty = skipTypes(ty.lastSon, abstractVarRange) # emit range check:
if optBoundsCheck in p.options:
if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options):
if ty.kind == tyString and not defined(nimNoZeroTerminator):
linefmt(p, cpsStmts,
"if ((NU)($1) > (NU)$2){ #raiseIndexError2($1,$2); $3}$n",
[rdLoc(b), lenExpr(p, a), raiseInstr(p)])
@@ -1174,12 +1237,12 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
const seqAppendPattern = "($2) #incrSeqV3((TGenericSeq*)($1), $3)"
call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a),
getTypeDesc(p.module, e[1].typ),
genTypeInfo(p.module, seqType, e.info)])
genTypeInfoV1(p.module, seqType, e.info)])
else:
const seqAppendPattern = "($2) #incrSeqV3($1, $3)"
call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a),
getTypeDesc(p.module, e[1].typ),
genTypeInfo(p.module, seqType, e.info)])
genTypeInfoV1(p.module, seqType, e.info)])
# emit the write barrier if required, but we can always move here, so
# use 'genRefAssign' for the seq.
genRefAssign(p, a, call)
@@ -1199,7 +1262,7 @@ proc genReset(p: BProc, n: PNode) =
when false:
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
[addrLoc(p.config, a),
genTypeInfo(p.module, skipTypes(a.t, {tyVar}), n.info)])
genTypeInfoV1(p.module, skipTypes(a.t, {tyVar}), n.info)])
proc genDefault(p: BProc; n: PNode; d: var TLoc) =
if d.k == locNone: getTemp(p, n.typ, d, needsInit=true)
@@ -1218,19 +1281,19 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
if optTinyRtti in p.config.globalOptions:
if needsInit:
b.r = ropecg(p.module, "($1) #nimNewObj($2)",
[getTypeDesc(p.module, typ), sizeExpr])
b.r = ropecg(p.module, "($1) #nimNewObj($2, NIM_ALIGNOF($3))",
[getTypeDesc(p.module, typ), sizeExpr, getTypeDesc(p.module, bt)])
else:
b.r = ropecg(p.module, "($1) #nimNewObjUninit($2)",
[getTypeDesc(p.module, typ), sizeExpr])
b.r = ropecg(p.module, "($1) #nimNewObjUninit($2, NIM_ALIGNOF($3))",
[getTypeDesc(p.module, typ), sizeExpr, getTypeDesc(p.module, bt)])
genAssignment(p, a, b, {})
else:
let ti = genTypeInfo(p.module, typ, a.lode.info)
let ti = genTypeInfoV1(p.module, typ, a.lode.info)
if bt.destructor != nil and not isTrivialProc(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:
if bt.destructor.typ == nil or bt.destructor.typ.callConv != ccDefault:
if bt.destructor.typ == nil or bt.destructor.typ.callConv != ccNimCall:
localError(p.module.config, a.lode.info,
"the destructor that is turned into a finalizer needs " &
"to have the 'nimcall' calling convention")
@@ -1284,18 +1347,18 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
if p.config.selectedGC == gcGo:
# we need the write barrier
call.r = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype),
genTypeInfo(p.module, seqtype, dest.lode.info), length])
genTypeInfoV1(p.module, seqtype, dest.lode.info), length])
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", [addrLoc(p.config, dest), call.rdLoc])
else:
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", [getTypeDesc(p.module, seqtype),
genTypeInfo(p.module, seqtype, dest.lode.info), length])
genTypeInfoV1(p.module, seqtype, dest.lode.info), length])
linefmt(p, cpsStmts, "$1 = $2;$n", [dest.rdLoc, call.rdLoc])
else:
if lenIsZero:
call.r = rope"NIM_NIL"
else:
call.r = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype),
genTypeInfo(p.module, seqtype, dest.lode.info), length])
genTypeInfoV1(p.module, seqtype, dest.lode.info), length])
genAssignment(p, dest, call, {})
proc genNewSeq(p: BProc, e: PNode) =
@@ -1304,9 +1367,10 @@ proc genNewSeq(p: BProc, e: PNode) =
initLocExpr(p, e[2], b)
if optSeqDestructors in p.config.globalOptions:
let seqtype = skipTypes(e[1].typ, abstractVarRange)
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
[a.rdLoc, b.rdLoc, getTypeDesc(p.module, seqtype.lastSon),
getSeqPayloadType(p.module, seqtype)])
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
[a.rdLoc, b.rdLoc,
getTypeDesc(p.module, seqtype.lastSon),
getSeqPayloadType(p.module, seqtype)])
else:
let lenIsZero = optNilSeqs notin p.options and
e[2].kind == nkIntLit and e[2].intVal == 0
@@ -1319,14 +1383,15 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
initLocExpr(p, e[1], a)
if optSeqDestructors in p.config.globalOptions:
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",
linefmt(p, cpsStmts, "$1.len = 0; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
[d.rdLoc, a.rdLoc, getTypeDesc(p.module, seqtype.lastSon),
getSeqPayloadType(p.module, seqtype)])
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]))
genTypeInfoV1(p.module, seqtype, e.info), a.rdLoc]))
gcUsage(p.config, e)
proc rawConstExpr(p: BProc, n: PNode; d: var TLoc) =
@@ -1338,7 +1403,7 @@ proc rawConstExpr(p: BProc, n: PNode; d: var TLoc) =
# expression not found in the cache:
inc(p.module.labels)
p.module.s[cfsData].addf("static NIM_CONST $1 $2 = $3;$n",
[getTypeDesc(p.module, t), d.r, genBracedInit(p, n, isConst = true)])
[getTypeDesc(p.module, t), d.r, genBracedInit(p, n, isConst = true, t)])
proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr:
@@ -1348,7 +1413,7 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
result = false
proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
#echo rendertree e, " ", e.isDeepConstExpr
#echo renderTree e, " ", e.isDeepConstExpr
# inheritance in C++ does not allow struct initialization so
# we skip this step here:
if not p.module.compileToCpp and optSeqDestructors notin p.config.globalOptions:
@@ -1428,7 +1493,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
let l = intLiteral(n.len)
if optSeqDestructors in p.config.globalOptions:
let seqtype = n.typ
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
[rdLoc dest[], l, getTypeDesc(p.module, seqtype.lastSon),
getSeqPayloadType(p.module, seqtype)])
else:
@@ -1459,7 +1524,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
let L = toInt(lengthOrd(p.config, n[1].typ))
if optSeqDestructors in p.config.globalOptions:
let seqtype = n.typ
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
[rdLoc d, L, getTypeDesc(p.module, seqtype.lastSon),
getSeqPayloadType(p.module, seqtype)])
else:
@@ -1496,7 +1561,10 @@ proc genNewFinalize(p: BProc, e: PNode) =
initLocExpr(p, e[1], a)
initLocExpr(p, e[2], f)
initLoc(b, locExpr, a.lode, OnHeap)
ti = genTypeInfo(p.module, refType, e.info)
if optTinyRtti in p.config.globalOptions:
ti = genTypeInfoV2(p.module, refType, e.info)
else:
ti = genTypeInfoV1(p.module, refType, e.info)
p.module.s[cfsTypeInit3].addf("$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
getTypeDesc(p.module, refType),
@@ -1511,9 +1579,9 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope =
result = ropecg(p.module, "#isObj($1.m_type, $2)",
[a, genTypeInfo2Name(p.module, dest)])
else:
# unfortunately 'genTypeInfo' sets tfObjHasKids as a side effect, so we
# unfortunately 'genTypeInfoV1' sets tfObjHasKids as a side effect, so we
# have to call it here first:
let ti = genTypeInfo(p.module, dest, info)
let ti = genTypeInfoV1(p.module, dest, info)
if tfFinal in dest.flags or (objHasKidsValid in p.module.flags and
tfObjHasKids notin dest.flags):
result = "$1.m_type == $2" % [a, ti]
@@ -1526,7 +1594,7 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope =
when false:
# former version:
result = ropecg(p.module, "#isObj($1.m_type, $2)",
[a, genTypeInfo(p.module, dest, info)])
[a, genTypeInfoV1(p.module, dest, info)])
proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
var a: TLoc
@@ -1576,12 +1644,12 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
of tyEnum, tyOrdinal:
putIntoDest(p, d, e,
ropecg(p.module, "#reprEnum((NI)$1, $2)", [
rdLoc(a), genTypeInfo(p.module, t, e.info)]), a.storage)
rdLoc(a), genTypeInfoV1(p.module, t, e.info)]), a.storage)
of tyString:
putIntoDest(p, d, e, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]), a.storage)
of tySet:
putIntoDest(p, d, e, ropecg(p.module, "#reprSet($1, $2)", [
addrLoc(p.config, a), genTypeInfo(p.module, t, e.info)]), a.storage)
addrLoc(p.config, a), genTypeInfoV1(p.module, t, e.info)]), a.storage)
of tyOpenArray, tyVarargs:
var b: TLoc
case skipTypes(a.t, abstractVarRange).kind
@@ -1596,20 +1664,20 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
else: internalError(p.config, e[0].info, "genRepr()")
putIntoDest(p, d, e,
ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
genTypeInfo(p.module, elemType(t), e.info)]), a.storage)
genTypeInfoV1(p.module, elemType(t), e.info)]), a.storage)
of tyCString, tyArray, tyRef, tyPtr, tyPointer, tyNil, tySequence:
putIntoDest(p, d, e,
ropecg(p.module, "#reprAny($1, $2)", [
rdLoc(a), genTypeInfo(p.module, t, e.info)]), a.storage)
rdLoc(a), genTypeInfoV1(p.module, t, e.info)]), a.storage)
of tyEmpty, tyVoid:
localError(p.config, e.info, "'repr' doesn't support 'void' type")
else:
putIntoDest(p, d, e, ropecg(p.module, "#reprAny($1, $2)",
[addrLoc(p.config, a), genTypeInfo(p.module, t, e.info)]),
[addrLoc(p.config, a), genTypeInfoV1(p.module, t, e.info)]),
a.storage)
gcUsage(p.config, e)
proc rdMType(p: BProc; a: TLoc; nilCheck: var Rope): Rope =
proc rdMType(p: BProc; a: TLoc; nilCheck: var Rope; enforceV1 = false): Rope =
result = rdLoc(a)
var t = skipTypes(a.t, abstractInst)
while t.kind in {tyVar, tyLent, tyPtr, tyRef}:
@@ -1623,13 +1691,20 @@ proc rdMType(p: BProc; a: TLoc; nilCheck: var Rope): Rope =
result.add(".Sup")
t = skipTypes(t[0], skipPtrs)
result.add ".m_type"
if optTinyRtti in p.config.globalOptions and enforceV1:
result.add "->typeInfoV1"
proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
discard cgsym(p.module, "TNimType")
let t = e[1].typ
# ordinary static type information
putIntoDest(p, d, e, genTypeInfoV1(p.module, t, e.info))
proc genGetTypeInfoV2(p: BProc, e: PNode, d: var TLoc) =
let t = e[1].typ
if isFinal(t) or e[0].sym.name.s != "getDynamicTypeInfo":
# ordinary static type information
putIntoDest(p, d, e, genTypeInfo(p.module, t, e.info))
putIntoDest(p, d, e, genTypeInfoV2(p.module, t, e.info))
else:
var a: TLoc
initLocExpr(p, e[1], a)
@@ -1641,7 +1716,7 @@ template genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
var a: TLoc
initLocExpr(p, n[1], a)
a.r = ropecg(p.module, frmt, [rdLoc(a)])
a.flags = a.flags - {lfIndirect} # this flag should not be propagated here (not just for HCR)
a.flags.excl lfIndirect # this flag should not be propagated here (not just for HCR)
if d.k == locNone: getTemp(p, n.typ, d)
genAssignment(p, d, a, {})
gcUsage(p.config, n)
@@ -1663,8 +1738,12 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
else:
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)+1", [rdLoc(b), rdLoc(c)]))
else:
if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)")
else: unaryExpr(p, e, d, "$1Len_0")
if not reifiedOpenArray(a):
if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)")
else: unaryExpr(p, e, d, "$1Len_0")
else:
if op == mHigh: unaryExpr(p, e, d, "($1.Field1-1)")
else: unaryExpr(p, e, d, "$1.Field1")
of tyCString:
if op == mHigh: unaryExpr(p, e, d, "($1 ? (#nimCStrLen($1)-1) : -1)")
else: unaryExpr(p, e, d, "($1 ? #nimCStrLen($1) : 0)")
@@ -1718,13 +1797,13 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
const setLenPattern = "($3) #setLengthSeqV2(&($1)->Sup, $4, $2)"
call.r = ropecg(p.module, setLenPattern, [
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
genTypeInfo(p.module, t.skipTypes(abstractInst), e.info)])
genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info)])
else:
const setLenPattern = "($3) #setLengthSeqV2($1, $4, $2)"
call.r = ropecg(p.module, setLenPattern, [
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
genTypeInfo(p.module, t.skipTypes(abstractInst), e.info)])
genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info)])
genAssignment(p, a, call, {})
gcUsage(p.config, e)
@@ -1749,6 +1828,8 @@ proc genSwap(p: BProc, e: PNode, d: var TLoc) =
# temp = a
# a = b
# b = temp
cowBracket(p, e[1])
cowBracket(p, e[2])
var a, b, tmp: TLoc
getTemp(p, skipTypes(e[1].typ, abstractVar), tmp)
initLocExpr(p, e[1], a) # eval a
@@ -1982,25 +2063,30 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc) =
checkUnsignedConversions notin p.config.legacyFeatures):
discard "no need to generate a check because it was disabled"
else:
let raiser =
case skipTypes(n.typ, abstractVarRange).kind
of tyUInt..tyUInt64, tyChar: "raiseRangeErrorU"
of tyFloat..tyFloat128: "raiseRangeErrorF"
else: "raiseRangeErrorI"
discard cgsym(p.module, raiser)
# This seems to be bug-compatible with Nim version 1 but what we
# should really do here is to check if uint64Value < high(int)
let n0t = n[0].typ
let boundaryCast =
if n0t.skipTypes(abstractVarRange).kind in {tyUInt, tyUInt32, tyUInt64} or
(n0t.sym != nil and sfSystemModule in n0t.sym.owner.flags and n0t.sym.name.s == "csize"):
"(NI64)"
else:
""
# emit range check:
linefmt(p, cpsStmts, "if ($6($1) < $2 || $6($1) > $3){ $4($1, $2, $3); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), boundaryCast])
if n0t.kind in {tyUInt, tyUInt64}:
linefmt(p, cpsStmts, "if ($1 > ($6)($3)){ #raiseRangeErrorNoArgs(); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), getTypeDesc(p.module, n0t)])
else:
let raiser =
case skipTypes(n.typ, abstractVarRange).kind
of tyUInt..tyUInt64, tyChar: "raiseRangeErrorU"
of tyFloat..tyFloat128: "raiseRangeErrorF"
else: "raiseRangeErrorI"
discard cgsym(p.module, raiser)
let boundaryCast =
if n0t.skipTypes(abstractVarRange).kind in {tyUInt, tyUInt32, tyUInt64} or
(n0t.sym != nil and sfSystemModule in n0t.sym.owner.flags and n0t.sym.name.s == "csize"):
"(NI64)"
else:
""
linefmt(p, cpsStmts, "if ($6($1) < $2 || $6($1) > $3){ $4($1, $2, $3); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), boundaryCast])
putIntoDest(p, d, n, "(($1) ($2))" %
[getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage)
@@ -2065,10 +2151,14 @@ proc skipAddr(n: PNode): PNode =
proc genWasMoved(p: BProc; n: PNode) =
var a: TLoc
initLocExpr(p, n[1].skipAddr, a)
resetLoc(p, a)
#linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
# [addrLoc(p.config, a), getTypeDesc(p.module, a.t)])
let n1 = n[1].skipAddr
if p.withinBlockLeaveActions > 0 and notYetAlive(n1):
discard
else:
initLocExpr(p, n1, a)
resetLoc(p, a)
#linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
# [addrLoc(p.config, a), getTypeDesc(p.module, a.t)])
proc genMove(p: BProc; n: PNode; d: var TLoc) =
var a: TLoc
@@ -2077,7 +2167,7 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
# generated by liftdestructors:
var src: TLoc
initLocExpr(p, n[2], src)
linefmt(p, cpsStmts, "if ($1.len && $1.p != $2.p) {", [rdLoc(a), rdLoc(src)])
linefmt(p, cpsStmts, "if ($1.p != $2.p) {", [rdLoc(a), rdLoc(src)])
genStmts(p, n[3])
linefmt(p, cpsStmts, "}$n$1.len = $2.len; $1.p = $2.p;$n", [rdLoc(a), rdLoc(src)])
else:
@@ -2093,16 +2183,20 @@ proc genDestroy(p: BProc; n: PNode) =
of tyString:
var a: TLoc
initLocExpr(p, arg, a)
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
" #deallocShared($1.p);$n" &
" $1.p = NIM_NIL; $1.len = 0; }$n",
[rdLoc(a)])
if optThreads in p.config.globalOptions:
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
" #deallocShared($1.p);$n" &
"}$n", [rdLoc(a)])
else:
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
" #dealloc($1.p);$n" &
"}$n", [rdLoc(a)])
of tySequence:
var a: TLoc
initLocExpr(p, arg, a)
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
" #deallocShared($1.p);$n" &
" $1.p = NIM_NIL; $1.len = 0; }$n",
" #alignedDealloc($1.p, NIM_ALIGNOF($2));$n" &
"}$n",
[rdLoc(a), getTypeDesc(p.module, t.lastSon)])
else: discard "nothing to do"
else:
@@ -2122,12 +2216,20 @@ proc genDispose(p: BProc; n: PNode) =
if elemType.destructor != nil:
var destroyCall = newNodeI(nkCall, n.info)
genStmts(p, destroyCall)
lineCg(p, cpsStmts, ["#nimRawDispose($#)", rdLoc(a)])
lineFmt(p, cpsStmts, "#nimRawDispose($1, NIM_ALIGNOF($2))", [rdLoc(a), getTypeDesc(p.module, elemType)])
else:
# ``nimRawDisposeVirtual`` calls the ``finalizer`` which is the same as the
# destructor, but it uses the runtime type. Afterwards the memory is freed:
lineCg(p, cpsStmts, ["#nimDestroyAndDispose($#)", rdLoc(a)])
proc genSlice(p: BProc; e: PNode; d: var TLoc) =
let (x, y) = genOpenArraySlice(p, e, e.typ, e.typ.lastSon)
if d.k == locNone: getTemp(p, e.typ, d)
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $3;$n", [rdLoc(d), x, y])
when false:
localError(p.config, e.info, "invalid context for 'toOpenArray'; " &
"'toOpenArray' is only valid within a call expression")
proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
const ToStringProcSlot = -4
let t = e[1].typ.skipTypes(abstractInst+{tyRange})
@@ -2154,6 +2256,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mAddI..mPred: binaryArithOverflow(p, e, d, op)
of mRepr: genRepr(p, e, d)
of mGetTypeInfo: genGetTypeInfo(p, e, d)
of mGetTypeInfoV2: genGetTypeInfoV2(p, e, d)
of mSwap: genSwap(p, e, d)
of mInc, mDec:
const opr: array[mInc..mDec, string] = ["+=", "-="]
@@ -2205,6 +2308,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($1)")
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
of mStrToStr, mUnown: expr(p, e[1], d)
of mIsolate: genCall(p, e, d)
of mEnumToStr:
if optTinyRtti in p.config.globalOptions:
genEnumToStr(p, e, d)
@@ -2220,27 +2324,29 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
gcUsage(p.config, e)
else:
genNewFinalize(p, e)
of mNewSeq: genNewSeq(p, e)
of mNewSeq:
if optSeqDestructors in p.config.globalOptions:
e[1] = makeAddr(e[1])
genCall(p, e, d)
else:
genNewSeq(p, e)
of mNewSeqOfCap: genNewSeqOfCap(p, e, d)
of mSizeOf:
let t = e[1].typ.skipTypes({tyTypeDesc})
putIntoDest(p, d, e, "((NI)sizeof($1))" % [getTypeDesc(p.module, t)])
putIntoDest(p, d, e, "((NI)sizeof($1))" % [getTypeDesc(p.module, t, skVar)])
of mAlignOf:
let t = e[1].typ.skipTypes({tyTypeDesc})
if not p.module.compileToCpp:
p.module.includeHeader("<stdalign.h>")
putIntoDest(p, d, e, "((NI)alignof($1))" % [getTypeDesc(p.module, t)])
putIntoDest(p, d, e, "((NI)NIM_ALIGNOF($1))" % [getTypeDesc(p.module, t, skVar)])
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")
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 tname = getTypeDesc(p.module, t)
let tname = getTypeDesc(p.module, t, skVar)
let member =
if t.kind == tyTuple:
"Field" & rope(dotExpr[1].sym.position)
@@ -2301,6 +2407,10 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
let n = semparallel.liftParallel(p.module.g.graph, p.module.module, e)
expr(p, n, d)
of mDeepCopy:
if p.config.selectedGC in {gcArc, gcOrc} and optEnableDeepCopy notin p.config.globalOptions:
localError(p.config, e.info,
"for --gc:arc|orc 'deepcopy' support has to be enabled with --deepcopy:on")
var a, b: TLoc
let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1]
initLocExpr(p, x, a)
@@ -2311,9 +2421,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mMove: genMove(p, e, d)
of mDestroy: genDestroy(p, e)
of mAccessEnv: unaryExpr(p, e, d, "$1.ClE_0")
of mSlice:
localError(p.config, e.info, "invalid context for 'toOpenArray'; " &
"'toOpenArray' is only valid within a call expression")
of mSlice: genSlice(p, e, d)
else:
when defined(debugMagics):
echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind
@@ -2390,7 +2498,7 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
inc(p.module.labels)
var tmp = "CNSTCLOSURE" & rope(p.module.labels)
p.module.s[cfsData].addf("static NIM_CONST $1 $2 = $3;$n",
[getTypeDesc(p.module, n.typ), tmp, genBracedInit(p, n, isConst = true)])
[getTypeDesc(p.module, n.typ), tmp, genBracedInit(p, n, isConst = true, n.typ)])
putIntoDest(p, d, n, tmp, OnStatic)
else:
var tmp, a, b: TLoc
@@ -2453,6 +2561,8 @@ proc genStmtList(p: BProc, n: PNode) =
genStmtListExprImpl:
genStmts(p, n[^1])
from parampatterns import isLValue
proc upConv(p: BProc, n: PNode, d: var TLoc) =
var a: TLoc
initLocExpr(p, n[0], a)
@@ -2463,7 +2573,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
let checkFor = if optTinyRtti in p.config.globalOptions:
genTypeInfo2Name(p.module, dest)
else:
genTypeInfo(p.module, dest, n.info)
genTypeInfoV1(p.module, dest, n.info)
if nilCheck != nil:
linefmt(p, cpsStmts, "if ($1 && !#isObj($2, $3)){ #raiseObjectConversionError(); $4}$n",
[nilCheck, r, checkFor, raiseInstr(p)])
@@ -2471,7 +2581,11 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
linefmt(p, cpsStmts, "if (!#isObj($1, $2)){ #raiseObjectConversionError(); $3}$n",
[r, checkFor, raiseInstr(p)])
if n[0].typ.kind != tyObject:
putIntoDest(p, d, n,
if n.isLValue:
putIntoDest(p, d, n,
"(*(($1*) (&($2))))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage)
else:
putIntoDest(p, d, n,
"(($1) ($2))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage)
else:
putIntoDest(p, d, n, "(*($1*) ($2))" %
@@ -2523,7 +2637,7 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
# expression not found in the cache:
inc(p.module.labels)
p.module.s[cfsData].addf("static NIM_CONST $1 $2 = $3;$n",
[getTypeDesc(p.module, t), tmp, genBracedInit(p, n, isConst = true)])
[getTypeDesc(p.module, t, skConst), tmp, genBracedInit(p, n, isConst = true, t)])
if d.k == locNone:
fillLoc(d, locData, n, tmp, OnStatic)
@@ -2588,10 +2702,12 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
else:
putLocIntoDest(p, d, sym.loc)
of skTemp:
if sym.loc.r == nil:
# we now support undeclared 'skTemp' variables for easier
# transformations in other parts of the compiler:
assignLocalVar(p, n)
when false:
# this is more harmful than helpful.
if sym.loc.r == nil:
# we now support undeclared 'skTemp' variables for easier
# transformations in other parts of the compiler:
assignLocalVar(p, n)
if sym.loc.r == nil or sym.loc.t == nil:
#echo "FAILED FOR PRCO ", p.prc.name.s
#echo renderTree(p.prc.ast, {renderIds})
@@ -2666,9 +2782,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
expr(p, n[1][0], d)
of nkObjDownConv: downConv(p, n, d)
of nkObjUpConv: upConv(p, n, d)
of nkChckRangeF: genRangeChck(p, n, d)
of nkChckRange64: genRangeChck(p, n, d)
of nkChckRange: genRangeChck(p, n, d)
of nkChckRangeF, nkChckRange64, nkChckRange: genRangeChck(p, n, d)
of nkStringToCString: convStrToCStr(p, n, d)
of nkCStringToString: convCStrToStr(p, n, d)
of nkLambdaKinds:
@@ -2688,9 +2802,11 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
of nkReturnStmt: genReturnStmt(p, n)
of nkBreakStmt: genBreakStmt(p, n)
of nkAsgn:
cow(p, n[1])
if nfPreventCg notin n.flags:
genAsgn(p, n, fastAsgn=false)
of nkFastAsgn:
cow(p, n[1])
if nfPreventCg notin n.flags:
# transf is overly aggressive with 'nkFastAsgn', so we work around here.
# See tests/run/tcnstseq3 for an example that would fail otherwise.
@@ -2745,8 +2861,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind")
proc genNamedConstExpr(p: BProc, n: PNode; isConst: bool): Rope =
if n.kind == nkExprColonExpr: result = genBracedInit(p, n[1], isConst)
else: result = genBracedInit(p, n, isConst)
if n.kind == nkExprColonExpr: result = genBracedInit(p, n[1], isConst, n[0].typ)
else: result = genBracedInit(p, n, isConst, n.typ)
proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
var t = skipTypes(typ, abstractRange+{tyOwned}-{tyTypeDesc})
@@ -2785,8 +2901,10 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
result.add getDefaultValue(p, t.sons[1], info)
result.add "}"
#result = rope"{}"
of tyOpenArray, tyVarargs:
result = rope"{NIM_NIL, 0}"
of tySet:
if mapType(p.config, t) == ctArray: result = rope"{}"
if mapSetType(p.config, t) == ctArray: result = rope"{}"
else: result = rope"0"
else:
globalError(p.config, info, "cannot create null element for: " & $t.kind)
@@ -2851,10 +2969,10 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
for i in 1..<constOrNil.len:
if constOrNil[i].kind == nkExprColonExpr:
if constOrNil[i][0].sym.name.id == field.name.id:
result.add genBracedInit(p, constOrNil[i][1], isConst)
result.add genBracedInit(p, constOrNil[i][1], isConst, field.typ)
return
elif i == field.position:
result.add genBracedInit(p, constOrNil[i], isConst)
result.add genBracedInit(p, constOrNil[i], isConst, field.typ)
return
# not found, produce default value:
result.add getDefaultValue(p, field.typ, info)
@@ -2873,7 +2991,10 @@ proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode,
getNullValueAuxT(p, orig, base, base.n, constOrNil, result, count, isConst, info)
result.add "}"
elif not isObjLackingTypeField(t):
result.add genTypeInfo(p.module, orig, obj.info)
if optTinyRtti in p.config.globalOptions:
result.add genTypeInfoV2(p.module, orig, obj.info)
else:
result.add genTypeInfoV1(p.module, orig, obj.info)
inc count
getNullValueAux(p, t, obj, constOrNil, result, count, isConst, info)
# do not emit '{}' as that is not valid C:
@@ -2892,25 +3013,35 @@ proc genConstObjConstr(p: BProc; n: PNode; isConst: bool): Rope =
proc genConstSimpleList(p: BProc, n: PNode; isConst: bool): Rope =
result = rope("{")
for i in 0..<n.len - 1:
result.addf("$1,$n", [genNamedConstExpr(p, n[i], isConst)])
if n.len > 0:
result.add(genNamedConstExpr(p, n[^1], isConst))
result.addf("}$n", [])
for i in 0..<n.len:
let it = n[i]
if i > 0: result.add ",\n"
if it.kind == nkExprColonExpr: result.add genBracedInit(p, it[1], isConst, it[0].typ)
else: result.add genBracedInit(p, it, isConst, it.typ)
result.add("}\n")
proc genConstTuple(p: BProc, n: PNode; isConst: bool; tup: PType): Rope =
result = rope("{")
for i in 0..<n.len:
let it = n[i]
if i > 0: result.add ",\n"
if it.kind == nkExprColonExpr: result.add genBracedInit(p, it[1], isConst, tup[i])
else: result.add genBracedInit(p, it, isConst, tup[i])
result.add("}\n")
proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool): Rope =
var data = "{{$1, $1 | NIM_STRLIT_FLAG}" % [n.len.rope]
let base = t.skipTypes(abstractInst)[0]
if n.len > 0:
# array part needs extra curlies:
data.add(", {")
for i in 0..<n.len:
if i > 0: data.addf(",$n", [])
data.add genBracedInit(p, n[i], isConst)
data.add genBracedInit(p, n[i], isConst, base)
data.add("}")
data.add("}")
result = getTempName(p.module)
let base = t.skipTypes(abstractInst)[0]
appcg(p.module, cfsData,
"static $5 struct {$n" &
@@ -2923,14 +3054,14 @@ proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool): Rope =
result = "(($1)&$2)" % [getTypeDesc(p.module, t), result]
proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool): Rope =
let base = t.skipTypes(abstractInst)[0]
var data = rope"{"
for i in 0..<n.len:
if i > 0: data.addf(",$n", [])
data.add genBracedInit(p, n[i], isConst)
data.add genBracedInit(p, n[i], isConst, base)
data.add("}")
let payload = getTempName(p.module)
let base = t.skipTypes(abstractInst)[0]
appcg(p.module, cfsData,
"static $5 struct {$n" &
@@ -2940,47 +3071,32 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool): Rope =
if isConst: "const" else: ""])
result = "{$1, ($2*)&$3}" % [rope(n.len), getSeqPayloadType(p.module, t), payload]
proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope =
proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType): Rope =
case n.kind
of nkHiddenStdConv, nkHiddenSubConv:
when false:
# XXX The frontend doesn't keep conversions to openArray for us. :-(
# We need to change 'transformConv' first, but that is hard.
if n.typ.kind == tyOpenArray:
assert n[1].kind == nkBracket
let data = genBracedInit(p, n[1], isConst)
let payload = getTempName(p.module)
let ctype = getTypeDesc(p.module, n.typ.skipTypes(abstractInst)[0])
let arrLen = n[1].len
appcg(p.module, cfsData,
"static $5 $1 $3[$2] = $4;$n", [
ctype, arrLen, payload, data,
if isConst: "const" else: ""])
result = "{($1*)&$2, $3}" % [ctype, payload, rope arrLen]
else:
result = genBracedInit(p, n[1], isConst)
result = genBracedInit(p, n[1], isConst, n.typ)
else:
var ty = tyNone
if n.typ == nil:
var typ: PType = nil
if optionalType == nil:
if n.kind in nkStrKinds:
ty = tyString
else:
internalError(p.config, n.info, "node has no type")
else:
ty = skipTypes(n.typ, abstractInstOwned + {tyStatic}).kind
typ = skipTypes(optionalType, abstractInstOwned + {tyStatic})
ty = typ.kind
case ty
of tySet:
var cs: TBitSet
toBitSet(p.config, n, cs)
let cs = toBitSet(p.config, n)
result = genRawSetData(cs, int(getSize(p.config, n.typ)))
of tySequence:
if optSeqDestructors in p.config.globalOptions:
result = genConstSeqV2(p, n, n.typ, isConst)
result = genConstSeqV2(p, n, typ, isConst)
else:
result = genConstSeq(p, n, n.typ, isConst)
result = genConstSeq(p, n, typ, isConst)
of tyProc:
if n.typ.callConv == ccClosure and n.len > 1 and n[1].kind == nkNilLit:
if typ.callConv == ccClosure and n.len > 1 and n[1].kind == nkNilLit:
# Conversion: nimcall -> closure.
# this hack fixes issue that nkNilLit is expanded to {NIM_NIL,NIM_NIL}
# this behaviour is needed since closure_var = nil must be
@@ -2993,13 +3109,30 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope =
else:
var d: TLoc
initLocExpr(p, n[0], d)
result = "{(($1) $2),NIM_NIL}" % [getClosureType(p.module, n.typ, clHalfWithEnv), rdLoc(d)]
result = "{(($1) $2),NIM_NIL}" % [getClosureType(p.module, typ, clHalfWithEnv), rdLoc(d)]
else:
var d: TLoc
initLocExpr(p, n, d)
result = rdLoc(d)
of tyArray, tyTuple, tyOpenArray, tyVarargs:
of tyArray, tyVarargs:
result = genConstSimpleList(p, n, isConst)
of tyTuple:
result = genConstTuple(p, n, isConst, typ)
of tyOpenArray:
if n.kind != nkBracket:
internalError(p.config, n.info, "const openArray expression is not an array construction")
let data = genConstSimpleList(p, n, isConst)
let payload = getTempName(p.module)
let ctype = getTypeDesc(p.module, typ[0])
let arrLen = n.len
appcg(p.module, cfsData,
"static $5 $1 $3[$2] = $4;$n", [
ctype, arrLen, payload, data,
if isConst: "const" else: ""])
result = "{($1*)&$2, $3}" % [ctype, payload, rope arrLen]
of tyObject:
result = genConstObjConstr(p, n, isConst)
of tyString, tyCString:

View File

@@ -48,6 +48,10 @@ const
NimMergeEndMark = "/*\tNIM_merge_END:*/"
proc genSectionStart*(fs: TCFileSection; conf: ConfigRef): Rope =
# useful for debugging and only adds at most a few lines in each file
result.add("\n/* section: ")
result.add(CFileSectionNames[fs])
result.add(" */\n")
if compilationCachePresent(conf):
result = nil
result.add("\n/*\t")
@@ -278,7 +282,7 @@ proc mergeRequired*(m: BModule): bool =
if m.s[i] != nil:
#echo "not empty: ", i, " ", m.s[i]
return true
for i in low(TCProcSection)..high(TCProcSection):
for i in TCProcSection:
if m.initProc.s(i) != nil:
#echo "not empty: ", i, " ", m.initProc.s[i]
return true
@@ -288,7 +292,7 @@ proc mergeFiles*(cfilename: AbsoluteFile, m: BModule) =
var old: TMergeSections
readMergeSections(cfilename, old)
# do the merge; old section before new section:
for i in low(TCFileSection)..high(TCFileSection):
for i in TCFileSection:
m.s[i] = old.f[i] & m.s[i]
for i in low(TCProcSection)..high(TCProcSection):
for i in TCProcSection:
m.initProc.s(i) = old.p[i] & m.initProc.s(i)

View File

@@ -200,6 +200,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
var stack = newSeq[tuple[fin: PNode, inExcept: bool, label: Natural]](0)
inc p.withinBlockLeaveActions
for i in 1..howManyTrys:
let tryStmt = p.nestedTryStmts.pop
if p.config.exc == excSetjmp:
@@ -217,6 +218,8 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
if finallyStmt != nil:
genStmts(p, finallyStmt[0])
dec p.withinBlockLeaveActions
# push old elements again:
for i in countdown(howManyTrys-1, 0):
p.nestedTryStmts.add(stack[i])
@@ -269,7 +272,7 @@ proc genGotoVar(p: BProc; value: PNode) =
else:
lineF(p, cpsStmts, "goto NIMSTATE_$#;$n", [value.intVal.rope])
proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope
proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType): Rope
proc potentialValueInit(p: BProc; v: PSym; value: PNode): Rope =
if lfDynamicLib in v.loc.flags or sfThread in v.flags or p.hcrOn:
@@ -277,7 +280,7 @@ proc potentialValueInit(p: BProc; v: PSym; value: PNode): Rope =
elif sfGlobal in v.flags and value != nil and isDeepConstExpr(value, p.module.compileToCpp) and
p.withinLoop == 0 and not containsGarbageCollectedRef(v.typ):
#echo "New code produced for ", v.name.s, " ", p.config $ value.info
result = genBracedInit(p, value, isConst = false)
result = genBracedInit(p, value, isConst = false, v.typ)
else:
result = nil
@@ -379,7 +382,13 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
proc genSingleVar(p: BProc, a: PNode) =
let v = a[0].sym
if sfCompileTime in v.flags: return
if sfCompileTime in v.flags:
# fix issue #12640
# {.global, compileTime.} pragma in proc
if sfGlobal in v.flags and p.prc != nil and p.prc.kind == skProc:
discard
else:
return
genSingleVar(p, v, a[0], a[2])
proc genClosureVar(p: BProc, a: PNode) =
@@ -728,6 +737,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
initLocExprSingleUse(p, t[0], a)
finallyActions(p)
var e = rdLoc(a)
discard getTypeDesc(p.module, t[0].typ)
var typ = skipTypes(t[0].typ, abstractPtrs)
# XXX For reasons that currently escape me, this is only required by the new
# C++ based exception handling:
@@ -860,10 +870,10 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
genCaseGeneric(p, t, d, "", "if (#eqStrings($1, $2)) goto $3;$n")
proc branchHasTooBigRange(b: PNode): bool =
for i in 0..<b.len-1:
for it in b:
# last son is block
if (b[i].kind == nkRange) and
b[i][1].intVal - b[i][0].intVal > RangeExpandLimit:
if (it.kind == nkRange) and
it[1].intVal - it[0].intVal > RangeExpandLimit:
return true
proc ifSwitchSplitPoint(p: BProc, n: PNode): int =
@@ -987,9 +997,14 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
p.nestedTryStmts.add((fin, false, 0.Natural))
startBlock(p, "try {$n")
expr(p, t[0], d)
endBlock(p)
if t.kind == nkHiddenTryStmt:
lineCg(p, cpsStmts, "try {$n", [])
expr(p, t[0], d)
lineCg(p, cpsStmts, "}$n", [])
else:
startBlock(p, "try {$n")
expr(p, t[0], d)
endBlock(p)
# First pass: handle Nim based exceptions:
lineCg(p, cpsStmts, "catch (#Exception* T$1_) {$n", [etmp+1])
@@ -1031,7 +1046,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
let checkFor = if optTinyRtti in p.config.globalOptions:
genTypeInfo2Name(p.module, typeNode.typ)
else:
genTypeInfo(p.module, typeNode.typ, typeNode.info)
genTypeInfoV1(p.module, typeNode.typ, typeNode.info)
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
@@ -1209,6 +1224,10 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
p.nestedTryStmts.add((fin, false, Natural lab))
p.flags.incl nimErrorFlagAccessed
if not isEmptyType(t.typ) and d.k == locNone:
getTemp(p, t.typ, d)
expr(p, t[0], d)
if 1 < t.len and t[1].kind == nkExceptBranch:
@@ -1242,7 +1261,7 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
let checkFor = if optTinyRtti in p.config.globalOptions:
genTypeInfo2Name(p.module, t[i][j].typ)
else:
genTypeInfo(p.module, t[i][j].typ, t[i][j].info)
genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info)
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
@@ -1279,7 +1298,7 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
# handler present or only handlers that did not match.
linefmt(p, cpsStmts, "*nimErr_ = oldNimErrFin$1_;$n", [lab])
endBlock(p)
if p.prc != nil: raiseExit(p)
raiseExit(p)
if hasExcept: inc p.withinTryWithExcept
proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
@@ -1345,13 +1364,13 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", [safePoint])
else:
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
lineCg(p, cpsStmts, "if ($1.status == 0) {$n", [safePoint])
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
p.nestedTryStmts.add((fin, quirkyExceptions, 0.Natural))
expr(p, t[0], d)
if not quirkyExceptions:
linefmt(p, cpsStmts, "#popSafePoint();$n", [])
endBlock(p)
lineCg(p, cpsStmts, "}$n", [])
startBlock(p, "else {$n")
linefmt(p, cpsStmts, "#popSafePoint();$n", [])
genRestoreFrameAfterException(p)
@@ -1381,7 +1400,7 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
let checkFor = if optTinyRtti in p.config.globalOptions:
genTypeInfo2Name(p.module, t[i][j].typ)
else:
genTypeInfo(p.module, t[i][j].typ, t[i][j].info)
genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info)
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
@@ -1452,7 +1471,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
else:
# ignore empty lines
result.add("\"")
result.add(x)
result.add(x.replace("\"", "\\\""))
result.add("\\n\"\n")
else:
res.add("\L")
@@ -1496,7 +1515,7 @@ proc genPragma(p: BProc, n: PNode) =
of wEmit: genEmit(p, it)
of wInjectStmt:
var p = newProc(nil, p.module)
p.options = p.options - {optLineTrace, optStackTrace}
p.options.excl {optLineTrace, optStackTrace}
genStmts(p, it[1])
p.module.injectStmt = p.s(cpsStmts)
else: discard
@@ -1506,7 +1525,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
field: PSym) =
var t = skipTypes(objtype, abstractVar)
assert t.kind == tyObject
discard genTypeInfo(p.module, t, a.lode.info)
discard genTypeInfoV1(p.module, t, a.lode.info)
if not containsOrIncl(p.module.declaredThings, field.id):
appcg(p.module, cfsVars, "extern $1",
[discriminatorTableDecl(p.module, t, field)])
@@ -1554,7 +1573,7 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
let le = e[0]
let ri = e[1]
var a: TLoc
discard getTypeDesc(p.module, le.typ.skipTypes(skipPtrs))
discard getTypeDesc(p.module, le.typ.skipTypes(skipPtrs), skVar)
initLoc(a, locNone, le, OnUnknown)
a.flags.incl(lfEnforceDeref)
a.flags.incl(lfPrepareForMutation)

View File

@@ -42,11 +42,12 @@ proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
proc generateThreadLocalStorage(m: BModule) =
if m.g.nimtv != nil and (usesThreadVars in m.flags or sfMainModule in m.module.flags):
for t in items(m.g.nimtvDeps): discard getTypeDesc(m, t)
finishTypeDescriptions(m)
m.s[cfsSeqTypes].addf("typedef struct {$1} NimThreadVars;$n", [m.g.nimtv])
proc generateThreadVarsSize(m: BModule) =
if m.g.nimtv != nil:
let externc = if m.config.cmd == cmdCompileToCpp or
let externc = if m.config.backend == backendCpp or
sfCompileToCpp in m.module.flags: "extern \"C\" "
else: ""
m.s[cfsProcs].addf(

View File

@@ -173,7 +173,7 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope =
[result, markerName, getModuleDllPath(m)])
proc genTraverseProcForGlobal(m: BModule, s: PSym; info: TLineInfo): Rope =
discard genTypeInfo(m, s.loc.t, info)
discard genTypeInfoV1(m, s.loc.t, info)
var c: TTraversalClosure
var p = newProc(nil, m)

View File

@@ -149,7 +149,7 @@ proc mapSetType(conf: ConfigRef; typ: PType): TCTypeKind =
of 8: result = ctInt64
else: result = ctArray
proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
proc mapType(conf: ConfigRef; typ: PType; kind: TSymKind): TCTypeKind =
## Maps a Nim type to a C type
case typ.kind
of tyNone, tyTyped: result = ctVoid
@@ -157,14 +157,17 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
of tyChar: result = ctChar
of tyNil: result = ctPtr
of tySet: result = mapSetType(conf, typ)
of tyOpenArray, tyArray, tyVarargs, tyUncheckedArray: result = ctArray
of tyOpenArray, tyVarargs:
if kind == skParam: result = ctArray
else: result = ctStruct
of tyArray, tyUncheckedArray: result = ctArray
of tyObject, tyTuple: result = ctStruct
of tyUserTypeClasses:
doAssert typ.isResolvedUserTypeClass
return mapType(conf, typ.lastSon)
return mapType(conf, typ.lastSon, kind)
of tyGenericBody, tyGenericInst, tyGenericParam, tyDistinct, tyOrdinal,
tyTypeDesc, tyAlias, tySink, tyInferred, tyOwned:
result = mapType(conf, lastSon(typ))
result = mapType(conf, lastSon(typ), kind)
of tyEnum:
if firstOrd(conf, typ) < 0:
result = ctInt32
@@ -175,7 +178,7 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
of 4: result = ctInt32
of 8: result = ctInt64
else: result = ctInt32
of tyRange: result = mapType(conf, typ[0])
of tyRange: result = mapType(conf, typ[0], kind)
of tyPtr, tyVar, tyLent, tyRef:
var base = skipTypes(typ.lastSon, typedescInst)
case base.kind
@@ -192,14 +195,14 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
of tyInt..tyUInt64:
result = TCTypeKind(ord(typ.kind) - ord(tyInt) + ord(ctInt))
of tyStatic:
if typ.n != nil: result = mapType(conf, lastSon typ)
if typ.n != nil: result = mapType(conf, lastSon typ, kind)
else: doAssert(false, "mapType")
else: doAssert(false, "mapType")
proc mapReturnType(conf: ConfigRef; typ: PType): TCTypeKind =
#if skipTypes(typ, typedescInst).kind == tyArray: result = ctPtr
#else:
result = mapType(conf, typ)
result = mapType(conf, typ, skResult)
proc isImportedType(t: PType): bool =
result = t.sym != nil and sfImportc in t.sym.flags
@@ -209,7 +212,7 @@ proc isImportedCppType(t: PType): bool =
result = (t.sym != nil and sfInfixCall in t.sym.flags) or
(x.sym != nil and sfInfixCall in x.sym.flags)
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKind): Rope
proc isObjLackingTypeField(typ: PType): bool {.inline.} =
result = (typ.kind == tyObject) and ((tfFinal in typ.flags) and
@@ -223,7 +226,7 @@ proc isInvalidReturnType(conf: ConfigRef; rettype: PType): bool =
if rettype == nil or (tfByCopy notin rettype.flags and getSize(conf, rettype) > conf.target.floatSize*3):
result = true
else:
case mapType(conf, rettype)
case mapType(conf, rettype, skResult)
of ctArray:
result = not (skipTypes(rettype, typedescInst).kind in
{tyVar, tyLent, tyRef, tyPtr})
@@ -239,7 +242,7 @@ const
"N_STDCALL", "N_CDECL", "N_SAFECALL",
"N_SYSCALL", # this is probably not correct for all platforms,
# but one can #define it to what one wants
"N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_CLOSURE", "N_NOCONV"]
"N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_THISCALL", "N_CLOSURE", "N_NOCONV"]
proc cacheGetType(tab: TypeCache; sig: SigHash): Rope =
# returns nil if we need to declare this type
@@ -248,8 +251,13 @@ proc cacheGetType(tab: TypeCache; sig: SigHash): Rope =
result = tab.getOrDefault(sig)
proc addAbiCheck(m: BModule, t: PType, name: Rope) =
if isDefined(m.config, "checkabi") and (let size = getSize(m.config, t); size != szUnknownSize):
m.s[cfsTypeInfo].addf("NIM_CHECK_SIZE($1, $2);$n", [name, rope(size)])
if isDefined(m.config, "checkAbi") and (let size = getSize(m.config, t); size != szUnknownSize):
var msg = "backend & Nim disagree on size for: "
msg.addTypeHeader(m.config, t)
var msg2 = ""
msg2.addQuoted msg # not a hostspot so extra allocation doesn't matter
m.s[cfsTypeInfo].addf("NIM_STATIC_ASSERT(sizeof($1) == $2, $3);$n", [name, rope(size), msg2.rope])
# see `testCodegenABICheck` for example error message it generates
proc ccgIntroducedPtr(conf: ConfigRef; s: PSym, retType: PType): bool =
var pt = skipTypes(s.typ, typedescInst)
@@ -264,19 +272,19 @@ proc ccgIntroducedPtr(conf: ConfigRef; s: PSym, retType: PType): bool =
result = true
elif (optByRef in s.options) or (getSize(conf, pt) > conf.target.floatSize * 3):
result = true # requested anyway
elif retType != nil and retType.kind == tyLent:
result = true
elif (tfFinal in pt.flags) and (pt[0] == nil):
result = false # no need, because no subtyping possible
else:
result = true # ordinary objects are always passed by reference,
# otherwise casting doesn't work
of tyTuple:
if retType != nil and retType.kind == tyLent:
result = true
else:
result = (getSize(conf, pt) > conf.target.floatSize*3) or (optByRef in s.options)
else: result = false
result = (getSize(conf, pt) > conf.target.floatSize*3) or (optByRef in s.options)
else:
result = false
# first parameter and return type is 'lent T'? --> use pass by pointer
if s.position == 0 and retType != nil and retType.kind == tyLent:
result = not (pt.kind in {tyVar, tyArray, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} or
pt.kind == tySet and mapSetType(conf, pt) == ctArray)
proc fillResult(conf: ConfigRef; param: PNode) =
fillLoc(param.sym.loc, locParam, param, ~"Result",
@@ -329,7 +337,6 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
let sig = hashType typ
if cacheGetType(m.typeCache, sig) == nil:
m.typeCache[sig] = result
addAbiCheck(m, typ, result)
proc pushType(m: BModule, typ: PType) =
for i in 0..high(m.typeStack):
@@ -344,8 +351,8 @@ proc getTypePre(m: BModule, typ: PType; sig: SigHash): Rope =
if result == nil: result = cacheGetType(m.typeCache, sig)
proc structOrUnion(t: PType): Rope =
let cachedUnion {.global.} = rope("union")
let cachedStruct {.global.} = rope("struct")
let cachedUnion = rope("union")
let cachedStruct = rope("struct")
let t = t.skipTypes({tyAlias, tySink})
if tfUnion in t.flags: cachedUnion
else: cachedStruct
@@ -365,7 +372,7 @@ proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope =
if result != nil: return
result = getTypePre(m, typ, sig)
if result != nil: return
let concrete = typ.skipTypes(abstractInst + {tyOpt})
let concrete = typ.skipTypes(abstractInst)
case concrete.kind
of tySequence, tyTuple, tyObject:
result = getTypeName(m, typ, sig)
@@ -377,7 +384,7 @@ proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope =
doAssert m.forwTypeCache[sig] == result
else: internalError(m.config, "getTypeForward(" & $typ.kind & ')')
proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet; kind: TSymKind): Rope =
## like getTypeDescAux but creates only a *weak* dependency. In other words
## we know we only need a pointer to it so we only generate a struct forward
## declaration:
@@ -385,7 +392,7 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
case etB.kind
of tyObject, tyTuple:
if isImportedCppType(etB) and t.kind == tyGenericInst:
result = getTypeDescAux(m, t, check)
result = getTypeDescAux(m, t, check, kind)
else:
result = getTypeForward(m, t, hashType(t))
pushType(m, t)
@@ -415,18 +422,18 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
result = getTypeForward(m, t, sig) & seqStar(m)
pushType(m, t)
else:
result = getTypeDescAux(m, t, check)
result = getTypeDescAux(m, t, check, kind)
proc getSeqPayloadType(m: BModule; t: PType): Rope =
var check = initIntSet()
result = getTypeDescWeak(m, t, check) & "_Content"
result = getTypeDescWeak(m, t, check, skParam) & "_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)
discard getTypeDescAux(m, t, check, skVar)
else:
# little hack for now to prevent multiple definitions of the same
# Seq_Content:
@@ -435,7 +442,7 @@ $3ifndef $2_Content_PP
$3define $2_Content_PP
struct $2_Content { NI cap; $1 data[SEQ_DECL_SIZE];};
$3endif$N
""", [getTypeDescAux(m, t.skipTypes(abstractInst)[0], check), result, rope"#"])
""", [getTypeDescAux(m, t.skipTypes(abstractInst)[0], check, skVar), result, rope"#"])
proc paramStorageLoc(param: PSym): TStorageLoc =
if param.typ.skipTypes({tyVar, tyLent, tyTypeDesc}).kind notin {
@@ -451,7 +458,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
if t[0] == nil or isInvalidReturnType(m.config, t[0]):
rettype = ~"void"
else:
rettype = getTypeDescAux(m, t[0], check)
rettype = getTypeDescAux(m, t[0], check, skResult)
for i in 1..<t.n.len:
if t.n[i].kind != nkSym: internalError(m.config, t.n.info, "genProcParams")
var param = t.n[i].sym
@@ -460,15 +467,17 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
fillLoc(param.loc, locParam, t.n[i], mangleParamName(m, param),
param.paramStorageLoc)
if ccgIntroducedPtr(m.config, param, t[0]):
params.add(getTypeDescWeak(m, param.typ, check))
params.add(getTypeDescWeak(m, param.typ, check, skParam))
params.add(~"*")
incl(param.loc.flags, lfIndirect)
param.loc.storage = OnUnknown
elif weakDep:
params.add(getTypeDescWeak(m, param.typ, check))
params.add(getTypeDescWeak(m, param.typ, check, skParam))
else:
params.add(getTypeDescAux(m, param.typ, check))
params.add(getTypeDescAux(m, param.typ, check, skParam))
params.add(~" ")
if sfNoalias in param.flags:
params.add(~"NIM_NOALIAS ")
params.add(param.loc.r)
# declare the len field for open arrays:
var arr = param.typ
@@ -485,10 +494,10 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
var arr = t[0]
if params != nil: params.add(", ")
if mapReturnType(m.config, t[0]) != ctArray:
params.add(getTypeDescWeak(m, arr, check))
params.add(getTypeDescWeak(m, arr, check, skResult))
params.add("*")
else:
params.add(getTypeDescAux(m, arr, check))
params.add(getTypeDescAux(m, arr, check, skResult))
params.addf(" Result", [])
if t.callConv == ccClosure and declareEnvironment:
if params != nil: params.add(", ")
@@ -557,19 +566,21 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
# have to recurse via 'getTypeDescAux'. And not doing so prevents problems
# with heavily templatized C++ code:
if not isImportedCppType(rectype):
let noAlias = if sfNoalias in field.flags: ~" NIM_NOALIAS" else: nil
let fieldType = field.loc.lode.typ.skipTypes(abstractInst)
if fieldType.kind == tyUncheckedArray:
result.addf("$1 $2[SEQ_DECL_SIZE];$n",
[getTypeDescAux(m, fieldType.elemType, check), sname])
[getTypeDescAux(m, fieldType.elemType, check, skField), sname])
elif fieldType.kind == tySequence:
# we need to use a weak dependency here for trecursive_table.
result.addf("$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname])
result.addf("$1$3 $2;$n", [getTypeDescWeak(m, field.loc.t, check, skField), sname, noAlias])
elif field.bitsize != 0:
result.addf("$1 $2:$3;$n", [getTypeDescAux(m, field.loc.t, check), sname, rope($field.bitsize)])
result.addf("$1$4 $2:$3;$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, rope($field.bitsize), noAlias])
else:
# don't use fieldType here because we need the
# tyGenericInst for C++ template support
result.addf("$1 $2;$n", [getTypeDescAux(m, field.loc.t, check), sname])
result.addf("$1$3 $2;$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias])
else: internalError(m.config, n.info, "genRecordFieldsAux()")
proc getRecordFields(m: BModule, typ: PType, check: var IntSet): Rope =
@@ -604,11 +615,14 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
if (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags:
appcg(m, result, " {$n", [])
else:
appcg(m, result, " {$n#TNimType* m_type;$n", [])
if optTinyRtti in m.config.globalOptions:
appcg(m, result, " {$n#TNimTypeV2* m_type;$n", [])
else:
appcg(m, result, " {$n#TNimType* m_type;$n", [])
hasField = true
elif m.compileToCpp:
appcg(m, result, " : public $1 {$n",
[getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check)])
[getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check, skField)])
if typ.isException and m.config.exc == excCpp:
when false:
appcg(m, result, "virtual void raise() { throw *this; }$n", []) # required for polymorphic exceptions
@@ -621,7 +635,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
hasField = true
else:
appcg(m, result, " {$n $1 Sup;$n",
[getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check)])
[getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check, skField)])
hasField = true
else:
result.addf(" {$n", [name])
@@ -641,7 +655,7 @@ proc getTupleDesc(m: BModule, typ: PType, name: Rope,
var desc: Rope = nil
for i in 0..<typ.len:
desc.addf("$1 Field$2;$n",
[getTypeDescAux(m, typ[i], check), rope(i)])
[getTypeDescAux(m, typ[i], check, skField), rope(i)])
if desc == nil: result.add("char dummy;\L")
else: result.add(desc)
result.add("};\L")
@@ -675,8 +689,22 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
result = if result.kind == tyGenericInst: result[1]
else: result.elemType
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
proc getOpenArrayDesc(m: BModule, t: PType, check: var IntSet; kind: TSymKind): Rope =
let sig = hashType(t)
if kind == skParam:
result = getTypeDescWeak(m, t[0], check, kind) & "*"
else:
result = cacheGetType(m.typeCache, sig)
if result == nil:
result = getTypeName(m, t, sig)
m.typeCache[sig] = result
let elemType = getTypeDescWeak(m, t[0], check, kind)
m.s[cfsTypes].addf("typedef struct {$n$2* Field0;$nNI Field1;$n} $1;$n",
[result, elemType])
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKind): Rope =
# returns only the type's name
var t = origTyp.skipTypes(irrelevantForBackend-{tyOwned})
if containsOrIncl(check, t.id):
if not (isImportedCppType(origTyp) or isImportedCppType(t)):
@@ -687,17 +715,22 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
if t.sym != nil: useHeader(m, t.sym)
if t != origTyp and origTyp.sym != nil: useHeader(m, origTyp.sym)
let sig = hashType(origTyp)
defer: # defer is the simplest in this case
if isImportedType(t) and not m.typeABICache.containsOrIncl(sig):
addAbiCheck(m, t, result)
result = getTypePre(m, t, sig)
if result != nil:
if result != nil and t.kind != tyOpenArray:
excl(check, t.id)
return
case t.kind
of tyRef, tyPtr, tyVar, tyLent:
var star = if t.kind == tyVar and tfVarIsPtr notin origTyp.flags and
var star = if t.kind in {tyVar} and tfVarIsPtr notin origTyp.flags and
compileToCpp(m): "&" else: "*"
var et = origTyp.skipTypes(abstractInst).lastSon
var etB = et.skipTypes(abstractInst)
if mapType(m.config, t) == ctPtrToArray:
if mapType(m.config, t, kind) == ctPtrToArray and (etB.kind != tyOpenArray or kind == skParam):
if etB.kind == tySet:
et = getSysType(m.g.graph, unknownLineInfo, tyUInt8)
else:
@@ -707,7 +740,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
case etB.kind
of tyObject, tyTuple:
if isImportedCppType(etB) and et.kind == tyGenericInst:
result = getTypeDescAux(m, et, check) & star
result = getTypeDescAux(m, et, check, kind) & star
else:
# no restriction! We have a forward declaration for structs
let name = getTypeForward(m, et, hashType et)
@@ -715,7 +748,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
m.typeCache[sig] = result
of tySequence:
if optSeqDestructors in m.config.globalOptions:
result = getTypeDescWeak(m, et, check) & star
result = getTypeDescWeak(m, et, check, kind) & star
m.typeCache[sig] = result
else:
# no restriction! We have a forward declaration for structs
@@ -725,11 +758,10 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
pushType(m, et)
else:
# else we have a strong dependency :-(
result = getTypeDescAux(m, et, check) & star
result = getTypeDescAux(m, et, check, kind) & star
m.typeCache[sig] = result
of tyOpenArray, tyVarargs:
result = getTypeDescWeak(m, t[0], check) & "*"
m.typeCache[sig] = result
result = getOpenArrayDesc(m, t, check, kind)
of tyEnum:
result = cacheGetType(m.typeCache, sig)
if result == nil:
@@ -775,7 +807,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
[result, rettype, desc])
of tySequence:
if optSeqDestructors in m.config.globalOptions:
result = getTypeDescWeak(m, t, check)
result = getTypeDescWeak(m, t, check, kind)
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:
@@ -796,11 +828,11 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
if m.compileToCpp:
appcg(m, m.s[cfsSeqTypes],
cppSeq & " $1 data[SEQ_DECL_SIZE];$n" &
"};$n", [getTypeDescAux(m, t[0], check), result])
"};$n", [getTypeDescAux(m, t[0], check, kind), result])
else:
appcg(m, m.s[cfsSeqTypes],
cSeq & " $1 data[SEQ_DECL_SIZE];$n" &
"};$n", [getTypeDescAux(m, t[0], check), result])
"};$n", [getTypeDescAux(m, t[0], check, kind), result])
else:
result = rope("TGenericSeq")
result.add(seqStar(m))
@@ -808,7 +840,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
result = getTypeName(m, origTyp, sig)
m.typeCache[sig] = result
if not isImportedType(t):
let foo = getTypeDescAux(m, t[0], check)
let foo = getTypeDescAux(m, t[0], check, kind)
m.s[cfsTypes].addf("typedef $1 $2[1];$n", [foo, result])
of tyArray:
var n: BiggestInt = toInt64(lengthOrd(m.config, t))
@@ -816,10 +848,9 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
result = getTypeName(m, origTyp, sig)
m.typeCache[sig] = result
if not isImportedType(t):
let foo = getTypeDescAux(m, t[1], check)
let foo = getTypeDescAux(m, t[1], check, kind)
m.s[cfsTypes].addf("typedef $1 $2[$3];$n",
[foo, result, rope(n)])
else: addAbiCheck(m, t, result)
of tyObject, tyTuple:
if isImportedCppType(t) and origTyp.kind == tyGenericInst:
let cppName = getTypeName(m, t, sig)
@@ -833,7 +864,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
internalAssert m.config, ty.n != nil
result.add ty.n.renderTree
else:
result.add getTypeDescAux(m, ty, check)
result.add getTypeDescAux(m, ty, check, kind)
while i < cppName.data.len:
if cppName.data[i] == '\'':
@@ -880,7 +911,8 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
else: getTupleDesc(m, t, result, check)
if not isImportedType(t):
m.s[cfsTypes].add(recdesc)
elif tfIncompleteStruct notin t.flags: addAbiCheck(m, t, result)
elif tfIncompleteStruct notin t.flags:
discard # addAbiCheck(m, t, result) # already handled elsewhere
of tySet:
# Don't use the imported name as it may be scoped: 'Foo::SomeKind'
result = $t.kind & '_' & t.lastSon.typeName & $t.lastSon.hashType
@@ -893,16 +925,16 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
[result, rope(getSize(m.config, t))])
of tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias, tySink, tyOwned,
tyUserTypeClass, tyUserTypeClassInst, tyInferred:
result = getTypeDescAux(m, lastSon(t), check)
result = getTypeDescAux(m, lastSon(t), check, kind)
else:
internalError(m.config, "getTypeDescAux(" & $t.kind & ')')
result = nil
# fixes bug #145:
excl(check, t.id)
proc getTypeDesc(m: BModule, typ: PType): Rope =
proc getTypeDesc(m: BModule, typ: PType; kind = skParam): Rope =
var check = initIntSet()
result = getTypeDescAux(m, typ, check)
result = getTypeDescAux(m, typ, check, kind)
type
TClosureTypeKind = enum ## In C closures are mapped to 3 different things.
@@ -934,8 +966,9 @@ proc finishTypeDescriptions(m: BModule) =
if optSeqDestructors in m.config.globalOptions and t.skipTypes(abstractInst).kind == tySequence:
seqV2ContentType(m, t, check)
else:
discard getTypeDescAux(m, t, check)
discard getTypeDescAux(m, t, check, skParam)
inc(i)
m.typeStack.setLen 0
template cgDeclFrmt*(s: PSym): string =
s.constraint.strVal
@@ -980,7 +1013,7 @@ proc genProcHeader(m: BModule, prc: PSym, asPtr: bool = false): Rope =
# ------------------ type info generation -------------------------------------
proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope
proc genTypeInfoV1(m: BModule, t: PType; info: TLineInfo): Rope
proc getNimNode(m: BModule): Rope =
result = "$1[$2]" % [m.typeNodesName, rope(m.typeNodes)]
inc(m.typeNodes)
@@ -1000,11 +1033,14 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
let nameHcr = tiNameForHcr(m, name)
var size: Rope
if tfIncompleteStruct in typ.flags: size = rope"void*"
else: size = getTypeDesc(m, origType)
if tfIncompleteStruct in typ.flags:
size = rope"void*"
else:
size = getTypeDesc(m, origType, skVar)
m.s[cfsTypeInit3].addf(
"$1.size = sizeof($2);$n" & "$1.kind = $3;$n" & "$1.base = $4;$n",
[nameHcr, size, rope(nimtypeKind), base])
"$1.size = sizeof($2);$n$1.align = NIM_ALIGNOF($2);$n$1.kind = $3;$n$1.base = $4;$n",
[nameHcr, size, rope(nimtypeKind), base]
)
# compute type flags for GC optimization
var flags = 0
if not containsGarbageCollectedRef(typ): flags = flags or 1
@@ -1040,7 +1076,7 @@ proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope;
if typ.kind == tyPtr and x.kind == tyObject and incompleteType(x):
base = rope("0")
else:
base = genTypeInfo(m, x, info)
base = genTypeInfoV1(m, x, info)
else:
base = rope("0")
genTypeInfoAuxBase(m, typ, origType, name, base, info)
@@ -1098,8 +1134,8 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
m.s[cfsTypeInit3].addf("$1.kind = 3;$n" &
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
"$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
"$1.len = $7;$n", [expr, getTypeDesc(m, origType), field.loc.r,
genTypeInfo(m, field.typ, info),
"$1.len = $7;$n", [expr, getTypeDesc(m, origType, skVar), field.loc.r,
genTypeInfoV1(m, field.typ, info),
makeCString(field.name.s),
tmp, rope(L)])
m.s[cfsData].addf("TNimNode* $1[$2];$n", [tmp, rope(L+1)])
@@ -1135,8 +1171,8 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
internalError(m.config, n.info, "genObjectFields")
m.s[cfsTypeInit3].addf("$1.kind = 1;$n" &
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
"$1.name = $5;$n", [expr, getTypeDesc(m, origType),
field.loc.r, genTypeInfo(m, field.typ, info), makeCString(field.name.s)])
"$1.name = $5;$n", [expr, getTypeDesc(m, origType, skVar),
field.loc.r, genTypeInfoV1(m, field.typ, info), makeCString(field.name.s)])
else: internalError(m.config, n.info, "genObjectFields")
proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo) =
@@ -1171,7 +1207,7 @@ proc genTupleInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo)
"$1.offset = offsetof($2, Field$3);$n" &
"$1.typ = $4;$n" &
"$1.name = \"Field$3\";$n",
[tmp2, getTypeDesc(m, origType), rope(i), genTypeInfo(m, a, info)])
[tmp2, getTypeDesc(m, origType, skVar), rope(i), genTypeInfoV1(m, a, info)])
m.s[cfsTypeInit3].addf("$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
[expr, rope(typ.len), tmp])
else:
@@ -1228,7 +1264,7 @@ proc genSetInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
[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[1], info), info)
genTypeInfoAuxBase(m, typ, typ, name, genTypeInfoV1(m, typ[1], info), info)
proc fakeClosureType(m: BModule; owner: PSym): PType =
# we generate the same RTTI as for a tuple[pointer, ref tuple[]]
@@ -1246,13 +1282,14 @@ proc genDeepCopyProc(m: BModule; s: PSym; result: Rope) =
m.s[cfsTypeInit3].addf("$1.deepcopy =(void* (N_RAW_NIMCALL*)(void*))$2;$n",
[result, s.loc.r])
proc declareNimType(m: BModule, str: Rope, ownerModule: PSym) =
proc declareNimType(m: BModule, name: string; str: Rope, ownerModule: PSym) =
let nr = rope(name)
if m.hcrOn:
m.s[cfsData].addf("static TNimType* $1;$n", [str])
m.s[cfsTypeInit1].addf("\t$1 = (TNimType*)hcrGetGlobal($2, \"$1\");$n",
[str, getModuleDllPath(m, ownerModule)])
m.s[cfsData].addf("static $2* $1;$n", [str, nr])
m.s[cfsTypeInit1].addf("\t$1 = ($3*)hcrGetGlobal($2, \"$1\");$n",
[str, getModuleDllPath(m, ownerModule), nr])
else:
m.s[cfsData].addf("extern TNimType $1;$n", [str])
m.s[cfsData].addf("extern $2 $1;$n", [str, nr])
proc genTypeInfo2Name(m: BModule; t: PType): Rope =
var res = "|"
@@ -1285,21 +1322,26 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
# 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:
if theProc.typ == nil or theProc.typ.callConv != ccDefault:
if theProc.typ == nil or theProc.typ.callConv != ccNimCall:
localError(m.config, info,
theProc.name.s & " needs to have the 'nimcall' calling convention")
genProc(m, theProc)
result = theProc.loc.r
when false:
if not canFormAcycle(t) and op == attachedTrace:
echo "ayclic but has this =trace ", t, " ", theProc.ast
else:
if op == attachedTrace and m.config.selectedGC == gcOrc and
containsGarbageCollectedRef(t):
when false:
# re-enable this check
when false:
if op == attachedTrace and m.config.selectedGC == gcOrc and
containsGarbageCollectedRef(t):
# unfortunately this check is wrong for an object type that only contains
# .cursor fields like 'Node' inside 'cycleleak'.
internalError(m.config, info, "no attached trace proc found")
result = rope("NIM_NIL")
proc genTypeInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo) =
proc genTypeInfoV2Impl(m: BModule, t, origType: PType, name: Rope; info: TLineInfo) =
var typeName: Rope
if t.kind == tyObject:
if incompleteType(t):
@@ -1309,20 +1351,68 @@ proc genTypeInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo)
else:
typeName = rope("NIM_NIL")
discard cgsym(m, "TNimType")
m.s[cfsData].addf("N_LIB_PRIVATE TNimType $1;$n", [name])
discard cgsym(m, "TNimTypeV2")
m.s[cfsData].addf("N_LIB_PRIVATE TNimTypeV2 $1;$n", [name])
let destroyImpl = genHook(m, t, info, attachedDestructor)
let traceImpl = genHook(m, t, info, attachedTrace)
let disposeImpl = genHook(m, t, info, attachedDispose)
m.s[cfsTypeInit3].addf("$1.destructor = (void*)$2; $1.size = sizeof($3);$n" &
"$1.name = $4;$n" &
"$1.traceImpl = (void*)$5;$n" &
"$1.disposeImpl = (void*)$6;$n", [
name, destroyImpl, getTypeDesc(m, t), typeName,
traceImpl, disposeImpl])
var flags = 0
if not canFormAcycle(t): flags = flags or 1
proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
addf(m.s[cfsTypeInit3], "$1.destructor = (void*)$2; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.name = $4;$n; $1.traceImpl = (void*)$5; $1.disposeImpl = (void*)$6; $1.flags = $7;", [
name, destroyImpl, getTypeDesc(m, t), typeName,
traceImpl, disposeImpl, rope(flags)])
if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions:
discard genTypeInfoV1(m, t, info)
proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
let origType = t
var t = skipTypes(origType, irrelevantForBackend + tyUserTypeClasses)
let prefixTI = if m.hcrOn: "(" else: "(&"
let sig = hashType(origType)
result = m.typeInfoMarkerV2.getOrDefault(sig)
if result != nil:
return prefixTI.rope & result & ")".rope
let marker = m.g.typeInfoMarkerV2.getOrDefault(sig)
if marker.str != nil:
discard cgsym(m, "TNimTypeV2")
declareNimType(m, "TNimTypeV2", marker.str, marker.owner)
# also store in local type section:
m.typeInfoMarkerV2[sig] = marker.str
return prefixTI.rope & marker.str & ")".rope
result = "NTIv2$1_" % [rope($sig)]
m.typeInfoMarkerV2[sig] = result
let owner = t.skipTypes(typedescPtrs).owner.getModule
if owner != m.module:
# make sure the type info is created in the owner module
assert m.g.modules[owner.position] != nil
discard genTypeInfoV2(m.g.modules[owner.position], origType, info)
# reference the type info as extern here
discard cgsym(m, "TNimTypeV2")
declareNimType(m, "TNimTypeV2", result, owner)
return prefixTI.rope & result & ")".rope
m.g.typeInfoMarkerV2[sig] = (str: result, owner: owner)
genTypeInfoV2Impl(m, t, origType, result, info)
result = prefixTI.rope & result & ")".rope
proc openArrayToTuple(m: BModule; t: PType): PType =
result = newType(tyTuple, t.owner)
let p = newType(tyPtr, t.owner)
let a = newType(tyUncheckedArray, t.owner)
a.add t.lastSon
p.add a
result.add p
result.add getSysType(m.g.graph, t.owner.info, tyInt)
proc genTypeInfoV1(m: BModule, t: PType; info: TLineInfo): Rope =
let origType = t
var t = skipTypes(origType, irrelevantForBackend + tyUserTypeClasses)
@@ -1337,7 +1427,7 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
if marker.str != nil:
discard cgsym(m, "TNimType")
discard cgsym(m, "TNimNode")
declareNimType(m, marker.str, marker.owner)
declareNimType(m, "TNimType", marker.str, marker.owner)
# also store in local type section:
m.typeInfoMarker[sig] = marker.str
return prefixTI.rope & marker.str & ")".rope
@@ -1349,63 +1439,68 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
if owner != m.module:
# make sure the type info is created in the owner module
assert m.g.modules[owner.position] != nil
discard genTypeInfo(m.g.modules[owner.position], origType, info)
discard genTypeInfoV1(m.g.modules[owner.position], origType, info)
# reference the type info as extern here
discard cgsym(m, "TNimType")
discard cgsym(m, "TNimNode")
declareNimType(m, result, owner)
declareNimType(m, "TNimType", result, owner)
return prefixTI.rope & result & ")".rope
m.g.typeInfoMarker[sig] = (str: result, owner: owner)
if optTinyRtti in m.config.globalOptions:
genTypeInfoV2(m, t, origType, result, info)
else:
case t.kind
of tyEmpty, tyVoid: result = rope"0"
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar, tyLent:
case t.kind
of tyEmpty, tyVoid: result = rope"0"
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar, tyLent:
genTypeInfoAuxBase(m, t, t, result, rope"0", info)
of tyStatic:
if t.n != nil: result = genTypeInfoV1(m, lastSon t, info)
else: internalError(m.config, "genTypeInfoV1(" & $t.kind & ')')
of tyUserTypeClasses:
internalAssert m.config, t.isResolvedUserTypeClass
return genTypeInfoV1(m, t.lastSon, info)
of tyProc:
if t.callConv != ccClosure:
genTypeInfoAuxBase(m, t, t, result, rope"0", info)
of tyStatic:
if t.n != nil: result = genTypeInfo(m, lastSon t, info)
else: internalError(m.config, "genTypeInfo(" & $t.kind & ')')
of tyUserTypeClasses:
internalAssert m.config, t.isResolvedUserTypeClass
return genTypeInfo(m, t.lastSon, info)
of tyProc:
if t.callConv != ccClosure:
genTypeInfoAuxBase(m, t, t, result, rope"0", info)
else:
let x = fakeClosureType(m, t.owner)
genTupleInfo(m, x, x, result, info)
of tySequence:
genTypeInfoAux(m, t, t, result, info)
if optSeqDestructors notin m.config.globalOptions:
if m.config.selectedGC >= gcMarkAndSweep:
let markerProc = genTraverseProc(m, origType, sig)
m.s[cfsTypeInit3].addf("$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
of tyRef:
genTypeInfoAux(m, t, t, result, info)
if m.config.selectedGC >= gcMarkAndSweep:
let markerProc = genTraverseProc(m, origType, sig)
m.s[cfsTypeInit3].addf("$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
of tyPtr, tyRange, tyUncheckedArray: genTypeInfoAux(m, t, t, result, info)
of tyArray: genArrayInfo(m, t, result, info)
of tySet: genSetInfo(m, t, result, info)
of tyEnum: genEnumInfo(m, t, result, info)
of tyObject:
genObjectInfo(m, t, origType, result, info)
of tyTuple:
# if t.n != nil: genObjectInfo(m, t, result)
# else:
# BUGFIX: use consistently RTTI without proper field names; otherwise
# results are not deterministic!
genTupleInfo(m, t, origType, result, info)
else: internalError(m.config, "genTypeInfo(" & $t.kind & ')')
else:
let x = fakeClosureType(m, t.owner)
genTupleInfo(m, x, x, result, info)
of tySequence:
genTypeInfoAux(m, t, t, result, info)
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcV2, gcGo}:
let markerProc = genTraverseProc(m, origType, sig)
m.s[cfsTypeInit3].addf("$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
of tyRef:
genTypeInfoAux(m, t, t, result, info)
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcV2, gcGo}:
let markerProc = genTraverseProc(m, origType, sig)
m.s[cfsTypeInit3].addf("$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
of tyPtr, tyRange, tyUncheckedArray: genTypeInfoAux(m, t, t, result, info)
of tyArray: genArrayInfo(m, t, result, info)
of tySet: genSetInfo(m, t, result, info)
of tyEnum: genEnumInfo(m, t, result, info)
of tyObject:
genObjectInfo(m, t, origType, result, info)
of tyTuple:
# if t.n != nil: genObjectInfo(m, t, result)
# else:
# BUGFIX: use consistently RTTI without proper field names; otherwise
# results are not deterministic!
genTupleInfo(m, t, origType, result, info)
of tyOpenArray:
let x = openArrayToTuple(m, t)
genTupleInfo(m, x, origType, result, info)
else: internalError(m.config, "genTypeInfoV1(" & $t.kind & ')')
if t.attachedOps[attachedDeepCopy] != nil:
genDeepCopyProc(m, t.attachedOps[attachedDeepCopy], result)
elif origType.attachedOps[attachedDeepCopy] != nil:
genDeepCopyProc(m, origType.attachedOps[attachedDeepCopy], result)
if optTinyRtti in m.config.globalOptions and t.kind == tyObject and sfImportc notin t.sym.flags:
let v2info = genTypeInfoV2(m, origType, info)
addf(m.s[cfsTypeInit3], "$1->typeInfoV1 = (void*)&$2; $2.typeInfoV2 = (void*)$1;$n", [
v2info, result])
result = prefixTI.rope & result & ")".rope
proc genTypeSection(m: BModule, n: PNode) =

View File

@@ -279,7 +279,7 @@ proc genProc(m: BModule, prc: PSym)
proc raiseInstr(p: BProc): Rope
template compileToCpp(m: BModule): untyped =
m.config.cmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags
m.config.backend == backendCpp or sfCompileToCpp in m.module.flags
proc getTempName(m: BModule): Rope =
result = m.tmpBase & rope(m.labels)
@@ -310,14 +310,19 @@ include ccgtypes
# ------------------------------ Manager of temporaries ------------------
template mapTypeChooser(n: PNode): TSymKind =
(if n.kind == nkSym: n.sym.kind else: skVar)
template mapTypeChooser(a: TLoc): TSymKind = mapTypeChooser(a.lode)
proc addrLoc(conf: ConfigRef; a: TLoc): Rope =
result = a.r
if lfIndirect notin a.flags and mapType(conf, a.t) != ctArray:
if lfIndirect notin a.flags and mapType(conf, a.t, mapTypeChooser(a)) != ctArray:
result = "(&" & result & ")"
proc byRefLoc(p: BProc; a: TLoc): Rope =
result = a.r
if lfIndirect notin a.flags and mapType(p.config, a.t) != ctArray and not
if lfIndirect notin a.flags and mapType(p.config, a.t, mapTypeChooser(a)) != ctArray and not
p.module.compileToCpp:
result = "(&" & result & ")"
@@ -355,7 +360,10 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
while s.kind == tyObject and s[0] != nil:
r.add(".Sup")
s = skipTypes(s[0], skipPtrs)
linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t, a.lode.info)])
if optTinyRtti in p.config.globalOptions:
linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfoV2(p.module, t, a.lode.info)])
else:
linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfoV1(p.module, t, a.lode.info)])
of frEmbedded:
if optTinyRtti in p.config.globalOptions:
var tmp: TLoc
@@ -364,14 +372,14 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
rawConstExpr(p, newNodeIT(nkType, a.lode.info, objType), tmp)
linefmt(p, cpsStmts,
"#nimCopyMem((void*)$1, (NIM_CONST void*)&$2, sizeof($3));$n",
[rdLoc(a), rdLoc(tmp), getTypeDesc(p.module, objType)])
[rdLoc(a), rdLoc(tmp), getTypeDesc(p.module, objType, mapTypeChooser(a))])
else:
rawConstExpr(p, newNodeIT(nkType, a.lode.info, t), tmp)
genAssignment(p, a, tmp, {})
else:
# worst case for performance:
var r = if mode == constructObj: addrLoc(p.config, a) else: rdLoc(a)
linefmt(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t, a.lode.info)])
linefmt(p, section, "#objectInit($1, $2);$n", [r, genTypeInfoV1(p.module, t, a.lode.info)])
if isException(t):
var r = rdLoc(a)
@@ -387,7 +395,7 @@ proc genRefAssign(p: BProc, dest, src: TLoc)
proc isComplexValueType(t: PType): bool {.inline.} =
let t = t.skipTypes(abstractInst + tyUserTypeClasses)
result = t.kind in {tyArray, tySet, tyTuple, tyObject} or
result = t.kind in {tyArray, tySet, tyTuple, tyObject, tyOpenArray} or
(t.kind == tyProc and t.callConv == ccClosure)
include ccgreset
@@ -408,13 +416,11 @@ proc resetLoc(p: BProc, loc: var TLoc) =
else:
linefmt(p, cpsStmts, "$1 = 0;$n", [rdLoc(loc)])
else:
if optNilCheck in p.options:
linefmt(p, cpsStmts, "#chckNil((void*)$1);$n", [addrLoc(p.config, loc)])
if loc.storage != OnStack and containsGcRef:
specializeReset(p, loc)
when false:
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
[addrLoc(p.config, loc), genTypeInfo(p.module, loc.t, loc.lode.info)])
[addrLoc(p.config, loc), genTypeInfoV1(p.module, loc.t, loc.lode.info)])
# XXX: generated reset procs should not touch the m_type
# field, so disabling this should be safe:
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
@@ -422,7 +428,8 @@ proc resetLoc(p: BProc, loc: var TLoc) =
# array passed as argument decayed into pointer, bug #7332
# so we use getTypeDesc here rather than rdLoc(loc)
linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
[addrLoc(p.config, loc), getTypeDesc(p.module, loc.t)])
[addrLoc(p.config, loc),
getTypeDesc(p.module, loc.t, mapTypeChooser(loc))])
# XXX: We can be extra clever here and call memset only
# on the bytes following the m_type field?
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
@@ -439,14 +446,14 @@ proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
genRefAssign(p, loc, nilLoc)
else:
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
getTypeDesc(p.module, typ)])
getTypeDesc(p.module, typ, mapTypeChooser(loc))])
else:
if not isTemp or containsGarbageCollectedRef(loc.t):
# don't use nimZeroMem for temporary values for performance if we can
# avoid it:
if not isImportedCppType(typ):
linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
[addrLoc(p.config, loc), getTypeDesc(p.module, typ)])
[addrLoc(p.config, loc), getTypeDesc(p.module, typ, mapTypeChooser(loc))])
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
@@ -464,17 +471,25 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
inc(p.labels)
result.r = "T" & rope(p.labels) & "_"
linefmt(p, cpsLocals, "$1 $2;$n", [getTypeDesc(p.module, t), result.r])
linefmt(p, cpsLocals, "$1 $2;$n", [getTypeDesc(p.module, t, skVar), result.r])
result.k = locTemp
result.lode = lodeTyp t
result.storage = OnStack
result.flags = {}
constructLoc(p, result, not needsInit)
when false:
# XXX Introduce a compiler switch in order to detect these easily.
if getSize(p.config, t) > 1024 * 1024:
if p.prc != nil:
echo "ENORMOUS TEMPORARY! ", p.config $ p.prc.info
else:
echo "ENORMOUS TEMPORARY! ", p.config $ p.lastLineInfo
writeStackTrace()
proc getTempCpp(p: BProc, t: PType, result: var TLoc; value: Rope) =
inc(p.labels)
result.r = "T" & rope(p.labels) & "_"
linefmt(p, cpsStmts, "$1 $2 = $3;$n", [getTypeDesc(p.module, t), result.r, value])
linefmt(p, cpsStmts, "$1 $2 = $3;$n", [getTypeDesc(p.module, t, skVar), result.r, value])
result.k = locTemp
result.lode = lodeTyp t
result.storage = OnStack
@@ -496,12 +511,13 @@ proc localVarDecl(p: BProc; n: PNode): Rope =
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
result.addf("NIM_ALIGN($1) ", [rope(s.alignment)])
result.add getTypeDesc(p.module, s.typ)
result.add getTypeDesc(p.module, s.typ, skVar)
if s.constraint.isNil:
if sfRegister in s.flags: result.add(" register")
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
# decl.add(" GC_GUARD")
if sfVolatile in s.flags: result.add(" volatile")
if sfNoalias in s.flags: result.add(" NIM_NOALIAS")
result.add(" ")
result.add(s.loc.r)
else:
@@ -549,7 +565,7 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
internalError(p.config, n.info, ".threadvar variables cannot have a value")
else:
var decl: Rope = nil
var td = getTypeDesc(p.module, s.loc.t)
var td = getTypeDesc(p.module, s.loc.t, skVar)
if s.constraint.isNil:
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
decl.addf "NIM_ALIGN($1) ", [rope(s.alignment)]
@@ -562,6 +578,7 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
if p.hcrOn: decl.add("*")
if sfRegister in s.flags: decl.add(" register")
if sfVolatile in s.flags: decl.add(" volatile")
if sfNoalias in s.flags: decl.add(" NIM_NOALIAS")
if value != nil:
decl.addf(" $1 = $2;$n", [s.loc.r, value])
else:
@@ -689,13 +706,13 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
[loadlib, genStringLiteral(m, lib.path)])
else:
var p = newProc(nil, m)
p.options = p.options - {optStackTrace}
p.options.excl optStackTrace
p.flags.incl nimErrorFlagDisabled
var dest: TLoc
initLoc(dest, locTemp, lib.path, OnStack)
dest.r = getTempName(m)
appcg(m, m.s[cfsDynLibInit],"$1 $2;$n",
[getTypeDesc(m, lib.path.typ), rdLoc(dest)])
[getTypeDesc(m, lib.path.typ, skVar), rdLoc(dest)])
expr(p, lib.path, dest)
m.s[cfsVars].add(p.s(cpsLocals))
@@ -735,7 +752,7 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
params.add(rdLoc(a))
params.add(", ")
let load = "\t$1 = ($2) ($3$4));$n" %
[tmp, getTypeDesc(m, sym.typ), params, makeCString($extname)]
[tmp, getTypeDesc(m, sym.typ, skVar), params, makeCString($extname)]
var last = lastSon(n)
if last.kind == nkHiddenStdConv: last = last[1]
internalAssert(m.config, last.kind == nkStrLit)
@@ -749,8 +766,8 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
else:
appcg(m, m.s[cfsDynLibInit],
"\t$1 = ($2) #nimGetProcAddr($3, $4);$n",
[tmp, getTypeDesc(m, sym.typ), lib.name, makeCString($extname)])
m.s[cfsVars].addf("$2 $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t)])
[tmp, getTypeDesc(m, sym.typ, skVar), lib.name, makeCString($extname)])
m.s[cfsVars].addf("$2 $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t, skVar)])
proc varInDynamicLib(m: BModule, sym: PSym) =
var lib = sym.annex
@@ -762,9 +779,9 @@ proc varInDynamicLib(m: BModule, sym: PSym) =
inc(m.labels, 2)
appcg(m, m.s[cfsDynLibInit],
"$1 = ($2*) #nimGetProcAddr($3, $4);$n",
[tmp, getTypeDesc(m, sym.typ), lib.name, makeCString($extname)])
[tmp, getTypeDesc(m, sym.typ, skVar), lib.name, makeCString($extname)])
m.s[cfsVars].addf("$2* $1;$n",
[sym.loc.r, getTypeDesc(m, sym.loc.t)])
[sym.loc.r, getTypeDesc(m, sym.loc.t, skVar)])
proc symInDynamicLibPartial(m: BModule, sym: PSym) =
sym.loc.r = mangleDynLibProc(sym)
@@ -1083,11 +1100,11 @@ proc genProcAux(m: BModule, prc: PSym) =
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 (
m.config.backend != backendCpp) or (
sym.flags * {sfInfixCall, sfCompilerProc, sfMangleCpp} == {} and
sym.flags * {sfImportc, sfExportc} != {} and
sym.magic == mNone and
m.config.cmd == cmdCompileToCpp)
m.config.backend == backendCpp)
proc genProcPrototype(m: BModule, sym: PSym) =
useHeader(m, sym)
@@ -1183,21 +1200,44 @@ proc requestConstImpl(p: BProc, sym: PSym) =
useHeader(m, sym)
if sym.loc.k == locNone:
fillLoc(sym.loc, locData, sym.ast, mangleName(p.module, sym), OnStatic)
if m.hcrOn: incl(sym.loc.flags, lfIndirect)
if lfNoDecl in sym.loc.flags: return
# declare implementation:
var q = findPendingModule(m, sym)
if q != nil and not containsOrIncl(q.declaredThings, sym.id):
assert q.initProc.module == q
# add a suffix for hcr - will later init the global pointer with this data
let actualConstName = if m.hcrOn: sym.loc.r & "_const" else: sym.loc.r
q.s[cfsData].addf("N_LIB_PRIVATE NIM_CONST $1 $2 = $3;$n",
[getTypeDesc(q, sym.typ), sym.loc.r, genBracedInit(q.initProc, sym.ast, isConst = true)])
[getTypeDesc(q, sym.typ), actualConstName,
genBracedInit(q.initProc, sym.ast, isConst = true, sym.typ)])
if m.hcrOn:
# generate the global pointer with the real name
q.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(m, sym.loc.t, skVar), sym.loc.r])
# register it (but ignore the boolean result of hcrRegisterGlobal)
q.initProc.procSec(cpsLocals).addf(
"\thcrRegisterGlobal($1, \"$2\", sizeof($3), NULL, (void**)&$2);$n",
[getModuleDllPath(q, sym), sym.loc.r, rdLoc(sym.loc)])
# always copy over the contents of the actual constant with the _const
# suffix ==> this means that the constant is reloadable & updatable!
q.initProc.procSec(cpsLocals).add(ropecg(q,
"\t#nimCopyMem((void*)$1, (NIM_CONST void*)&$2, sizeof($3));$n",
[sym.loc.r, actualConstName, rdLoc(sym.loc)]))
# declare header:
if q != m and not containsOrIncl(m.declaredThings, sym.id):
assert(sym.loc.r != nil)
let headerDecl = "extern NIM_CONST $1 $2;$n" %
[getTypeDesc(m, sym.loc.t), sym.loc.r]
m.s[cfsData].add(headerDecl)
if sfExportc in sym.flags and p.module.g.generatedHeader != nil:
p.module.g.generatedHeader.s[cfsData].add(headerDecl)
if m.hcrOn:
m.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(m, sym.loc.t, skVar), sym.loc.r]);
m.initProc.procSec(cpsLocals).addf(
"\t$1 = ($2*)hcrGetGlobal($3, \"$1\");$n", [sym.loc.r,
getTypeDesc(m, sym.loc.t, skVar), getModuleDllPath(q, sym)])
else:
let headerDecl = "extern NIM_CONST $1 $2;$n" %
[getTypeDesc(m, sym.loc.t, skVar), sym.loc.r]
m.s[cfsData].add(headerDecl)
if sfExportc in sym.flags and p.module.g.generatedHeader != nil:
p.module.g.generatedHeader.s[cfsData].add(headerDecl)
proc isActivated(prc: PSym): bool = prc.typ != nil
@@ -1234,15 +1274,16 @@ proc genVarPrototype(m: BModule, n: PNode) =
if sym.kind in {skLet, skVar, skField, skForVar} and sym.alignment > 0:
m.s[cfsVars].addf "NIM_ALIGN($1) ", [rope(sym.alignment)]
m.s[cfsVars].add(if m.hcrOn: "static " else: "extern ")
m.s[cfsVars].add(getTypeDesc(m, sym.loc.t))
m.s[cfsVars].add(getTypeDesc(m, sym.loc.t, skVar))
if m.hcrOn: m.s[cfsVars].add("*")
if lfDynamicLib in sym.loc.flags: m.s[cfsVars].add("*")
if sfRegister in sym.flags: m.s[cfsVars].add(" register")
if sfVolatile in sym.flags: m.s[cfsVars].add(" volatile")
if sfNoalias in sym.flags: m.s[cfsVars].add(" NIM_NOALIAS")
m.s[cfsVars].addf(" $1;$n", [sym.loc.r])
if m.hcrOn: m.initProc.procSec(cpsLocals).addf(
"\t$1 = ($2*)hcrGetGlobal($3, \"$1\");$n", [sym.loc.r,
getTypeDesc(m, sym.loc.t), getModuleDllPath(m, sym)])
getTypeDesc(m, sym.loc.t, skVar), getModuleDllPath(m, sym)])
proc addNimDefines(result: var Rope; conf: ConfigRef) {.inline.} =
result.addf("#define NIM_INTBITS $1\L", [
@@ -1548,7 +1589,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
if sfSystemModule in m.module.flags:
if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone:
g.mainDatInit.add(ropecg(m, "\t#initThreadVarsEmulation();$N", []))
if m.config.target.targetOS != osStandalone and m.config.selectedGC != gcNone:
if m.config.target.targetOS != osStandalone and m.config.selectedGC notin {gcNone, gcArc, gcOrc}:
g.mainDatInit.add(ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", []))
if m.s[cfsInitProc].len > 0:
@@ -1600,10 +1641,10 @@ proc hcrGetProcLoadCode(m: BModule, sym, prefix, handle, getProcFunc: string): R
prc.typ.sym = nil
if not containsOrIncl(m.declaredThings, prc.id):
m.s[cfsVars].addf("static $2 $1;$n", [prc.loc.r, getTypeDesc(m, prc.loc.t)])
m.s[cfsVars].addf("static $2 $1;$n", [prc.loc.r, getTypeDesc(m, prc.loc.t, skVar)])
result = "\t$1 = ($2) $3($4, $5);$n" %
[tmp, getTypeDesc(m, prc.typ), getProcFunc.rope, handle.rope, makeCString(prefix & sym)]
[tmp, getTypeDesc(m, prc.typ, skVar), getProcFunc.rope, handle.rope, makeCString(prefix & sym)]
proc genInitCode(m: BModule) =
## this function is called in cgenWriteModules after all modules are closed,
@@ -1653,6 +1694,10 @@ proc genInitCode(m: BModule) =
writeSection(preInitProc, cpsInit, m.hcrOn)
writeSection(preInitProc, cpsStmts)
prc.addf("}/* preInitProc end */$N", [])
when false:
m.initProc.blocks[0].sections[cpsLocals].add m.preInitProc.s(cpsLocals)
m.initProc.blocks[0].sections[cpsInit].prepend m.preInitProc.s(cpsInit)
m.initProc.blocks[0].sections[cpsStmts].prepend m.preInitProc.s(cpsStmts)
# add new scope for following code, because old vcc compiler need variable
# be defined at the top of the block
@@ -1764,11 +1809,6 @@ proc genModule(m: BModule, cfile: Cfile): Rope =
if moduleIsEmpty:
result = nil
proc newPreInitProc(m: BModule): BProc =
result = newProc(nil, m)
# little hack so that unique temporaries are generated:
result.labels = 100_000
proc initProcOptions(m: BModule): TOptions =
let opts = m.config.options
if sfSystemModule in m.module.flags: opts-{optStackTrace} else: opts
@@ -1789,7 +1829,9 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: AbsoluteFile): BModule
result.sigConflicts = initCountTable[SigHash]()
result.initProc = newProc(nil, result)
result.initProc.options = initProcOptions(result)
result.preInitProc = newPreInitProc(result)
result.preInitProc = newProc(nil, result)
result.preInitProc.flags.incl nimErrorFlagDisabled
result.preInitProc.labels = 100_000 # little hack so that unique temporaries are generated
initNodeTable(result.dataCache)
result.typeStack = @[]
result.typeNodesName = getTempName(result)
@@ -1819,7 +1861,10 @@ template injectG() {.dirty.} =
graph.backend = newModuleList(graph)
let g = BModuleList(graph.backend)
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
when not defined(nimHasSinkInference):
{.pragma: nosinks.}
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} =
injectG()
result = newModule(g, module, graph.config)
if optGenIndex in graph.config.globalOptions and g.generatedHeader == nil:
@@ -1859,7 +1904,7 @@ 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.backend == backendObjc or sfCompileToObjc in m.module.flags: ".nim.m"
else: ".nim.c"
result = changeFileExt(completeCfilePath(m.config, withPackageName(m.config, m.cfilename)), ext)
@@ -2014,7 +2059,7 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
if m.config.exc == excGoto and getCompilerProc(graph, "nimTestErrorFlag") != nil:
discard cgsym(m, "nimTestErrorFlag")
if {optGenStaticLib, optGenDynLib} * m.config.globalOptions == {}:
if {optGenStaticLib, optGenDynLib, optNoMain} * m.config.globalOptions == {}:
for i in countdown(high(graph.globalDestructors), 0):
n.add graph.globalDestructors[i]
if passes.skipCodegen(m.config, n): return
@@ -2055,7 +2100,8 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
let disp = generateMethodDispatchers(graph)
for x in disp: genProcAux(m, x.sym)
m.g.modulesClosed.add m
let mm = m
m.g.modulesClosed.add mm
proc genForwardedProcs(g: BModuleList) =
# Forward declared proc:s lack bodies when first encountered, so they're given

View File

@@ -11,7 +11,7 @@
import
ast, ropes, options, intsets,
tables, ndi, lineinfos, pathutils, modulegraphs
tables, ndi, lineinfos, pathutils, modulegraphs, sets
type
TLabel* = Rope # for the C generator a label is just a rope
@@ -25,7 +25,7 @@ type
# this is needed for strange type generation
# reasons
cfsFieldInfo, # section for field information
cfsTypeInfo, # section for type information
cfsTypeInfo, # section for type information (ag ABI checks)
cfsProcHeaders, # section for C procs prototypes
cfsData, # section for C constant data
cfsVars, # section for C variable declarations
@@ -97,6 +97,7 @@ type
# requires 'T x = T()' to become 'T x; x = T()'
# (yes, C++ is weird like that)
withinTryWithExcept*: int # required for goto based exception handling
withinBlockLeaveActions*: int # complex to explain
sigConflicts*: CountTable[string]
TTypeSeq* = seq[PType]
@@ -121,6 +122,7 @@ type
forwardedProcs*: seq[PSym] # proc:s that did not yet have a body
generatedHeader*: BModule
typeInfoMarker*: TypeCacheWithOwner
typeInfoMarkerV2*: TypeCacheWithOwner
config*: ConfigRef
graph*: ModuleGraph
strVersion*, seqVersion*: int # version of the string/seq implementation to use
@@ -145,11 +147,16 @@ type
# without extension)
tmpBase*: Rope # base for temp identifier generation
typeCache*: TypeCache # cache the generated types
typeABICache*: HashSet[SigHash] # cache for ABI checks; reusing typeCache
# would be ideal but for some reason enums
# don't seem to get cached so it'd generate
# 1 ABI check per occurence in code
forwTypeCache*: TypeCache # cache for forward declarations of types
declaredThings*: IntSet # things we have declared in this .c file
declaredProtos*: IntSet # prototypes we have declared in this .c file
headerFiles*: seq[string] # needed headers to include
typeInfoMarker*: TypeCache # needed for generating type information
typeInfoMarkerV2*: TypeCache
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
@@ -185,8 +192,8 @@ proc newProc*(prc: PSym, module: BModule): BProc =
new(result)
result.prc = prc
result.module = module
if prc != nil: result.options = prc.options
else: result.options = module.config.options
result.options = if prc != nil: prc.options
else: module.config.options
newSeq(result.blocks, 1)
result.nestedTryStmts = @[]
result.finallySafePoints = @[]

View File

@@ -113,7 +113,7 @@ proc createDispatcher(s: PSym): PSym =
excl(disp.flags, sfExported)
disp.typ = copyType(disp.typ, disp.typ.owner, false)
# we can't inline the dispatcher itself (for now):
if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
if disp.typ.callConv == ccInline: disp.typ.callConv = ccNimCall
disp.ast = copyTree(s.ast)
disp.ast[bodyPos] = newNodeI(nkEmpty, s.info)
disp.loc.r = nil

View File

@@ -392,6 +392,10 @@ proc hasYieldsInExpressions(n: PNode): bool =
return true
else:
result = n.hasYields
of nkCast:
for i in 1..<n.len:
if n[i].hasYieldsInExpressions:
return true
else:
for c in n:
if c.hasYieldsInExpressions:
@@ -485,7 +489,6 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
if ns:
needsSplit = true
var tmp: PSym
var s: PNode
let isExpr = not isEmptyType(n.typ)
if isExpr:
tmp = ctx.newTempVar(n.typ)
@@ -604,6 +607,12 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
internalError(ctx.g.config, "lowerStmtListExpr(nkCaseStmt): " & $branch.kind)
result.add(n)
result.add(ctx.newEnvVarAccess(tmp))
elif n[0].kind == nkStmtListExpr:
result = newNodeI(nkStmtList, n.info)
let (st, ex) = exprToStmtList(n[0])
result.add(st)
n[0] = ex
result.add(n)
of nkCallKinds, nkChckRange, nkChckRangeF, nkChckRange64:
var ns = false
@@ -690,7 +699,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv,
nkDerefExpr, nkHiddenDeref:
var ns = false
for i in 0..<n.len:
for i in ord(n.kind == nkCast)..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -742,8 +751,6 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
result.add(n)
of nkWhileStmt:
var ns = false
var condNeedsSplit = false
n[0] = ctx.lowerStmtListExprs(n[0], condNeedsSplit)
var bodyNeedsSplit = false

View File

@@ -7,20 +7,33 @@
# distribution, for details about the copyright.
#
## Helpers for binaries that use compiler passes, eg: nim, nimsuggest, nimfix
## Helpers for binaries that use compiler passes, e.g.: nim, nimsuggest, nimfix
import
options, idents, nimconf, extccomp, commands, msgs,
lineinfos, modulegraphs, condsyms, os, pathutils
lineinfos, modulegraphs, condsyms, os, pathutils, parseopt
from strutils import normalize
proc prependCurDir*(f: AbsoluteFile): AbsoluteFile =
when defined(unix):
if os.isAbsolute(f.string): result = f
else: result = AbsoluteFile("./" & f.string)
else:
result = f
proc addCmdPrefix*(result: var string, kind: CmdLineKind) =
# consider moving this to std/parseopt
case kind
of cmdLongOption: result.add "--"
of cmdShortOption: result.add "-"
of cmdArgument, cmdEnd: discard
type
NimProg* = ref object
suggestMode*: bool
supportsStdinFile*: bool
processCmdLine*: proc(pass: TCmdLinePass, cmd: string; config: ConfigRef)
mainCommand*: proc(graph: ModuleGraph)
proc initDefinesProg*(self: NimProg, conf: ConfigRef, name: string) =
condsyms.initDefines(conf.symbols)
@@ -42,37 +55,28 @@ proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) =
else:
conf.projectPath = AbsoluteDir canonicalizePath(conf, AbsoluteFile getCurrentDir())
proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: ConfigRef): bool =
proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: ConfigRef;
graph: ModuleGraph): bool =
if self.suggestMode:
conf.command = "nimsuggest"
loadConfigs(DefaultConfig, cache, conf) # load all config files
block:
if not self.suggestMode:
let scriptFile = conf.projectFull.changeFileExt("nims")
if not self.suggestMode:
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
if fileExists(scriptFile) and scriptFile == conf.projectFull:
if conf.command == "":
conf.command = "e"
return false
elif conf.command.normalize == "e":
return false
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
if fileExists(scriptFile) and scriptFile == conf.projectFull:
if conf.command == "":
conf.command = "e"
return false
elif conf.command.normalize == "e":
return false
# now process command line arguments again, because some options in the
# command line can overwrite the config file's settings
extccomp.initVars(conf)
# XXX This is hacky. We need to find a better way.
case conf.command
of "cpp", "compiletocpp":
conf.cmd = cmdCompileToCpp
else:
discard
self.processCmdLine(passCmd2, "", conf)
if conf.command == "":
rawMessage(conf, errGenerated, "command missing")
let graph = newModuleGraph(cache, conf)
graph.suggestMode = self.suggestMode
self.mainCommand(graph)
return true

View File

@@ -53,15 +53,14 @@ const
"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
result = ""
for f in T:
if result.len > 0: result.add "|"
result.add $f
const
Usage = slurp"../doc/basicopt.txt".replace(" //", " ")
AdvancedUsage = slurp"../doc/advopt.txt".replace(" //", " ") % [genFeatureDesc(Feature), genFeatureDesc(LegacyFeature)]
Usage = slurp"../doc/basicopt.txt".replace(" //", " ")
AdvancedUsage = slurp"../doc/advopt.txt".replace(" //", " ") % [genFeatureDesc(Feature), genFeatureDesc(LegacyFeature)]
proc getCommandLineDesc(conf: ConfigRef): string =
result = (HelpMessage % [VersionAsString, platform.OS[conf.target.hostOS].name,
@@ -98,7 +97,7 @@ proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) =
CPU[conf.target.hostCPU].name, CompileDate]),
{msgStdout})
const gitHash = gorge("git log -n 1 --format=%H").strip
const gitHash {.strdefine.} = gorge("git log -n 1 --format=%H").strip
when gitHash.len == 40:
msgWriteln(conf, "git hash: " & gitHash, {msgStdout})
@@ -146,24 +145,24 @@ proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TC
proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
info: TLineInfo) =
case arg.normalize
of "","on": conf.options = conf.options + op
of "off": conf.options = conf.options - op
of "", "on": conf.options.incl op
of "off": conf.options.excl op
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
proc processOnOffSwitchOrList(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
info: TLineInfo): bool =
result = false
case arg.normalize
of "on": conf.options = conf.options + op
of "off": conf.options = conf.options - op
of "on": conf.options.incl op
of "off": conf.options.excl op
of "list": result = true
else: localError(conf, info, errOnOffOrListExpectedButXFound % arg)
proc processOnOffSwitchG(conf: ConfigRef; op: TGlobalOptions, arg: string, pass: TCmdLinePass,
info: TLineInfo) =
case arg.normalize
of "", "on": conf.globalOptions = conf.globalOptions + op
of "off": conf.globalOptions = conf.globalOptions - op
of "", "on": conf.globalOptions.incl op
of "off": conf.globalOptions.excl op
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
proc expectArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
@@ -176,7 +175,7 @@ proc expectNoArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info:
proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
info: TLineInfo; orig: string; conf: ConfigRef) =
var id = "" # arg = key:val or [key]:val; with val=on|off
var id = "" # arg = key or [key] or key:val or [key]:val; with val=on|off
var i = 0
var n = hintMin
var isBracket = false
@@ -190,18 +189,20 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
if i < arg.len and arg[i] == ']': inc(i)
else: invalidCmdLineOption(conf, pass, orig, info)
if i < arg.len and (arg[i] in {':', '='}): inc(i)
if i == arg.len: discard
elif i < arg.len and (arg[i] in {':', '='}): inc(i)
else: invalidCmdLineOption(conf, pass, orig, info)
if state == wHint:
let x = findStr(lineinfos.HintsToStr, id)
if x >= 0: n = TNoteKind(x + ord(hintMin))
let x = findStr(hintMin..hintMax, id, errUnknown)
if x != errUnknown: n = TNoteKind(x)
else: localError(conf, info, "unknown hint: " & id)
else:
let x = findStr(lineinfos.WarningsToStr, id)
if x >= 0: n = TNoteKind(x + ord(warnMin))
let x = findStr(warnMin..warnMax, id, errUnknown)
if x != errUnknown: n = TNoteKind(x)
else: localError(conf, info, "unknown warning: " & id)
let val = substr(arg, i).normalize
var val = substr(arg, i).normalize
if val == "": val = "on"
if val notin ["on", "off"]:
localError(conf, info, errOnOrOffExpectedButXFound % arg)
elif n notin conf.cmdlineNotes or pass == passCmd1:
@@ -209,12 +210,18 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
incl(conf.modifiedyNotes, n)
case val
of "on":
incl(conf.notes, n)
incl(conf.mainPackageNotes, n)
if state == wWarningAsError:
incl(conf.warningAsErrors, n)
else:
incl(conf.notes, n)
incl(conf.mainPackageNotes, n)
of "off":
excl(conf.notes, n)
excl(conf.mainPackageNotes, n)
excl(conf.foreignPackageNotes, n)
if state == wWarningAsError:
excl(conf.warningAsErrors, n)
else:
excl(conf.notes, n)
excl(conf.mainPackageNotes, n)
excl(conf.foreignPackageNotes, n)
proc processCompile(conf: ConfigRef; filename: string) =
var found = findFile(conf, filename)
@@ -222,10 +229,10 @@ proc processCompile(conf: ConfigRef; filename: string) =
extccomp.addExternalFileToCompile(conf, found)
const
errNoneBoehmRefcExpectedButXFound = "'none', 'boehm' or 'refc' expected, but '$1' found"
errNoneBoehmRefcExpectedButXFound = "'arc', 'orc', 'markAndSweep', 'boehm', 'go', 'none', 'regions', or 'refc' expected, but '$1' found"
errNoneSpeedOrSizeExpectedButXFound = "'none', 'speed' or 'size' expected, but '$1' found"
errGuiConsoleOrLibExpectedButXFound = "'gui', 'console' or 'lib' expected, but '$1' found"
errInvalidExceptionSystem = "'goto', 'setjmp', 'cpp' or 'quirky' expected, but '$1' found"
errInvalidExceptionSystem = "'goto', 'setjump', 'cpp' or 'quirky' expected, but '$1' found"
proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo): bool =
case switch.normalize
@@ -291,7 +298,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
result = conf.options * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck}
of "infchecks": result = contains(conf.options, optInfCheck)
of "nanchecks": result = contains(conf.options, optNaNCheck)
of "nilchecks": result = contains(conf.options, optNilCheck)
of "nilchecks": result = false # not a thing
of "objchecks": result = contains(conf.options, optObjCheck)
of "fieldchecks": result = contains(conf.options, optFieldCheck)
of "rangechecks": result = contains(conf.options, optRangeCheck)
@@ -312,7 +319,6 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
of "patterns", "trmacros": result = contains(conf.options, optTrMacros)
of "excessivestacktrace": result = contains(conf.globalOptions, optExcessiveStackTrace)
of "nilseqs": result = contains(conf.options, optNilSeqs)
of "oldast": result = contains(conf.options, optOldAst)
else: invalidCmdLineOption(conf, passCmd1, switch, info)
proc processPath(conf: ConfigRef; path: string, info: TLineInfo,
@@ -385,6 +391,19 @@ proc handleStdinInput*(conf: ConfigRef) =
if conf.outDir.isEmpty:
conf.outDir = getNimcacheDir(conf)
proc specialDefine(conf: ConfigRef, key: string) =
# Keep this syncronized with the default config/nim.cfg!
if cmpIgnoreStyle(key, "nimQuirky") == 0:
conf.exc = excQuirky
elif cmpIgnoreStyle(key, "release") == 0 or cmpIgnoreStyle(key, "danger") == 0:
conf.options.excl {optStackTrace, optLineTrace, optLineDir, optOptimizeSize}
conf.globalOptions.excl {optExcessiveStackTrace, optCDebug}
conf.options.incl optOptimizeSpeed
if cmpIgnoreStyle(key, "danger") == 0 or cmpIgnoreStyle(key, "quick") == 0:
conf.options.excl {optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck,
optOverflowCheck, optAssert, optStackTrace, optLineTrace, optLineDir}
conf.globalOptions.excl {optCDebug}
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
conf: ConfigRef) =
var
@@ -426,23 +445,28 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "outdir":
expectArg(conf, switch, arg, pass, info)
conf.outDir = processPath(conf, arg, info, notRelativeToProj=true)
of "usenimcache":
processOnOffSwitchG(conf, {optUseNimcache}, arg, pass, info)
of "docseesrcurl":
expectArg(conf, switch, arg, pass, info)
conf.docSeeSrcUrl = arg
of "docroot":
conf.docRoot = if arg.len == 0: "@default" else: arg
conf.docRoot = if arg.len == 0: docRootDefault else: arg
of "backend", "b":
let backend = parseEnum(arg.normalize, TBackend.default)
if backend == TBackend.default: localError(conf, info, "invalid backend: '$1'" % arg)
conf.backend = backend
of "doccmd": conf.docCmd = arg
of "mainmodule", "m":
discard "allow for backwards compatibility, but don't do anything"
of "define", "d":
expectArg(conf, switch, arg, pass, info)
if {':', '='} in arg:
splitSwitch(conf, arg, key, val, pass, info)
if cmpIgnoreStyle(key, "nimQuirky") == 0:
conf.exc = excQuirky
specialDefine(conf, key)
defineSymbol(conf.symbols, key, val)
else:
if cmpIgnoreStyle(arg, "nimQuirky") == 0:
conf.exc = excQuirky
specialDefine(conf, arg)
defineSymbol(conf.symbols, arg)
of "undef", "u":
expectArg(conf, switch, arg, pass, info)
@@ -470,8 +494,13 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "forcebuild", "f":
processOnOffSwitchG(conf, {optForceFullMake}, arg, pass, info)
of "project":
processOnOffSwitchG(conf, {optWholeProject}, arg, pass, info)
processOnOffSwitchG(conf, {optWholeProject, optGenIndex}, arg, pass, info)
of "gc":
if conf.backend == backendJs or conf.command == "js":
# for: bug #16033
# This might still be imperfect, in rarse corner cases
# (where command is reset in nimscript, maybe).
return
expectArg(conf, switch, arg, pass, info)
if pass in {passCmd2, passPP}:
case arg.normalize
@@ -488,8 +517,6 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
defineSymbol(conf.symbols, "gcmarkandsweep")
of "destructors", "arc":
conf.selectedGC = gcArc
if conf.cmd != cmdCompileToCpp:
conf.exc = excGoto
defineSymbol(conf.symbols, "gcdestructors")
defineSymbol(conf.symbols, "gcarc")
incl conf.globalOptions, optSeqDestructors
@@ -499,8 +526,6 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
defineSymbol(conf.symbols, "nimV2")
of "orc":
conf.selectedGC = gcOrc
if conf.cmd != cmdCompileToCpp:
conf.exc = excGoto
defineSymbol(conf.symbols, "gcdestructors")
defineSymbol(conf.symbols, "gcorc")
incl conf.globalOptions, optSeqDestructors
@@ -529,6 +554,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
of "hint": processSpecificNote(arg, wHint, pass, info, switch, conf)
of "warningaserror": processSpecificNote(arg, wWarningAsError, pass, info, switch, conf)
of "hints":
if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf)
of "threadanalysis": processOnOffSwitchG(conf, {optThreadAnalysis}, arg, pass, info)
@@ -570,25 +596,13 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
else:
undefSymbol(conf.symbols, "hotcodereloading")
undefSymbol(conf.symbols, "useNimRtl")
of "oldnewlines":
case arg.normalize
of "", "on":
conf.oldNewlines = true
defineSymbol(conf.symbols, "nimOldNewlines")
of "off":
conf.oldNewlines = false
undefSymbol(conf.symbols, "nimOldNewlines")
else:
localError(conf, info, errOnOrOffExpectedButXFound % arg)
of "laxstrings": processOnOffSwitch(conf, {optLaxStrings}, arg, pass, info)
of "nilseqs": processOnOffSwitch(conf, {optNilSeqs}, arg, pass, info)
of "oldast": processOnOffSwitch(conf, {optOldAst}, arg, pass, info)
of "checks", "x": processOnOffSwitch(conf, ChecksOptions, arg, pass, info)
of "floatchecks":
processOnOffSwitch(conf, {optNaNCheck, optInfCheck}, arg, pass, info)
of "infchecks": processOnOffSwitch(conf, {optInfCheck}, arg, pass, info)
of "nanchecks": processOnOffSwitch(conf, {optNaNCheck}, arg, pass, info)
of "nilchecks": processOnOffSwitch(conf, {optNilCheck}, arg, pass, info)
of "nilchecks": discard "no such thing anymore"
of "objchecks": processOnOffSwitch(conf, {optObjCheck}, arg, pass, info)
of "fieldchecks": processOnOffSwitch(conf, {optFieldCheck}, arg, pass, info)
of "rangechecks": processOnOffSwitch(conf, {optRangeCheck}, arg, pass, info)
@@ -868,8 +882,9 @@ 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 "expandarc":
expectArg(conf, switch, arg, pass, info)
conf.arcToExpand[arg] = "T"
of "useversion":
expectArg(conf, switch, arg, pass, info)
case arg
@@ -880,14 +895,26 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
defineSymbol(conf.symbols, "NimPatch", "100")
# old behaviors go here:
defineSymbol(conf.symbols, "nimOldRelativePathBehavior")
undefSymbol(conf.symbols, "nimDoesntTrackDefects")
ast.eqTypeFlags.excl {tfGcSafe, tfNoSideEffect}
conf.globalOptions.incl optNimV1Emulation
of "1.2":
defineSymbol(conf.symbols, "NimMajor", "1")
defineSymbol(conf.symbols, "NimMinor", "2")
# always be compatible with 1.2.100:
defineSymbol(conf.symbols, "NimPatch", "100")
conf.globalOptions.incl optNimV12Emulation
else:
localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
of "benchmarkvm":
processOnOffSwitchG(conf, {optBenchmarkVM}, arg, pass, info)
of "profilevm":
processOnOffSwitchG(conf, {optProfileVM}, arg, pass, info)
of "sinkinference":
processOnOffSwitch(conf, {optSinkInference}, arg, pass, info)
of "cursorinference":
# undocumented, for debugging purposes only:
processOnOffSwitch(conf, {optCursorInference}, arg, pass, info)
of "panics":
processOnOffSwitchG(conf, {optPanics}, arg, pass, info)
if optPanics in conf.globalOptions:
@@ -895,15 +922,14 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "sourcemap":
conf.globalOptions.incl optSourcemap
conf.options.incl optLineDir
# processOnOffSwitchG(conf, {optSourcemap, opt}, arg, pass, info)
of "deepcopy":
processOnOffSwitchG(conf, {optEnableDeepCopy}, arg, pass, info)
of "": # comes from "-" in for example: `nim c -r -` (gets stripped from -)
handleStdinInput(conf)
else:
if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
else: invalidCmdLineOption(conf, pass, switch, info)
template gCmdLineInfo*(): untyped = newLineInfo(commandLineIdx, 1, 1)
proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) =
var cmd, arg: string
splitSwitch(config, switch, cmd, arg, pass, gCmdLineInfo)

View File

@@ -13,7 +13,7 @@ import
strtabs
from options import Feature
from lineinfos import HintsToStr, WarningsToStr
from lineinfos import hintMin, hintMax, warnMin, warnMax
proc defineSymbol*(symbols: StringTableRef; symbol: string, value: string = "true") =
symbols[symbol] = value
@@ -86,13 +86,13 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimMacrosSizealignof")
defineSymbol("nimNoZeroExtendMagic")
defineSymbol("nimMacrosGetNodeId")
for f in low(Feature)..high(Feature):
for f in Feature:
defineSymbol("nimHas" & $f)
for s in WarningsToStr:
defineSymbol("nimHasWarning" & s)
for s in HintsToStr:
defineSymbol("nimHasHint" & s)
for s in warnMin..warnMax:
defineSymbol("nimHasWarning" & $s)
for s in hintMin..hintMax:
defineSymbol("nimHasHint" & $s)
defineSymbol("nimFixedOwned")
defineSymbol("nimHasStyleChecks")
@@ -102,6 +102,7 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimnomagic64")
defineSymbol("nimNewShiftOps")
defineSymbol("nimHasCursor")
defineSymbol("nimAlignPragma")
defineSymbol("nimHasExceptionsQuery")
defineSymbol("nimHasIsNamedTuple")
defineSymbol("nimHashOrdinalFixed")
@@ -116,5 +117,10 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimNewIntegerOps")
defineSymbol("nimHasInvariant")
defineSymbol("nimHasStacktraceMsgs")
defineSymbol("nimDoesntTrackDefects")
defineSymbol("nimHasLentIterators")
defineSymbol("nimHasDeclaredMagic")
defineSymbol("nimHasStacktracesModule")
defineSymbol("nimHasEffectTraitsModule")
defineSymbol("nimHasCastPragmaBlocks")
defineSymbol("nimHasJsBigIntBackend")

View File

@@ -51,7 +51,10 @@ proc generateDot*(graph: ModuleGraph; project: AbsoluteFile) =
rope(project.splitFile.name), b.dotGraph],
changeFileExt(project, "dot"))
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
when not defined(nimHasSinkInference):
{.pragma: nosinks.}
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} =
var g: PGen
new(g)
g.module = module

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, types, intsets, lineinfos, renderer
import ast, types, intsets, lineinfos, renderer, asciitables
from patterns import sameTrees
@@ -57,14 +57,11 @@ type
Con = object
code: ControlFlowGraph
inCall, inTryStmt: int
inTryStmt: int
blocks: seq[TBlock]
owner: PSym
proc debugInfo(info: TLineInfo): string =
result = $info.line #info.toFilename & ":" & $info.line
proc codeListing(c: ControlFlowGraph, result: var string, start=0; last = -1) =
proc codeListing(c: ControlFlowGraph, start = 0; last = -1): string =
# for debugging purposes
# first iteration: compute all necessary labels:
var jumpTargets = initIntSet()
@@ -85,17 +82,14 @@ proc codeListing(c: ControlFlowGraph, result: var string, start=0; last = -1) =
result.add "L"
result.addInt c[i].dest+i
result.add("\t#")
result.add(debugInfo(c[i].n.info))
result.add($c[i].n.info.line)
result.add("\n")
inc i
if i in jumpTargets: result.add("L" & $i & ": End\n")
# consider calling `asciitables.alignTable`
proc echoCfg*(c: ControlFlowGraph; start=0; last = -1) {.deprecated.} =
proc echoCfg*(c: ControlFlowGraph; start = 0; last = -1) {.deprecated.} =
## echos the ControlFlowGraph for debugging purposes.
var buf = ""
codeListing(c, buf, start, last)
echo buf
echo codeListing(c, start, last).alignTable
proc forkI(c: var Con; n: PNode): TPosition =
result = TPosition(c.code.len)
@@ -273,22 +267,20 @@ duplicate the 'join' instructions on breaks and return exits!
]#
proc genLabel(c: Con): TPosition =
result = TPosition(c.code.len)
proc genLabel(c: Con): TPosition = TPosition(c.code.len)
template checkedDistance(dist): int =
doAssert low(int) div 2 + 1 < dist and dist < high(int) div 2
dist
proc jmpBack(c: var Con, n: PNode, p = TPosition(0)) =
let dist = p.int - c.code.len
doAssert(low(int) div 2 + 1 < dist and dist < high(int) div 2)
c.code.add Instr(n: n, kind: goto, dest: dist)
c.code.add Instr(n: n, kind: goto, dest: checkedDistance(p.int - c.code.len))
proc patch(c: var Con, p: TPosition) =
# patch with current index
let p = p.int
let diff = c.code.len - p
doAssert(low(int) div 2 + 1 < diff and diff < high(int) div 2)
c.code[p].dest = diff
c.code[p.int].dest = checkedDistance(c.code.len - p.int)
proc gen(c: var Con; n: PNode) # {.noSideEffect.}
proc gen(c: var Con; n: PNode)
proc popBlock(c: var Con; oldLen: int) =
var exits: seq[TPosition]
@@ -302,8 +294,8 @@ proc popBlock(c: var Con; oldLen: int) =
c.patch e
c.blocks.setLen(oldLen)
template withBlock(labl: PSym; body: untyped) {.dirty.} =
var oldLen {.gensym.} = c.blocks.len
template withBlock(labl: PSym; body: untyped) =
let oldLen = c.blocks.len
c.blocks.add TBlock(isTryBlock: false, label: labl)
body
popBlock(c, oldLen)
@@ -366,11 +358,9 @@ when true:
endings[i] = c.forkI(n)
c.gen(n[1])
for i in countdown(endings.high, 0):
let endPos = endings[i]
c.patch(endPos)
c.patch(endings[i])
else:
proc genWhile(c: var Con; n: PNode) =
# lab1:
# cond, tmp
@@ -385,10 +375,9 @@ else:
c.jmpBack(n, lab1)
else:
c.gen(n[0])
let lab2 = c.forkI(n)
c.gen(n[1])
c.jmpBack(n, lab1)
c.patch(lab2)
forkT(n):
c.gen(n[1])
c.jmpBack(n, lab1)
template forkT(n, body) =
let lab1 = c.forkI(n)
@@ -434,16 +423,14 @@ proc genIf(c: var Con, n: PNode) =
]#
var endings: seq[TPosition] = @[]
for i in 0..<n.len:
var it = n[i]
let it = n[i]
c.gen(it[0])
if it.len == 2:
let elsePos = forkI(c, it[1])
c.gen(it[1])
endings.add(c.gotoI(it[1]))
c.patch(elsePos)
forkT(it[1]):
c.gen(it[1])
endings.add c.gotoI(it[1])
for i in countdown(endings.high, 0):
let endPos = endings[i]
c.patch(endPos)
c.patch(endings[i])
proc genAndOr(c: var Con; n: PNode) =
# asgn dest, a
@@ -473,16 +460,13 @@ proc genCase(c: var Con; n: PNode) =
c.gen(n[0])
for i in 1..<n.len:
let it = n[i]
if it.len == 1:
c.gen(it[0])
elif i == n.len-1 and isExhaustive:
if it.len == 1 or (i == n.len-1 and isExhaustive):
# treat the last branch as 'else' if this is an exhaustive case statement.
c.gen(it.lastSon)
else:
let elsePos = c.forkI(it.lastSon)
c.gen(it.lastSon)
endings.add(c.gotoI(it.lastSon))
c.patch(elsePos)
forkT(it.lastSon):
c.gen(it.lastSon)
endings.add c.gotoI(it.lastSon)
for i in countdown(endings.high, 0):
let endPos = endings[i]
c.patch(endPos)
@@ -506,7 +490,6 @@ proc genBreakOrRaiseAux(c: var Con, i: int, n: PNode) =
proc genBreak(c: var Con; n: PNode) =
if n[0].kind == nkSym:
#echo cast[int](n[0].sym)
for i in countdown(c.blocks.high, 0):
if not c.blocks[i].isTryBlock and c.blocks[i].label == n[0].sym:
genBreakOrRaiseAux(c, i, n)
@@ -525,7 +508,6 @@ proc genTry(c: var Con; n: PNode) =
c.blocks.add TBlock(isTryBlock: true, finale: if n[^1].kind == nkFinally: n[^1] else: newNode(nkEmpty))
inc c.inTryStmt
#let elsePos = c.forkI(n)
c.gen(n[0])
dec c.inTryStmt
@@ -534,20 +516,14 @@ proc genTry(c: var Con; n: PNode) =
c.blocks.setLen oldLen
#c.patch(elsePos)
for i in 1..<n.len:
let it = n[i]
if it.kind != nkFinally:
let endExcept = c.forkI(it)
c.gen(it.lastSon)
endings.add(c.gotoI(it))
c.patch(endExcept)
forkT(it):
c.gen(it.lastSon)
endings.add c.gotoI(it)
for i in countdown(endings.high, 0):
let endPos = endings[i]
c.patch(endPos)
# join the 'elsePos' forkI instruction:
#c.joinI(c.blocks[^1].forks.pop(), n)
c.patch(endings[i])
let fin = lastSon(n)
if fin.kind == nkFinally:
@@ -597,59 +573,43 @@ proc skipConvDfa*(n: PNode): PNode =
result = result[1]
else: break
proc genUse(c: var Con; orig: PNode) =
var n = orig
proc aliases*(obj, field: PNode): bool =
var n = field
var obj = obj
while true:
case obj.kind
of {nkObjDownConv, nkObjUpConv, nkAddr, nkHiddenAddr, nkDerefExpr, nkHiddenDeref}:
obj = obj[0]
of PathKinds1:
obj = obj[1]
else: break
while true:
if sameTrees(obj, n): return true
case n.kind
of PathKinds0 - {nkBracketExpr}:
n = n[0]
of nkBracketExpr:
gen(c, n[1])
of PathKinds0:
n = n[0]
of PathKinds1:
n = n[1]
else: break
if n.kind in nkCallKinds:
gen(c, n)
if n.kind == nkSym and n.sym.kind in InterestingSyms:
c.code.add Instr(n: orig, kind: use)
proc aliases*(obj, field: PNode): bool =
var n = field
var obj = obj
while obj.kind in {nkHiddenSubConv, nkHiddenStdConv, nkObjDownConv, nkObjUpConv,
nkAddr, nkHiddenAddr, nkDerefExpr, nkHiddenDeref}:
obj = obj[0]
while true:
if sameTrees(obj, n): return true
case n.kind
of PathKinds0, PathKinds1:
n = n[0]
else:
break
type InstrTargetKind* = enum
None, Full, Partial
proc useInstrTargets*(ins: Instr; loc: PNode): bool =
assert ins.kind == use
result = sameTrees(ins.n, loc) or
ins.n.aliases(loc) or loc.aliases(ins.n)
# We can come here if loc is 'x.f' and ins.n is 'x' or the other way round.
# use x.f; question: does it affect the full 'x'? No.
# use x; question does it affect 'x.f'? Yes.
proc defInstrTargets*(ins: Instr; loc: PNode): bool =
assert ins.kind == def
result = sameTrees(ins.n, loc) or ins.n.aliases(loc)
# We can come here if loc is 'x.f' and ins.n is 'x' or the other way round.
# def x.f; question: does it affect the full 'x'? No.
# def x; question: does it affect the 'x.f'? Yes.
proc instrTargets*(insloc, loc: PNode): InstrTargetKind =
if sameTrees(insloc, loc) or insloc.aliases(loc):
Full # x -> x; x -> x.f
elif loc.aliases(insloc):
Partial # x.f -> x
else: None
proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
var n = orig
while true:
case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr:
of PathKinds0 - {nkBracketExpr, nkHiddenDeref, nkDerefExpr}:
n = n[0]
of PathKinds1:
n = n[1]
of nkBracketExpr:
# in a[i] the 'i' must be known
if n.len > 1 and n[1].kind in {nkCharLit..nkUInt64Lit}:
@@ -662,14 +622,13 @@ proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
# bug #14159, we cannot reason about sinkParam[].location as it can
# still be shared for tyRef.
n = n[0]
return n.kind == nkSym and n.sym.owner == owner and (
n.sym.typ.skipTypes(abstractInst-{tyOwned}).kind in {tyOwned})
else:
break
return n.kind == nkSym and n.sym.owner == owner and
(n.sym.typ.skipTypes(abstractInst-{tyOwned}).kind in {tyOwned})
else: break
# XXX Allow closure deref operations here if we know
# the owner controlled the closure allocation?
result = n.kind == nkSym and n.sym.owner == owner and
owner.kind != skModule and
{sfGlobal, sfThread, sfCursor} * n.sym.flags == {} and
(n.sym.kind != skParam or isSinkParam(n.sym)) # or n.sym.typ.kind == tyVar)
# Note: There is a different move analyzer possible that checks for
# consume(param.key); param.key = newValue for all paths. Then code like
@@ -682,43 +641,42 @@ proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
# free the old data and all is lost! Lesson: Don't be too smart, trust the
# lower level C++ optimizer to specialize this code.
proc genDef(c: var Con; n: PNode) =
var m = n
# XXX do something about this duplicated logic here.
proc skipTrivials(c: var Con, n: PNode): PNode =
result = n
while true:
case m.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr:
m = m[0]
case result.kind
of PathKinds0 - {nkBracketExpr}:
result = result[0]
of nkBracketExpr:
gen(c, m[1])
m = m[0]
of nkHiddenDeref, nkDerefExpr:
m = m[0]
else:
break
gen(c, result[1])
result = result[0]
of PathKinds1:
result = result[1]
else: break
proc genUse(c: var Con; orig: PNode) =
let n = c.skipTrivials(orig)
if n.kind == nkSym and n.sym.kind in InterestingSyms:
c.code.add Instr(n: n, kind: def)
elif isAnalysableFieldAccess(n, c.owner):
c.code.add Instr(n: n, kind: def)
else:
# bug #13314: An assignment to t5.w = -5 is a usage of 't5'
# we still need to gather the use information:
c.code.add Instr(n: orig, kind: use)
elif n.kind in nkCallKinds:
gen(c, n)
proc genDef(c: var Con; orig: PNode) =
let n = c.skipTrivials(orig)
if n.kind == nkSym and n.sym.kind in InterestingSyms:
c.code.add Instr(n: orig, kind: def)
proc genCall(c: var Con; n: PNode) =
gen(c, n[0])
var t = n[0].typ
if t != nil: t = t.skipTypes(abstractInst)
inc c.inCall
for i in 1..<n.len:
gen(c, n[i])
when false:
if t != nil and i < t.len and t[i].kind == tyVar:
# This is wrong! Pass by var is a 'might def', not a 'must def'
# like the other defs we emit. This is not good enough for a move
# optimizer.
if t != nil and i < t.len and t[i].kind == tyOut:
# Pass by 'out' is a 'must def'. Good enough for a move optimizer.
genDef(c, n[i])
# every call can potentially raise:
if c.inTryStmt > 0 and canRaiseConservative(n[0]):
@@ -727,13 +685,11 @@ proc genCall(c: var Con; n: PNode) =
# goto exceptionHandler (except or finally)
# lab1:
# join F1
let endGoto = c.forkI(n)
for i in countdown(c.blocks.high, 0):
if c.blocks[i].isTryBlock:
genBreakOrRaiseAux(c, i, n)
break
c.patch(endGoto)
dec c.inCall
forkT(n):
for i in countdown(c.blocks.high, 0):
if c.blocks[i].isTryBlock:
genBreakOrRaiseAux(c, i, n)
break
proc genMagic(c: var Con; n: PNode; m: TMagic) =
case m
@@ -777,7 +733,7 @@ proc gen(c: var Con; n: PNode) =
# "uses" 'i'. But we are only talking about builtin array indexing so
# it doesn't matter and 'x = 34' is NOT a usage of 'x'.
genDef(c, n[0])
of PathKinds0 - {nkHiddenStdConv, nkHiddenSubConv, nkObjDownConv, nkObjUpConv}:
of PathKinds0 - {nkObjDownConv, nkObjUpConv}:
genUse(c, n)
of nkIfStmt, nkIfExpr: genIf(c, n)
of nkWhenStmt:
@@ -794,13 +750,12 @@ proc gen(c: var Con; n: PNode) =
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[0])
of nkConv, nkExprColonExpr, nkExprEqExpr, nkCast, nkHiddenSubConv, nkHiddenStdConv:
of nkDiscardStmt, nkObjDownConv, nkObjUpConv, nkStringToCString, nkCStringToString:
gen(c, n[0])
of nkConv, nkExprColonExpr, nkExprEqExpr, nkCast, PathKinds1:
gen(c, n[1])
of nkStringToCString, nkCStringToString: gen(c, n[0])
of nkVarSection, nkLetSection: genVarSection(c, n)
of nkDefer:
doAssert false, "dfa construction pass requires the elimination of 'defer'"
of nkDefer: doAssert false, "dfa construction pass requires the elimination of 'defer'"
else: discard
proc constructCfg*(s: PSym; body: PNode): ControlFlowGraph =
@@ -809,4 +764,7 @@ proc constructCfg*(s: PSym; body: PNode): ControlFlowGraph =
withBlock(s):
gen(c, body)
genImplicitReturn(c)
shallowCopy(result, c.code)
when defined(gcArc) or defined(gcOrc):
result = c.code # will move
else:
shallowCopy(result, c.code)

View File

@@ -17,19 +17,28 @@ import
packages/docutils/rst, packages/docutils/rstgen,
json, xmltree, cgi, trees, types,
typesrenderer, astalgo, lineinfos, intsets,
pathutils, trees
pathutils, trees, tables, nimpaths, renderverbatim, osproc
from std/private/globs import nativeToUnixPath
const
exportSection = skField
htmldocsDir = RelativeDir"htmldocs"
docCmdSkip = "skip"
type
TSections = array[TSymKind, Rope]
ExampleGroup = ref object
## a group of runnableExamples with same rdoccmd
rdoccmd: string ## from 1st arg in `runnableExamples(rdoccmd): body`
docCmd: string ## from user config, e.g. --doccmd:-d:foo
code: string ## contains imports; each import contains `body`
index: int ## group index
TDocumentor = object of rstgen.RstGenerator
modDesc: Rope # module description
module: PSym
modDeprecationMsg: Rope
toc, section: TSections
toc, toc2, section: TSections
tocTable: array[TSymKind, Table[string, Rope]]
indexValFilename: string
analytics: string # Google Analytics javascript, "" if doesn't exist
seenSymbols: StringTableRef # avoids duplicate symbol generation for HTML.
@@ -41,22 +50,12 @@ type
exampleCounter: int
emitted: IntSet # we need to track which symbols have been emitted
# already. See bug #3655
destFile*: AbsoluteFile
thisDir*: AbsoluteDir
examples: string
wroteCss*: bool
exampleGroups: OrderedTable[string, ExampleGroup]
wroteSupportFiles*: bool
PDoc* = ref TDocumentor ## Alias to type less.
proc nativeToUnix(path: string): string =
doAssert not path.isAbsolute # absolute files need more care for the drive
when DirSep == '\\':
result = replace(path, '\\', '/')
else: result = path
proc docOutDir(conf: ConfigRef, subdir: RelativeDir = RelativeDir""): AbsoluteDir =
if not conf.outDir.isEmpty: conf.outDir else: conf.projectPath / subdir
proc presentationPath*(conf: ConfigRef, file: AbsoluteFile, isTitle = false): RelativeFile =
## returns a relative file that will be appended to outDir
let file2 = $file
@@ -65,7 +64,7 @@ proc presentationPath*(conf: ConfigRef, file: AbsoluteFile, isTitle = false): Re
proc nimbleDir(): AbsoluteDir =
getNimbleFile(conf, file2).parentDir.AbsoluteDir
case conf.docRoot:
of "@default": # using `@` instead of `$` to avoid shell quoting complications
of docRootDefault:
result = getRelativePathFromConfigPath(conf, file)
let dir = nimbleDir()
if not dir.isEmpty:
@@ -81,17 +80,20 @@ proc presentationPath*(conf: ConfigRef, file: AbsoluteFile, isTitle = false): Re
result = getRelativePathFromConfigPath(conf, file)
if result.isEmpty: bail()
elif conf.docRoot.len > 0:
doAssert conf.docRoot.isAbsolute, conf.docRoot # or globalError
doAssert conf.docRoot.existsDir, conf.docRoot
result = relativeTo(file, conf.docRoot.AbsoluteDir)
# we're (currently) requiring `isAbsolute` to avoid confusion when passing
# a relative path (would it be relative wrt $PWD or to projectfile)
conf.globalAssert conf.docRoot.isAbsolute, arg=conf.docRoot
conf.globalAssert conf.docRoot.dirExists, arg=conf.docRoot
# needed because `canonicalizePath` called on `file`
result = file.relativeTo conf.docRoot.expandFilename.AbsoluteDir
else:
bail()
if isAbsolute(result.string):
result = file.string.splitPath()[1].RelativeFile
if isTitle:
result = result.string.nativeToUnix.RelativeFile
result = result.string.nativeToUnixPath.RelativeFile
else:
result = result.string.replace("..", "@@").RelativeFile ## refs #13223
result = result.string.replace("..", dotdotMangle).RelativeFile
doAssert not result.isEmpty
doAssert not isAbsolute(result.string)
@@ -139,7 +141,7 @@ template declareClosures =
result = options.findFile(conf, s).string
if result.len == 0:
result = getCurrentDir() / s
if not existsFile(result): result = ""
if not fileExists(result): result = ""
proc parseRst(text, filename: string,
line, column: int, hasToc: var bool,
@@ -150,13 +152,9 @@ proc parseRst(text, filename: string,
docgenFindFile, compilerMsgHandler)
proc getOutFile2(conf: ConfigRef; filename: RelativeFile,
ext: string, dir: RelativeDir; guessTarget: bool): AbsoluteFile =
if optWholeProject in conf.globalOptions:
let d = conf.docOutDir(dir)
createDir(d)
result = d / changeFileExt(filename, ext)
elif guessTarget:
let d = conf.docOutDir
ext: string, guessTarget: bool): AbsoluteFile =
if optWholeProject in conf.globalOptions or guessTarget:
let d = conf.outDir
createDir(d)
result = d / changeFileExt(filename, ext)
elif not conf.outFile.isEmpty:
@@ -170,6 +168,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
result.module = module
result.conf = conf
result.cache = cache
result.outDir = conf.outDir.string
initRstGenerator(result[], (if conf.cmd != cmdRst2tex: outHtml else: outLatex),
conf.configVars, filename.string, {roSupportRawDirective, roSupportMarkdown},
docgenFindFile, compilerMsgHandler)
@@ -196,6 +195,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
initStrTable result.types
result.onTestSnippet =
proc (gen: var RstGenerator; filename, cmd: string; status: int; content: string) =
if conf.docCmd == docCmdSkip: return
inc(gen.id)
var d = TDocumentor(gen)
var outp: AbsoluteFile
@@ -214,16 +214,24 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
# Include the current file if we're parsing a nim file
let importStmt = if d.isPureRst: "" else: "import \"$1\"\n" % [d.filename.replace("\\", "/")]
writeFile(outp, importStmt & content)
let c = if cmd.startsWith("nim "): os.getAppFilename() & cmd.substr(3)
else: cmd
let c2 = c % quoteShell(outp)
rawMessage(conf, hintExecuting, c2)
if execShellCmd(c2) != status:
rawMessage(conf, errGenerated, "executing of external program failed: " & c2)
proc interpSnippetCmd(cmd: string): string =
# backward compatibility hacks; interpolation commands should explicitly use `$`
if cmd.startsWith "nim ": result = "$nim " & cmd[4..^1]
else: result = cmd
result = result.replace("$1", "$options") % [
"nim", os.getAppFilename().quoteShell,
"backend", $d.conf.backend,
"options", outp.quoteShell,
]
let cmd = cmd.interpSnippetCmd
rawMessage(conf, hintExecuting, cmd)
let (output, gotten) = execCmdEx(cmd)
if gotten != status:
rawMessage(conf, errGenerated, "snippet failed: cmd: '$1' status: $2 expected: $3 output: $4" % [cmd, $gotten, $status, output])
result.emitted = initIntSet()
result.destFile = getOutFile2(conf, presentationPath(conf, filename),
outExt, htmldocsDir, false)
result.thisDir = result.destFile.splitFile.dir
result.destFile = getOutFile2(conf, presentationPath(conf, filename), outExt, false).string
result.thisDir = result.destFile.AbsoluteFile.splitFile.dir
template dispA(conf: ConfigRef; dest: var Rope, xml, tex: string, args: openArray[Rope]) =
if conf.cmd != cmdRst2tex: dest.addf(xml, args)
@@ -295,11 +303,13 @@ proc ropeFormatNamedVars(conf: ConfigRef; frmt: FormatStr,
proc genComment(d: PDoc, n: PNode): string =
result = ""
var dummyHasToc: bool
if n.comment.len > 0:
renderRstToOut(d[], parseRst(n.comment, toFullPath(d.conf, n.info),
toLinenumber(n.info), toColumn(n.info),
dummyHasToc, d.options, d.conf), result)
let comment = n.comment
when false:
# RFC: to preseve newlines in comments, this would work:
comment = comment.replace("\n", "\n\n")
renderRstToOut(d[], parseRst(comment, toFullPath(d.conf, n.info), toLinenumber(n.info),
toColumn(n.info), (var dummy: bool; dummy), d.options, d.conf), result)
proc genRecCommentAux(d: PDoc, n: PNode): Rope =
if n == nil: return nil
@@ -331,11 +341,10 @@ proc getPlainDocstring(n: PNode): string =
## You need to call this before genRecComment, whose side effects are removal
## of comments from the tree. The proc will recursively scan and return all
## the concatenated ``##`` comments of the node.
result = ""
if n == nil: return
if startsWith(n.comment, "##"):
if n == nil: result = ""
elif startsWith(n.comment, "##"):
result = n.comment
if result.len < 1:
else:
for i in 0..<n.safeLen:
result = getPlainDocstring(n[i])
if result.len > 0: return
@@ -346,8 +355,7 @@ proc belongsToPackage(conf: ConfigRef; module: PSym): bool =
proc externalDep(d: PDoc; module: PSym): string =
if optWholeProject in d.conf.globalOptions or d.conf.docRoot.len > 0:
let full = AbsoluteFile toFullPath(d.conf, FileIndex module.position)
let tmp = getOutFile2(d.conf, presentationPath(d.conf, full), HtmlExt,
htmldocsDir, sfMainModule notin module.flags)
let tmp = getOutFile2(d.conf, presentationPath(d.conf, full), HtmlExt, sfMainModule notin module.flags)
result = relativeTo(tmp, d.thisDir, '/').string
else:
result = extractFilename toFullPath(d.conf, FileIndex module.position)
@@ -360,6 +368,7 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
var kind = tkEof
var tokenPos = 0
var procTokenPos = 0
template escLit(): untyped = rope(esc(d.target, literal))
while true:
getNextTok(r, kind, literal)
inc tokenPos
@@ -368,7 +377,7 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
break
of tkComment:
dispA(d.conf, result, "<span class=\"Comment\">$1</span>", "\\spanComment{$1}",
[rope(esc(d.target, literal))])
[escLit])
of tokKeywordLow..tokKeywordHigh:
if kind in {tkProc, tkMethod, tkIterator, tkMacro, tkTemplate, tkFunc, tkConverter}:
procTokenPos = tokenPos
@@ -376,53 +385,53 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
[rope(literal)])
of tkOpr:
dispA(d.conf, result, "<span class=\"Operator\">$1</span>", "\\spanOperator{$1}",
[rope(esc(d.target, literal))])
[escLit])
of tkStrLit..tkTripleStrLit:
dispA(d.conf, result, "<span class=\"StringLit\">$1</span>",
"\\spanStringLit{$1}", [rope(esc(d.target, literal))])
"\\spanStringLit{$1}", [escLit])
of tkCharLit:
dispA(d.conf, result, "<span class=\"CharLit\">$1</span>", "\\spanCharLit{$1}",
[rope(esc(d.target, literal))])
[escLit])
of tkIntLit..tkUInt64Lit:
dispA(d.conf, result, "<span class=\"DecNumber\">$1</span>",
"\\spanDecNumber{$1}", [rope(esc(d.target, literal))])
"\\spanDecNumber{$1}", [escLit])
of tkFloatLit..tkFloat128Lit:
dispA(d.conf, result, "<span class=\"FloatNumber\">$1</span>",
"\\spanFloatNumber{$1}", [rope(esc(d.target, literal))])
"\\spanFloatNumber{$1}", [escLit])
of tkSymbol:
let s = getTokSym(r)
# -2 because of the whitespace in between:
if procTokenPos == tokenPos-2 and procLink != nil:
dispA(d.conf, result, "<a href=\"#$2\"><span class=\"Identifier\">$1</span></a>",
"\\spanIdentifier{$1}", [rope(esc(d.target, literal)), procLink])
"\\spanIdentifier{$1}", [escLit, procLink])
elif s != nil and s.kind in {skType, skVar, skLet, skConst} and
sfExported in s.flags and s.owner != nil and
belongsToPackage(d.conf, s.owner) and d.target == outHtml:
let external = externalDep(d, s.owner)
result.addf "<a href=\"$1#$2\"><span class=\"Identifier\">$3</span></a>",
[rope changeFileExt(external, "html"), rope literal,
rope(esc(d.target, literal))]
escLit]
else:
dispA(d.conf, result, "<span class=\"Identifier\">$1</span>",
"\\spanIdentifier{$1}", [rope(esc(d.target, literal))])
"\\spanIdentifier{$1}", [escLit])
of tkSpaces, tkInvalid:
result.add(literal)
of tkCurlyDotLe:
dispA(d.conf, result, "<span>" & # This span is required for the JS to work properly
template fun(s) = dispA(d.conf, result, s, "\\spanOther{$1}", [escLit])
if renderRunnableExamples in renderFlags: fun "$1"
else: fun: "<span>" & # This span is required for the JS to work properly
"""<span class="Other">{</span><span class="Other pragmadots">...</span><span class="Other">}</span>
</span>
<span class="pragmawrap">
<span class="Other">$1</span>
<span class="pragma">""".replace("\n", ""), # Must remove newlines because wrapped in a <pre>
"\\spanOther{$1}",
[rope(esc(d.target, literal))])
<span class="pragma">""".replace("\n", "") # Must remove newlines because wrapped in a <pre>
of tkCurlyDotRi:
dispA(d.conf, result, """
template fun(s) = dispA(d.conf, result, s, "\\spanOther{$1}", [escLit])
if renderRunnableExamples in renderFlags: fun "$1"
else: fun """
</span>
<span class="Other">$1</span>
</span>""".replace("\n", ""),
"\\spanOther{$1}",
[rope(esc(d.target, literal))])
</span>""".replace("\n", "")
of tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi,
tkBracketDotLe, tkBracketDotRi, tkParDotLe,
tkParDotRi, tkComma, tkSemiColon, tkColon, tkEquals, tkDot, tkDotDot,
@@ -430,51 +439,73 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
tkGStrLit, tkGTripleStrLit, tkInfixOpr, tkPrefixOpr, tkPostfixOpr,
tkBracketLeColon:
dispA(d.conf, result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}",
[rope(esc(d.target, literal))])
[escLit])
proc testExample(d: PDoc; ex: PNode) =
proc exampleOutputDir(d: PDoc): AbsoluteDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
proc writeExample(d: PDoc; ex: PNode, rdoccmd: string) =
if d.conf.errorCounter > 0: return
let outputDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
let outputDir = d.exampleOutputDir
createDir(outputDir)
inc d.exampleCounter
let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" &
"_examples" & $d.exampleCounter & ".nim"))
#let nimcache = outp.changeFileExt"" & "_nimcache"
renderModule(ex, d.filename, outp.string, conf = d.conf)
d.examples.add "import r\"" & outp.string & "\"\n"
if rdoccmd notin d.exampleGroups: d.exampleGroups[rdoccmd] = ExampleGroup(rdoccmd: rdoccmd, docCmd: d.conf.docCmd, index: d.exampleGroups.len)
d.exampleGroups[rdoccmd].code.add "import r\"$1\"\n" % outp.string
proc runAllExamples(d: PDoc) =
if d.examples.len == 0: return
let outputDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" &
"_examples.nim"))
writeFile(outp, d.examples)
let backend = if isDefined(d.conf, "js"): "js"
elif isDefined(d.conf, "cpp"): "cpp"
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:
quit "[Examples] failed: see " & outp.string
else:
# keep generated source file `outp` to allow inspection.
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
removeFile(outp.changeFileExt(ExeExt))
# This used to be: `let backend = if isDefined(d.conf, "js"): "js"` (etc), however
# using `-d:js` (etc) cannot work properly, e.g. would fail with `importjs`
# since semantics are affected by `config.backend`, not by isDefined(d.conf, "js")
let outputDir = d.exampleOutputDir
for _, group in d.exampleGroups:
if group.docCmd == docCmdSkip: continue
let outp = outputDir / RelativeFile("$1_group$2_examples.nim" % [d.filename.splitFile.name, $group.index])
group.code = "# autogenerated by docgen\n# source: $1\n# rdoccmd: $2\n$3" % [d.filename, group.rdoccmd, group.code]
writeFile(outp, group.code)
# most useful semantics is that `docCmd` comes after `rdoccmd`, so that we can (temporarily) override
# via command line
let cmd = "$nim $backend -r --warning:UnusedImport:off --path:$path --nimcache:$nimcache $rdoccmd $docCmd $file" % [
"nim", os.getAppFilename(),
"backend", $d.conf.backend,
"path", quoteShell(d.conf.projectPath),
"nimcache", quoteShell(outputDir),
"file", quoteShell(outp),
"rdoccmd", group.rdoccmd,
"docCmd", group.docCmd,
]
if os.execShellCmd(cmd) != 0:
quit "[runnableExamples] failed: generated file: '$1' group: '$2' cmd: $3" % [outp.string, $group[], cmd]
else:
# keep generated source file `outp` to allow inspection.
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
# removeFile(outp.changeFileExt(ExeExt)) # it's in nimcache, no need to remove
proc prepareExample(d: PDoc; n: PNode): tuple[rdoccmd: string, code: string] =
## returns `rdoccmd` and source code for this runnableExamples
var rdoccmd = ""
if n.len < 2 or n.len > 3: globalError(d.conf, n.info, "runnableExamples invalid")
if n.len == 3:
let n1 = n[1]
# xxx this should be evaluated during sempass
if n1.kind notin nkStrKinds: globalError(d.conf, n1.info, "string litteral expected")
rdoccmd = n1.strVal
proc prepareExamples(d: PDoc; n: PNode) =
var docComment = newTree(nkCommentStmt)
let loc = d.conf.toFileLineCol(n.info)
docComment.comment = "autogenerated by docgen from " & loc
docComment.comment = "autogenerated by docgen\nloc: $1\nrdoccmd: $2" % [loc, rdoccmd]
var runnableExamples = newTree(nkStmtList,
docComment,
newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
runnableExamples.info = n.info
let ret = extractRunnableExamplesSource(d.conf, n)
for a in n.lastSon: runnableExamples.add a
testExample(d, runnableExamples)
# we could also use `ret` instead here, to keep sources verbatim
writeExample(d, runnableExamples, rdoccmd)
result = (rdoccmd, ret)
when false:
proc extractImports(n: PNode; result: PNode) =
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
@@ -488,36 +519,101 @@ proc prepareExamples(d: PDoc; n: PNode) =
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
type RunnableState = enum
rsStart
rsComment
rsRunnable
rsDone
proc getAllRunnableExamplesImpl(d: PDoc; n: PNode, dest: var Rope, state: RunnableState): RunnableState =
##[
Simple state machine to tell whether we render runnableExamples and doc comments.
This is to ensure that we can interleave runnableExamples and doc comments freely;
the logic is easy to change but currently a doc comment following another doc comment
will not render, to avoid rendering in following case:
proc fn* =
runnableExamples: discard
## d1
runnableExamples: discard
## d2
## internal explanation # <- this one should be out; it's part of rest of function body and would likey not make sense in doc comment
discard # some code
]##
case n.kind
of nkCommentStmt:
if state in {rsStart, rsRunnable}:
dest.add genRecComment(d, n)
return rsComment
of nkCallKinds:
if isRunnableExamples(n[0]) and
n.len >= 2 and n.lastSon.kind == nkStmtList:
prepareExamples(d, n)
n.len >= 2 and n.lastSon.kind == nkStmtList and state in {rsStart, rsComment, rsRunnable}:
let (rdoccmd, code) = prepareExample(d, n)
var msg = "Example:"
if rdoccmd.len > 0: msg.add " cmd: " & rdoccmd
dispA(d.conf, dest, "\n<p><strong class=\"examples_text\">$1</strong></p>\n",
"\n\\textbf{$1}\n", [rope"Examples:"])
"\n\\textbf{$1}\n", [msg.rope])
inc d.listingCounter
let id = $d.listingCounter
dest.add(d.config.getOrDefault"doc.listing_start" % [id, "langNim"])
# this is a rather hacky way to get rid of the initial indentation
# that the renderer currently produces:
var i = 0
var body = n.lastSon
if body.len == 1 and body.kind == nkStmtList and
body.lastSon.kind == nkStmtList:
body = body.lastSon
for b in body:
if i > 0: dest.add "\n"
inc i
nodeToHighlightedHtml(d, b, dest, {}, nil)
var dest2 = ""
renderNimCode(dest2, code, isLatex = d.conf.cmd == cmdRst2tex)
dest.add dest2
dest.add(d.config.getOrDefault"doc.listing_end" % id)
return rsRunnable
else: discard
for i in 0..<n.safeLen:
getAllRunnableExamplesRec(d, n[i], orig, dest)
return rsDone
# change this to `rsStart` if you want to keep generating doc comments
# and runnableExamples that occur after some code in routine
proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) =
getAllRunnableExamplesRec(d, n, n, dest)
proc getRoutineBody(n: PNode): PNode =
##[
nim transforms these quite differently:
proc someType*(): int =
## foo
result = 3
=>
result =
## foo
3;
proc someType*(): int =
## foo
3
=>
## foo
result = 3;
so we normalize the results to get to the statement list containing the
(0 or more) doc comments and runnableExamples.
]##
result = n[bodyPos]
# This won't be transformed: result.id = 10. Namely result[0].kind != nkSym.
if result.kind == nkAsgn and result[0].kind == nkSym and
n.len > bodyPos+1 and n[bodyPos+1].kind == nkSym:
doAssert result.len == 2
result = result[1]
proc getAllRunnableExamples(d: PDoc, n: PNode, dest: var Rope) =
var n = n
var state = rsStart
template fn(n2) =
state = getAllRunnableExamplesImpl(d, n2, dest, state)
dest.add genComment(d, n).rope
case n.kind
of routineDefs:
n = n.getRoutineBody
case n.kind
of nkCommentStmt, nkCallKinds: fn(n)
else:
for i in 0..<n.safeLen:
fn(n[i])
if state == rsDone: return
else: fn(n)
proc isVisible(d: PDoc; n: PNode): bool =
result = false
@@ -621,7 +717,7 @@ proc complexName(k: TSymKind, n: PNode, baseName: string): string =
of skTemplate: result.add(".t")
of skConverter: result.add(".c")
else: discard
if n.len > paramsPos and n[paramsPos].kind == nkFormalParams:
if n.safeLen > paramsPos and n[paramsPos].kind == nkFormalParams:
let params = renderParamTypes(n[paramsPos])
if params.len > 0:
result.add(defaultParamSeparator)
@@ -692,8 +788,12 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
var result: Rope = nil
var literal, plainName = ""
var kind = tkEof
var comm = genRecComment(d, n) # call this here for the side-effect!
getAllRunnableExamples(d, n, comm)
var comm: Rope = nil
if n.kind in routineDefs:
getAllRunnableExamples(d, n, comm)
else:
comm.add genRecComment(d, n)
var r: TSrcGen
# Obtain the plain rendered string for hyperlink titles.
initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments,
@@ -751,7 +851,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
symbolOrIdRope, plainSymbolEncRope, symbolOrIdEncRope, seeSrcRope,
deprecationMsgRope]))
let external = d.destFile.relativeTo(d.conf.outDir, '/').changeFileExt(HtmlExt).string
let external = d.destFile.AbsoluteFile.relativeTo(d.conf.outDir, '/').changeFileExt(HtmlExt).string
var attype: Rope
if k in routineKinds and nameNode.kind == nkSym:
@@ -768,11 +868,13 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
xmltree.escape(getPlainDocstring(e).docstringSummary))
d.toc[k].add(ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item.toc"),
["name", "header", "desc", "itemID", "header_plain", "itemSym",
"itemSymOrID", "itemSymEnc", "itemSymOrIDEnc", "attype"],
[rope(getName(d, nameNode, d.splitAfter)), result, comm,
itemIDRope, plainNameRope, plainSymbolRope, symbolOrIdRope,
plainSymbolEncRope, symbolOrIdEncRope, attype]))
["name", "header_plain", "itemSymOrIDEnc"],
[nameRope, plainNameRope, symbolOrIdEncRope]))
d.tocTable[k].mgetOrPut(cleanPlainSymbol, nil).add(ropeFormatNamedVars(
d.conf, getConfigVar(d.conf, "doc.item.tocTable"),
["name", "header_plain", "itemSymOrID", "itemSymOrIDEnc"],
[nameRope, plainNameRope, rope(symbolOrId.replace(",", ",<wbr>")), symbolOrIdEncRope]))
# Ironically for types the complexSymbol is *cleaner* than the plainName
# because it doesn't include object fields or documentation comments. So we
@@ -849,7 +951,7 @@ proc traceDeps(d: PDoc, it: PNode) =
if d.section[k] != nil: d.section[k].add(", ")
dispA(d.conf, d.section[k],
"<a class=\"reference external\" href=\"$2\">$1</a>",
"$1", [rope esc(d.target, changeFileExt(external, "")),
"$1", [rope esc(d.target, external.prettyLink),
rope changeFileExt(external, "html")])
proc exportSym(d: PDoc; s: PSym) =
@@ -859,18 +961,22 @@ proc exportSym(d: PDoc; s: PSym) =
if d.section[k] != nil: d.section[k].add(", ")
dispA(d.conf, d.section[k],
"<a class=\"reference external\" href=\"$2\">$1</a>",
"$1", [rope esc(d.target, changeFileExt(external, "")),
"$1", [rope esc(d.target, external.prettyLink),
rope changeFileExt(external, "html")])
elif s.kind != skModule and s.owner != nil:
let module = originatingModule(s)
if belongsToPackage(d.conf, module):
let external = externalDep(d, module)
let
complexSymbol = complexName(s.kind, s.ast, s.name.s)
symbolOrIdRope = rope(d.newUniquePlainSymbol(complexSymbol))
external = externalDep(d, module)
if d.section[k] != nil: d.section[k].add(", ")
# XXX proper anchor generation here
dispA(d.conf, d.section[k],
"<a href=\"$2#$1\"><span class=\"Identifier\">$1</span></a>",
"<a href=\"$2#$3\"><span class=\"Identifier\">$1</span></a>",
"$1", [rope esc(d.target, s.name.s),
rope changeFileExt(external, "html")])
rope changeFileExt(external, "html"),
symbolOrIdRope])
proc documentNewEffect(cache: IdentCache; n: PNode): PNode =
let s = n[namePos].sym
@@ -895,8 +1001,8 @@ proc documentEffect(cache: IdentCache; n, x: PNode, effectType: TSpecialWord, id
# set the type so that the following analysis doesn't screw up:
effects[i].typ = real[i].typ
result = newNode(nkExprColonExpr, n.info, @[
newIdentNode(getIdent(cache, specialWords[effectType]), n.info), effects])
result = newTreeI(nkExprColonExpr, n.info,
newIdentNode(getIdent(cache, $effectType), n.info), effects)
proc documentWriteEffect(cache: IdentCache; n: PNode; flag: TSymFlag; pragmaName: string): PNode =
let s = n[namePos].sym
@@ -908,8 +1014,8 @@ proc documentWriteEffect(cache: IdentCache; n: PNode; flag: TSymFlag; pragmaName
effects.add params[i]
if effects.len > 0:
result = newNode(nkExprColonExpr, n.info, @[
newIdentNode(getIdent(cache, pragmaName), n.info), effects])
result = newTreeI(nkExprColonExpr, n.info,
newIdentNode(getIdent(cache, pragmaName), n.info), effects)
proc documentRaises*(cache: IdentCache; n: PNode) =
if n[namePos].kind != nkSym: return
@@ -973,7 +1079,7 @@ proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
if it.kind == nkSym:
if d.module != nil and d.module == it.sym.owner:
generateDoc(d, it.sym.ast, orig, kForceExport)
else:
elif it.sym.ast != nil:
exportSym(d, it.sym)
of nkExportExceptStmt: discard "transformed into nkExportStmt by semExportExcept"
of nkFromStmt, nkImportExceptStmt: traceDeps(d, n[0])
@@ -1070,7 +1176,7 @@ proc generateTags*(d: PDoc, n: PNode, r: var Rope) =
generateTags(d, lastSon(n[0]), r)
else: discard
proc genSection(d: PDoc, kind: TSymKind) =
proc genSection(d: PDoc, kind: TSymKind, groupedToc = false) =
const sectionNames: array[skModule..skField, string] = [
"Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Funcs",
"Methods", "Iterators", "Converters", "Macros", "Templates", "Exports"
@@ -1080,17 +1186,23 @@ proc genSection(d: PDoc, kind: TSymKind) =
d.section[kind] = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.section"), [
"sectionid", "sectionTitle", "sectionTitleID", "content"], [
ord(kind).rope, title, rope(ord(kind) + 50), d.section[kind]])
var tocSource = d.toc
if groupedToc:
for p in d.tocTable[kind].keys:
d.toc2[kind].add ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.section.toc2"), [
"sectionid", "sectionTitle", "sectionTitleID", "content", "plainName"], [
ord(kind).rope, title, rope(ord(kind) + 50), d.tocTable[kind][p], p.rope])
tocSource = d.toc2
d.toc[kind] = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.section.toc"), [
"sectionid", "sectionTitle", "sectionTitleID", "content"], [
ord(kind).rope, title, rope(ord(kind) + 50), d.toc[kind]])
ord(kind).rope, title, rope(ord(kind) + 50), tocSource[kind]])
const nimdocOutCss = "nimdoc.out.css"
# `out` to make it easier to use with gitignore in user's repos
proc relLink(outDir: AbsoluteDir, destFile: AbsoluteFile, linkto: RelativeFile): Rope =
rope($relativeTo(outDir / linkto, destFile.splitFile().dir, '/'))
proc cssHref(outDir: AbsoluteDir, destFile: AbsoluteFile): Rope =
rope($relativeTo(outDir / nimdocOutCss.RelativeFile, destFile.splitFile().dir, '/'))
proc genOutFile(d: PDoc): Rope =
proc genOutFile(d: PDoc, groupedToc = false): Rope =
var
code, content: Rope
title = ""
@@ -1098,36 +1210,42 @@ proc genOutFile(d: PDoc): Rope =
var tmp = ""
renderTocEntries(d[], j, 1, tmp)
var toc = tmp.rope
for i in low(TSymKind)..high(TSymKind):
genSection(d, i)
for i in TSymKind:
var shouldSort = i in {skProc, skFunc} and groupedToc
genSection(d, i, shouldSort)
toc.add(d.toc[i])
if toc != nil:
toc = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.toc"), ["content"], [toc])
for i in low(TSymKind)..high(TSymKind): code.add(d.section[i])
for i in TSymKind: code.add(d.section[i])
# Extract the title. Non API modules generate an entry in the index table.
if d.meta[metaTitle].len != 0:
title = d.meta[metaTitle]
let external = presentationPath(d.conf, AbsoluteFile d.filename).changeFileExt(HtmlExt).string.nativeToUnix
let external = presentationPath(d.conf, AbsoluteFile d.filename).changeFileExt(HtmlExt).string.nativeToUnixPath
setIndexTerm(d[], external, "", title)
else:
# Modules get an automatic title for the HTML, but no entry in the index.
# better than `extractFilename(changeFileExt(d.filename, ""))` as it disambiguates dups
title = $presentationPath(d.conf, AbsoluteFile d.filename, isTitle = true).changeFileExt("")
let bodyname = if d.hasToc and not d.isPureRst: "doc.body_toc_group"
var groupsection = getConfigVar(d.conf, "doc.body_toc_groupsection")
let bodyname = if d.hasToc and not d.isPureRst:
groupsection.setLen 0
"doc.body_toc_group"
elif d.hasToc: "doc.body_toc"
else: "doc.body_no_toc"
content = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, bodyname), ["title",
"tableofcontents", "moduledesc", "date", "time", "content", "deprecationMsg"],
"tableofcontents", "moduledesc", "date", "time", "content", "deprecationMsg", "theindexhref", "body_toc_groupsection"],
[title.rope, toc, d.modDesc, rope(getDateStr()),
rope(getClockStr()), code, d.modDeprecationMsg])
rope(getClockStr()), code, d.modDeprecationMsg, relLink(d.conf.outDir, d.destFile.AbsoluteFile, theindexFname.RelativeFile), groupsection.rope])
if optCompileOnly notin d.conf.globalOptions:
# XXX what is this hack doing here? 'optCompileOnly' means raw output!?
code = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.file"), [
"nimdoccss", "title", "tableofcontents", "moduledesc", "date", "time",
"nimdoccss", "dochackjs", "title", "tableofcontents", "moduledesc", "date", "time",
"content", "author", "version", "analytics", "deprecationMsg"],
[cssHref(d.conf.outDir, d.destFile), title.rope, toc, d.modDesc, rope(getDateStr()), rope(getClockStr()),
[relLink(d.conf.outDir, d.destFile.AbsoluteFile, nimdocOutCss.RelativeFile),
relLink(d.conf.outDir, d.destFile.AbsoluteFile, docHackJsFname.RelativeFile),
title.rope, toc, d.modDesc, rope(getDateStr()), rope(getClockStr()),
content, d.meta[metaAuthor].rope, d.meta[metaVersion].rope, d.analytics.rope, d.modDeprecationMsg])
else:
code = content
@@ -1135,38 +1253,39 @@ proc genOutFile(d: PDoc): Rope =
proc generateIndex*(d: PDoc) =
if optGenIndex in d.conf.globalOptions:
let dir = d.conf.docOutDir(htmldocsDir)
let dir = d.conf.outDir
createDir(dir)
let dest = dir / changeFileExt(presentationPath(d.conf, AbsoluteFile d.filename), IndexExt)
writeIndexFile(d[], dest.string)
proc updateOutfile(d: PDoc, outfile: AbsoluteFile) =
if d.module == nil or sfMainModule in d.module.flags: # nil for eg for commandRst2Html
if d.conf.outDir.isEmpty: d.conf.outDir = d.conf.docOutDir
if d.module == nil or sfMainModule in d.module.flags: # nil for e.g. for commandRst2Html
if d.conf.outFile.isEmpty:
d.conf.outFile = outfile.relativeTo(d.conf.outDir)
if isAbsolute(d.conf.outFile.string):
d.conf.outFile = splitPath(d.conf.outFile.string)[1].RelativeFile
proc writeOutput*(d: PDoc, useWarning = false) =
proc writeOutput*(d: PDoc, useWarning = false, groupedToc = false) =
runAllExamples(d)
var content = genOutFile(d)
var content = genOutFile(d, groupedToc)
if optStdout in d.conf.globalOptions:
writeRope(stdout, content)
else:
template outfile: untyped = d.destFile
#let outfile = getOutFile2(d.conf, shortenDir(d.conf, filename), outExt, htmldocsDir)
template outfile: untyped = d.destFile.AbsoluteFile
#let outfile = getOutFile2(d.conf, shortenDir(d.conf, filename), outExt)
let dir = outfile.splitFile.dir
createDir(dir)
updateOutfile(d, outfile)
if not writeRope(content, outfile):
rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile,
outfile.string)
elif not d.wroteCss:
let cssSource = $d.conf.getPrefixDir() / "doc" / "nimdoc.css"
let cssDest = $dir / nimdocOutCss
copyFile(cssSource, cssDest)
d.wroteCss = true
elif not d.wroteSupportFiles: # nimdoc.css + dochack.js
let nimr = $d.conf.getPrefixDir()
copyFile(docCss.interp(nimr = nimr), $d.conf.outDir / nimdocOutCss)
if optGenIndex in d.conf.globalOptions:
let docHackJs2 = getDocHacksJs(nimr, nim = getAppFilename())
copyFile(docHackJs2, $d.conf.outDir / docHackJs2.lastPathPart)
d.wroteSupportFiles = true
proc writeOutputJson*(d: PDoc, useWarning = false) =
runAllExamples(d)
@@ -1181,18 +1300,20 @@ proc writeOutputJson*(d: PDoc, useWarning = false) =
write(stdout, $content)
else:
var f: File
if open(f, d.destFile.string, fmWrite):
if open(f, d.destFile, fmWrite):
write(f, $content)
close(f)
updateOutfile(d, d.destFile)
updateOutfile(d, d.destFile.AbsoluteFile)
else:
localError(d.conf, newLineInfo(d.conf, AbsoluteFile d.filename, -1, -1),
warnUser, "unable to open file \"" & d.destFile.string &
warnUser, "unable to open file \"" & d.destFile &
"\" for writing")
proc handleDocOutputOptions*(conf: ConfigRef) =
if optWholeProject in conf.globalOptions:
# Backward compatibility with previous versions
# xxx this is buggy when user provides `nim doc --project -o:sub/bar.html main`,
# it'd write to `sub/bar.html/main.html`
conf.outDir = AbsoluteDir(conf.outDir / conf.outFile)
proc commandDoc*(cache: IdentCache, conf: ConfigRef) =
@@ -1267,18 +1388,20 @@ proc commandTags*(cache: IdentCache, conf: ConfigRef) =
if not writeRope(content, filename):
rawMessage(conf, errCannotOpenFile, filename.string)
proc commandBuildIndex*(cache: IdentCache, conf: ConfigRef) =
var content = mergeIndexes(conf.projectFull.string).rope
proc commandBuildIndex*(conf: ConfigRef, dir: string, outFile = RelativeFile"") =
var content = mergeIndexes(dir).rope
var outFile = RelativeFile"theindex"
if conf.outFile != RelativeFile"":
outFile = conf.outFile
var outFile = outFile
if outFile.isEmpty: outFile = theindexFname.RelativeFile.changeFileExt("")
let filename = getOutFile(conf, outFile, HtmlExt)
let code = ropeFormatNamedVars(conf, getConfigVar(conf, "doc.file"), [
"nimdoccss", "title", "tableofcontents", "moduledesc", "date", "time",
"nimdoccss", "dochackjs",
"title", "tableofcontents", "moduledesc", "date", "time",
"content", "author", "version", "analytics"],
[cssHref(conf.outDir, filename), rope"Index", nil, nil, rope(getDateStr()),
[relLink(conf.outDir, filename, nimdocOutCss.RelativeFile),
relLink(conf.outDir, filename, docHackJsFname.RelativeFile),
rope"Index", nil, nil, rope(getDateStr()),
rope(getClockStr()), content, nil, nil, nil])
# no analytics because context is not available

View File

@@ -29,6 +29,7 @@ proc shouldProcess(g: PGen): bool =
template closeImpl(body: untyped) {.dirty.} =
var g = PGen(p)
let useWarning = sfMainModule notin g.module.flags
let groupedToc = true
if shouldProcess(g):
body
try:
@@ -38,7 +39,7 @@ template closeImpl(body: untyped) {.dirty.} =
proc close(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
closeImpl:
writeOutput(g.doc, useWarning)
writeOutput(g.doc, useWarning, groupedToc)
proc closeJson(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
closeImpl:

View File

@@ -17,6 +17,8 @@ when defined(windows):
const libcDll = "msvcrt.dll"
elif defined(linux):
const libcDll = "libc.so(.6|.5|)"
elif defined(openbsd):
const libcDll = "/usr/lib/libc.so(.95.1|)"
elif defined(bsd):
const libcDll = "/lib/libc.so.7"
elif defined(osx):
@@ -102,7 +104,7 @@ proc mapType(conf: ConfigRef, t: ast.PType): ptr libffi.Type =
proc mapCallConv(conf: ConfigRef, cc: TCallingConvention, info: TLineInfo): TABI =
case cc
of ccDefault: result = DEFAULT_ABI
of ccNimCall: result = DEFAULT_ABI
of ccStdCall: result = when defined(windows) and defined(x86): STDCALL else: DEFAULT_ABI
of ccCDecl: result = DEFAULT_ABI
else:

View File

@@ -21,6 +21,7 @@ type
# new symbol
config: ConfigRef
ic: IdentCache
instID: int
proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
result = copyNode(a)
@@ -53,8 +54,8 @@ 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)
if sfGenSym in s.flags and optNimV019 notin c.config.globalOptions:
result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $x.id),
if sfGenSym in s.flags:
result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $c.instID),
if c.instLines: actual.info else: templ.info)
else:
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
@@ -166,7 +167,7 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
conf: ConfigRef;
ic: IdentCache;
ic: IdentCache; instID: ref int;
fromHlo=false): PNode =
inc(conf.evalTemplateCounter)
if conf.evalTemplateCounter > evalTemplateLimit:
@@ -181,6 +182,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
ctx.config = conf
ctx.ic = ic
initIdTable(ctx.mapping)
ctx.instID = instID[]
let body = tmpl.getBody
#echo "instantion of ", renderTree(body, {renderIds})
@@ -203,3 +205,5 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
#if ctx.debugActive:
# echo "instantion of ", renderTree(result, {renderIds})
dec(conf.evalTemplateCounter)
# The instID must be unique for every template instantiation, so we increment it here
inc instID[]

View File

@@ -143,16 +143,16 @@ compiler vcc:
result = (
name: "vcc",
objExt: "obj",
optSpeed: " /Ogityb2 /G7 ",
optSize: " /O1 /G7 ",
optSpeed: " /Ogityb2 ",
optSize: " /O1 ",
compilerExe: "cl",
cppCompiler: "cl",
compileTmpl: "/c$vccplatform $options $include /Fo$objfile $file",
buildGui: " /link /SUBSYSTEM:WINDOWS ",
compileTmpl: "/c$vccplatform $options $include /nologo /Fo$objfile $file",
buildGui: " /SUBSYSTEM:WINDOWS user32.lib ",
buildDll: " /LD",
buildLib: "lib /OUT:$libfile $objfiles",
linkerExe: "cl",
linkTmpl: "$builddll$vccplatform /Fe$exefile $objfiles $buildgui $options",
linkTmpl: "$builddll$vccplatform /Fe$exefile $objfiles $buildgui /nologo $options",
includeCmd: " /I",
linkDirCmd: " /LIBPATH:",
linkLibCmd: " $1.lib",
@@ -170,6 +170,7 @@ compiler clangcl:
result.compilerExe = "clang-cl"
result.cppCompiler = "clang-cl"
result.linkerExe = "clang-cl"
result.linkTmpl = "-fuse-ld=lld " & result.linkTmpl
# Intel C/C++ Compiler
compiler icl:
@@ -185,32 +186,6 @@ compiler icc:
result.compilerExe = "icc"
result.linkerExe = "icc"
# Local C Compiler
compiler lcc:
result = (
name: "lcc",
objExt: "obj",
optSpeed: " -O -p6 ",
optSize: " -O -p6 ",
compilerExe: "lcc",
cppCompiler: "",
compileTmpl: "$options $include -Fo$objfile $file",
buildGui: " -subsystem windows",
buildDll: " -dll",
buildLib: "", # XXX: not supported yet
linkerExe: "lcclnk",
linkTmpl: "$options $buildgui $builddll -O $exefile $objfiles",
includeCmd: " -I",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: " -g5 ",
pic: "",
asmStmtFrmt: "_asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {})
# Borland C Compiler
compiler bcc:
result = (
@@ -238,58 +213,6 @@ compiler bcc:
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard,
hasAttribute})
# Digital Mars C Compiler
compiler dmc:
result = (
name: "dmc",
objExt: "obj",
optSpeed: " -ff -o -6 ",
optSize: " -ff -o -6 ",
compilerExe: "dmc",
cppCompiler: "",
compileTmpl: "-c $options $include -o$objfile $file",
buildGui: " -L/exet:nt/su:windows",
buildDll: " -WD",
buildLib: "", # XXX: not supported yet
linkerExe: "dmc",
linkTmpl: "$options $buildgui $builddll -o$exefile $objfiles",
includeCmd: " -I",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: " -g ",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$3$n$1 $2",
produceAsm: "",
cppXsupport: "",
props: {hasCpp})
# Watcom C Compiler
compiler wcc:
result = (
name: "wcc",
objExt: "obj",
optSpeed: " -ox -on -6 -d0 -fp6 -zW ",
optSize: "",
compilerExe: "wcl386",
cppCompiler: "",
compileTmpl: "-c $options $include -fo=$objfile $file",
buildGui: " -bw",
buildDll: " -bd",
buildLib: "", # XXX: not supported yet
linkerExe: "wcl386",
linkTmpl: "$options $buildgui $builddll -fe=$exefile $objfiles ",
includeCmd: " -i=",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: " -d2 ",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {hasCpp})
# Tiny C Compiler
compiler tcc:
result = (
@@ -316,43 +239,16 @@ compiler tcc:
cppXsupport: "",
props: {hasSwitchRange, hasComputedGoto, hasGnuAsm})
# Pelles C Compiler
compiler pcc:
# Pelles C
result = (
name: "pcc",
objExt: "obj",
optSpeed: " -Ox ",
optSize: " -Os ",
compilerExe: "cc",
cppCompiler: "",
compileTmpl: "-c $options $include -Fo$objfile $file",
buildGui: " -SUBSYSTEM:WINDOWS",
buildDll: " -DLL",
buildLib: "", # XXX: not supported yet
linkerExe: "cc",
linkTmpl: "$options $buildgui $builddll -OUT:$exefile $objfiles",
includeCmd: " -I",
linkDirCmd: "", # XXX: not supported yet
linkLibCmd: "", # XXX: not supported yet
debug: " -Zi ",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {})
# Your C Compiler
compiler ucc:
compiler envcc:
result = (
name: "ucc",
name: "env",
objExt: "o",
optSpeed: " -O3 ",
optSize: " -O1 ",
compilerExe: "cc",
compilerExe: "",
cppCompiler: "",
compileTmpl: "-c $options $include -o $objfile $file",
compileTmpl: "-c $ccenvflags $options $include -o $objfile $file",
buildGui: "",
buildDll: " -shared ",
buildLib: "", # XXX: not supported yet
@@ -367,7 +263,7 @@ compiler ucc:
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {})
props: {hasGnuAsm})
const
CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [
@@ -375,23 +271,16 @@ const
nintendoSwitchGCC(),
llvmGcc(),
clang(),
lcc(),
bcc(),
dmc(),
wcc(),
vcc(),
tcc(),
pcc(),
ucc(),
envcc(),
icl(),
icc(),
clangcl()]
hExt* = ".h"
proc libNameTmpl(conf: ConfigRef): string {.inline.} =
result = if conf.target.targetOS == osWindows: "$1.lib" else: "lib$1.a"
proc nameToCC*(name: string): TSystemCC =
## Returns the kind of compiler referred to by `name`, or ccNone
## if the name doesn't refer to any known compiler.
@@ -414,15 +303,14 @@ proc isVSCompatible*(conf: ConfigRef): bool =
proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
# use ``cpu.os.cc`` for cross compilation, unless ``--compileOnly`` is given
# for niminst support
let fullSuffix =
if conf.cmd == cmdCompileToCpp:
".cpp" & suffix
elif conf.cmd == cmdCompileToOC:
".objc" & suffix
elif conf.cmd == cmdCompileToJS:
".js" & suffix
else:
suffix
var fullSuffix = suffix
case conf.backend
of backendCpp, backendJs, backendObjc: fullSuffix = "." & $conf.backend & suffix
of backendC: discard
of backendInvalid:
# during parsing of cfg files; we don't know the backend yet, no point in
# guessing wrong thing
return ""
if (conf.target.hostOS != conf.target.targetOS or conf.target.hostCPU != conf.target.targetCPU) and
optCompileOnly notin conf.globalOptions:
@@ -443,7 +331,7 @@ proc setCC*(conf: ConfigRef; ccname: string; info: TLineInfo) =
conf.compileOptions = getConfigVar(conf, conf.cCompiler, ".options.always")
conf.linkOptions = ""
conf.cCompilerPath = getConfigVar(conf, conf.cCompiler, ".path")
for i in low(CC)..high(CC): undefSymbol(conf.symbols, CC[i].name)
for c in CC: undefSymbol(conf.symbols, c.name)
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
proc addOpt(dest: var string, src: string) =
@@ -465,7 +353,7 @@ proc addCompileOptionCmd*(conf: ConfigRef; option: string) =
proc initVars*(conf: ConfigRef) =
# we need to define the symbol here, because ``CC`` may have never been set!
for i in low(CC)..high(CC): undefSymbol(conf.symbols, CC[i].name)
for c in CC: undefSymbol(conf.symbols, c.name)
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
addCompileOption(conf, getConfigVar(conf, conf.cCompiler, ".options.always"))
#addLinkOption(getConfigVar(cCompiler, ".options.linker"))
@@ -541,7 +429,6 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
proc cFileSpecificOptions(conf: ConfigRef; nimname, fullNimFile: string): string =
result = conf.compileOptions
addOpt(result, conf.cfileSpecificOptions.getOrDefault(fullNimFile))
for option in conf.compileOptionsCmd:
if strutils.find(result, option, 0) < 0:
@@ -562,6 +449,8 @@ proc cFileSpecificOptions(conf: ConfigRef; nimname, fullNimFile: string): string
let key = nimname & ".always"
if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key))
addOpt(result, conf.cfileSpecificOptions.getOrDefault(fullNimFile))
proc getCompileOptions(conf: ConfigRef): string =
result = cFileSpecificOptions(conf, "__dummy__", "__dummy__")
@@ -589,13 +478,25 @@ proc needsExeExt(conf: ConfigRef): bool {.inline.} =
(conf.target.hostOS == osWindows)
proc useCpp(conf: ConfigRef; cfile: AbsoluteFile): bool =
conf.cmd == cmdCompileToCpp and not cfile.string.endsWith(".c")
conf.backend == backendCpp and not cfile.string.endsWith(".c")
proc envFlags(conf: ConfigRef): string =
result = if conf.backend == backendCpp:
getEnv("CXXFLAGS")
else:
getEnv("CFLAGS")
proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: AbsoluteFile): string =
result = if useCpp(conf, cfile):
CC[compiler].cppCompiler
else:
CC[compiler].compilerExe
if compiler == ccEnv:
result = if useCpp(conf, cfile):
getEnv("CXX")
else:
getEnv("CC")
else:
result = if useCpp(conf, cfile):
CC[compiler].cppCompiler
else:
CC[compiler].compilerExe
if result.len == 0:
rawMessage(conf, errGenerated,
"Compiler '$1' doesn't support the requested target" %
@@ -631,7 +532,7 @@ proc ccHasSaneOverflow*(conf: ConfigRef): bool =
proc getLinkerExe(conf: ConfigRef; compiler: TSystemCC): string =
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
elif optMixedMode in conf.globalOptions and conf.cmd != cmdCompileToCpp: CC[compiler].cppCompiler
elif optMixedMode in conf.globalOptions and conf.backend != backendCpp: CC[compiler].cppCompiler
else: getCompilerExe(conf, compiler, AbsoluteFile"")
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
@@ -640,6 +541,11 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
# We produce files like module.nim.cpp, so the absolute Nim filename is not
# cfile.name but `cfile.cname.changeFileExt("")`:
var options = cFileSpecificOptions(conf, cfile.nimname, cfile.cname.changeFileExt("").string)
if useCpp(conf, cfile.cname):
# needs to be prepended so that --passc:-std=c++17 can override default.
# we could avoid allocation by making cFileSpecificOptions inplace
options = CC[c].cppXsupport & ' ' & options
var exe = getConfigVar(conf, c, ".exe")
if exe.len == 0: exe = getCompilerExe(conf, c, cfile.cname)
@@ -648,9 +554,6 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
ospNeedsPIC in platform.OS[conf.target.targetOS].props:
options.add(' ' & CC[c].pic)
if useCpp(conf, cfile.cname):
options.add(' ' & CC[c].cppXsupport)
if cfile.customArgs != "":
options.add ' '
options.add cfile.customArgs
@@ -691,7 +594,8 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
"dfile", dfile,
"file", cfsh, "objfile", quoteShell(objfile), "options", options,
"include", includeCmd, "nim", getPrefixDir(conf).string,
"lib", conf.libpath.string])
"lib", conf.libpath.string,
"ccenvflags", envFlags(conf)])
if optProduceAsm in conf.globalOptions:
if CC[conf.cCompiler].produceAsm.len > 0:
@@ -711,7 +615,8 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
"options", options, "include", includeCmd,
"nim", quoteShell(getPrefixDir(conf)),
"lib", quoteShell(conf.libpath),
"vccplatform", vccplatform(conf)])
"vccplatform", vccplatform(conf),
"ccenvflags", envFlags(conf)])
proc footprint(conf: ConfigRef; cfile: Cfile): SecureHash =
result = secureHash(
@@ -722,8 +627,7 @@ proc footprint(conf: ConfigRef; cfile: Cfile): SecureHash =
getCompileCFileCmd(conf, cfile))
proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
if conf.cmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM, cmdNone}:
return false
if conf.backend == backendJs: return false # pre-existing behavior, but not sure it's good
var hashFile = toGeneratedFile(conf, conf.withPackageName(cfile.cname), "sha1")
var currentHash = footprint(conf, cfile)
@@ -758,14 +662,7 @@ proc addExternalFileToCompile*(conf: ConfigRef; filename: AbsoluteFile) =
proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
objfiles: string, isDllBuild: bool): string =
if optGenStaticLib in conf.globalOptions:
var libname: string
if not conf.outFile.isEmpty:
libname = conf.outFile.string.expandTilde
if not libname.isAbsolute():
libname = getCurrentDir() / libname
else:
libname = (libNameTmpl(conf) % splitFile(conf.projectName).name)
result = CC[conf.cCompiler].buildLib % ["libfile", quoteShell(libname),
result = CC[conf.cCompiler].buildLib % ["libfile", quoteShell(output),
"objfiles", objfiles]
else:
var linkerExe = getConfigVar(conf, conf.cCompiler, ".linkerexe")
@@ -862,19 +759,16 @@ template tryExceptOSErrorMessage(conf: ConfigRef; errorPrefix: string = "", body
(ose.msg & " " & $ose.errorCode))
raise
proc getExtraCmds(conf: ConfigRef; output: AbsoluteFile): seq[string] =
when defined(macosx):
if optCDebug in conf.globalOptions and optGenStaticLib notin conf.globalOptions:
# if needed, add an option to skip or override location
result.add "dsymutil " & $(output).quoteShell
proc execLinkCmd(conf: ConfigRef; linkCmd: string) =
tryExceptOSErrorMessage(conf, "invocation of external linker program failed."):
execExternalProgram(conf, linkCmd, hintLinking)
proc maybeRunDsymutil(conf: ConfigRef; exe: AbsoluteFile) =
when defined(osx):
if optCDebug in conf.globalOptions and optGenStaticLib notin conf.globalOptions:
# if needed, add an option to skip or override location
let cmd = "dsymutil " & $(exe).quoteShell
conf.extraCmds.add cmd
tryExceptOSErrorMessage(conf, "invocation of dsymutil failed."):
execExternalProgram(conf, cmd, hintExecuting)
proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx: int)) =
let runCb = proc (idx: int, p: Process) =
let exitCode = p.peekExitCode
@@ -945,6 +839,7 @@ proc displayProgressCC(conf: ConfigRef, path, compileCmd: string): string =
proc callCCompiler*(conf: ConfigRef) =
var
linkCmd: string
extraCmds: seq[string]
if conf.globalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
return # speed up that call if only compiling and no script shall be
# generated
@@ -1015,6 +910,7 @@ proc callCCompiler*(conf: ConfigRef) =
let mainOutput = if optGenScript notin conf.globalOptions: conf.prepareToWriteOutput
else: AbsoluteFile(conf.projectName)
linkCmd = getLinkCmd(conf, mainOutput, objfiles)
extraCmds = getExtraCmds(conf, mainOutput)
if optCompileOnly notin conf.globalOptions:
const MaxCmdLen = when defined(windows): 8_000 else: 32_000
if linkCmd.len > MaxCmdLen:
@@ -1024,7 +920,8 @@ proc callCCompiler*(conf: ConfigRef) =
linkViaResponseFile(conf, linkCmd)
else:
execLinkCmd(conf, linkCmd)
maybeRunDsymutil(conf, mainOutput)
for cmd in extraCmds:
execExternalProgram(conf, cmd, hintExecuting)
else:
linkCmd = ""
if optGenScript in conf.globalOptions:
@@ -1098,10 +995,16 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
var buf = newStringOfCap(50)
let jsonFile = conf.getNimcacheDir / RelativeFile(conf.projectName & ".json")
conf.jsonBuildFile = jsonFile
let output = conf.absOutFile
var f: File
if open(f, jsonFile.string, fmWrite):
lit "{\"compile\":[\L"
lit "{\L"
lit "\"outputFile\": "
str $output
lit ",\L\"compile\":[\L"
cfiles(conf, f, buf, conf.toCompile, false)
lit "],\L\"link\":[\L"
var objfiles = ""
@@ -1109,10 +1012,10 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
linkfiles(conf, f, buf, objfiles, conf.toCompile, conf.externalToLink)
lit "],\L\"linkcmd\": "
str getLinkCmd(conf, conf.absOutFile, objfiles)
str getLinkCmd(conf, output, objfiles)
lit ",\L\"extraCmds\": "
lit $(%* conf.extraCmds)
lit $(%* getExtraCmds(conf, conf.absOutFile))
lit ",\L\"stdinInput\": "
lit $(%* conf.projectIsStdin)
@@ -1169,6 +1072,17 @@ proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
let jsonFile = toGeneratedFile(conf, projectfile, "json")
try:
let data = json.parseFile(jsonFile.string)
let output = data["outputFile"].getStr
createDir output.parentDir
let outputCurrent = $conf.absOutFile
if output != outputCurrent:
# previously, any specified output file would be silently ignored;
# simply copying won't work in some cases, for example with `extraCmds`,
# so we just make it an error, user should use same command for jsonscript
# as was used with --compileOnly.
globalError(conf, gCmdLineInfo, "jsonscript command outputFile '$1' must match '$2' which was specified during --compileOnly, see \"outputFile\" entry in '$3' " % [outputCurrent, output, jsonFile.string])
let toCompile = data["compile"]
doAssert toCompile.kind == JArray
var cmds: TStringSeq

View File

@@ -199,8 +199,8 @@ proc parseLine(p: var TTmplParser) =
inc(j)
llStreamWrite(p.outp, "\\n\"")
proc filterTmpl*(stdin: PLLStream, filename: AbsoluteFile,
call: PNode; conf: ConfigRef): PLLStream =
proc filterTmpl*(conf: ConfigRef, stdin: PLLStream, filename: AbsoluteFile,
call: PNode): PLLStream =
var p: TTmplParser
p.config = conf
p.info = newLineInfo(conf, filename, 0, 0)
@@ -214,9 +214,9 @@ proc filterTmpl*(stdin: PLLStream, filename: AbsoluteFile,
p.x = newStringOfCap(120)
# do not process the first line which contains the directive:
if llStreamReadLine(p.inp, p.x):
p.info.line = p.info.line + 1'u16
inc p.info.line
while llStreamReadLine(p.inp, p.x):
p.info.line = p.info.line + 1'u16
inc p.info.line
parseLine(p)
newLine(p)
result = p.outp

View File

@@ -1,89 +0,0 @@
#
#
# The Nim Compiler
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module implements for loop detection for better C code generation.
import ast, astalgo
const
someCmp = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
mLeI, mLeF64, mLeU, mLeEnum,
mLeCh, mLeB, mLePtr, mLtI, mLtF64, mLtU, mLtEnum,
mLtCh, mLtB, mLtPtr}
proc isCounter(s: PSym): bool {.inline.} =
s.kind in {skResult, skVar, skLet, skTemp} and
{sfGlobal, sfAddrTaken} * s.flags == {}
proc isCall(n: PNode): bool {.inline.} =
n.kind in nkCallKinds and n[0].kind == nkSym
proc fromSystem(op: PSym): bool = sfSystemModule in getModule(op).flags
proc getCounter(lastStmt: PNode): PSym =
if lastStmt.isCall:
let op = lastStmt.sym
if op.magic in {mDec, mInc} or
((op.name.s == "+=" or op.name.s == "-=") and op.fromSystem):
if op[1].kind == nkSym and isCounter(op[1].sym):
result = op[1].sym
proc counterInTree(n, loop: PNode; counter: PSym): bool =
# prune the search tree: within the loop the counter may be used:
if n == loop: return
case n.kind
of nkSym:
if n.sym == counter: return true
of nkVarSection, nkLetSection:
# definitions are fine!
for it in n:
if counterInTree(it.lastSon): return true
else:
for i in 0..<n.safeLen:
if counterInTree(n[i], loop, counter): return true
proc copyExcept(n: PNode, x, dest: PNode) =
if x == n: return
if n.kind in {nkStmtList, nkStmtListExpr}:
for i in 0..<n.len: copyExcept(n[i], x, dest)
else:
dest.add n
type
ForLoop* = object
counter*: PSym
init*, cond*, increment*, body*: PNode
proc extractForLoop*(loop, fullTree: PNode): ForLoop =
## returns 'counter == nil' if the while loop 'n' is not a for loop:
assert loop.kind == nkWhileStmt
let cond == loop[0]
if not cond.isCall: return
if cond[0].sym.magic notin someCmp: return
var lastStmt = loop[1]
while lastStmt.kind in {nkStmtList, nkStmtListExpr}:
lastStmt = lastStmt.lastSon
let counter = getCounter(lastStmt)
if counter.isNil or counter.ast.isNil: return
template `=~`(a, b): expr = a.kind == nkSym and a.sym == b
if cond[1] =~ counter or cond[2] =~ counter:
# ok, now check 'counter' is not used *after* the loop
if counterInTree(fullTree, loop, counter): return
# ok, success, fill in the fields:
result.counter = counter
result.init = counter.ast
result.cond = cond
result.increment = lastStmt
result.body = newNodeI(nkStmtList, loop[1].info)
copyExcept(loop[1], lastStmt, result.body)

View File

@@ -46,7 +46,7 @@ proc isLet(n: PNode): bool =
if n.sym.kind in {skLet, skTemp, skForVar}:
result = true
elif n.sym.kind == skParam and skipTypes(n.sym.typ,
abstractInst).kind != tyVar:
abstractInst).kind notin {tyVar}:
result = true
proc isVar(n: PNode): bool =
@@ -84,8 +84,8 @@ proc interestingCaseExpr*(m: PNode): bool = isLetLocation(m, true)
type
Operators* = object
opNot, opContains, opLe, opLt, opAnd, opOr, opIsNil, opEq: PSym
opAdd, opSub, opMul, opDiv, opLen: PSym
opNot*, opContains*, opLe*, opLt*, opAnd*, opOr*, opIsNil*, opEq*: PSym
opAdd*, opSub*, opMul*, opDiv*, opLen*: PSym
proc initOperators*(g: ModuleGraph): Operators =
result.opLe = createMagic(g, "<=", mLeI)
@@ -156,12 +156,12 @@ proc neg(n: PNode; o: Operators): PNode =
result[0] = newSymNode(o.opNot)
result[1] = n
proc buildCall(op: PSym; a: PNode): PNode =
proc buildCall*(op: PSym; a: PNode): PNode =
result = newNodeI(nkCall, a.info, 2)
result[0] = newSymNode(op)
result[1] = a
proc buildCall(op: PSym; a, b: PNode): PNode =
proc buildCall*(op: PSym; a, b: PNode): PNode =
result = newNodeI(nkInfix, a.info, 3)
result[0] = newSymNode(op)
result[1] = a
@@ -464,7 +464,7 @@ proc hasSubTree(n, x: PNode): bool =
for i in 0..n.safeLen-1:
if hasSubTree(n[i], x): return true
proc invalidateFacts*(m: var TModel, n: PNode) =
proc invalidateFacts*(s: var seq[PNode], n: PNode) =
# We are able to guard local vars (as opposed to 'let' variables)!
# 'while p != nil: f(p); p = p.next'
# This is actually quite easy to do:
@@ -482,8 +482,11 @@ proc invalidateFacts*(m: var TModel, n: PNode) =
# The same mechanism could be used for more complex data stored on the heap;
# procs that 'write: []' cannot invalidate 'n.kind' for instance. In fact, we
# could CSE these expressions then and help C's optimizer.
for i in 0..high(m.s):
if m.s[i] != nil and m.s[i].hasSubTree(n): m.s[i] = nil
for i in 0..high(s):
if s[i] != nil and s[i].hasSubTree(n): s[i] = nil
proc invalidateFacts*(m: var TModel, n: PNode) =
invalidateFacts(m.s, n)
proc valuesUnequal(a, b: PNode): bool =
if a.isValue and b.isValue:

View File

@@ -110,8 +110,8 @@ proc newIdentCache*(): IdentCache =
result.idDelegator = result.getIdent":delegator"
result.emptyIdent = result.getIdent("")
# initialize the keywords:
for s in succ(low(specialWords))..high(specialWords):
result.getIdent(specialWords[s], hashIgnoreStyle(specialWords[s])).id = ord(s)
for s in succ(low(TSpecialWord))..high(TSpecialWord):
result.getIdent($s, hashIgnoreStyle($s)).id = ord(s)
proc whichKeyword*(id: PIdent): TSpecialWord =
if id.id < 0: result = wInvalid

View File

@@ -187,10 +187,9 @@ proc impMod(c: PContext; it: PNode; importStmtResult: PNode) =
let it = transformImportAs(c, it)
let m = myImportModule(c, it, importStmtResult)
if m != nil:
var emptySet: IntSet
# ``addDecl`` needs to be done before ``importAllSymbols``!
addDecl(c, m, it.info) # add symbol to symbol table of module
importAllSymbolsExcept(c, m, emptySet)
importAllSymbols(c, m)
#importForwarded(c, m.ast, emptySet, m)
proc evalImport*(c: PContext, n: PNode): PNode =

18
compiler/index.nim Normal file
View File

@@ -0,0 +1,18 @@
##[
This module only exists to generate docs for the compiler.
## links
* [main docs](../lib.html)
* [compiler user guide](../nimc.html)
* [Internals of the Nim Compiler](../intern.html)
]##
#[
note: this is named `index` so that navigating to https://nim-lang.github.io/Nim/compiler/
will work.
xxx this should also import other modules, not transitively imported by `compiler/nim.nim`,
eg `evalffi`, otherwise these aren't shown. A glob could be used at CT.
]#
import nim

File diff suppressed because it is too large Load Diff

View File

@@ -35,9 +35,8 @@ App: Console
License: "copying.txt"
[Config]
Files: "config/nim.cfg"
Files: "config/nimdoc.cfg"
Files: "config/nimdoc.tex.cfg"
Files: "config/*.cfg"
Files: "config/config.nims"
[Documentation]
; Files: "doc/*.html"

View File

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

View File

@@ -0,0 +1,126 @@
#
#
# The Nim Compiler
# (c) Copyright 2020 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Implementation of the check that `recover` needs, see
## https://github.com/nim-lang/RFCs/issues/244 for more details.
import
ast, types, renderer, idents, intsets
proc canAlias(arg, ret: PType; marker: var IntSet): bool
proc canAliasN(arg: PType; n: PNode; marker: var IntSet): bool =
case n.kind
of nkRecList:
for i in 0..<n.len:
result = canAliasN(arg, n[i], marker)
if result: return
of nkRecCase:
assert(n[0].kind == nkSym)
result = canAliasN(arg, n[0], marker)
if result: return
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = canAliasN(arg, lastSon(n[i]), marker)
if result: return
else: discard
of nkSym:
result = canAlias(arg, n.sym.typ, marker)
else: discard
proc canAlias(arg, ret: PType; marker: var IntSet): bool =
if containsOrIncl(marker, ret.id):
return false
if ret.kind in {tyPtr, tyPointer}:
# unsafe so we don't care:
return false
if compareTypes(arg, ret, dcEqIgnoreDistinct):
return true
case ret.kind
of tyObject:
if isFinal(ret):
result = canAliasN(arg, ret.n, marker)
if not result and ret.len > 0 and ret[0] != nil:
result = canAlias(arg, ret[0], marker)
else:
result = true
of tyTuple:
for i in 0..<ret.len:
result = canAlias(arg, ret[i], marker)
if result: break
of tyArray, tySequence, tyDistinct, tyGenericInst,
tyAlias, tyInferred, tySink, tyLent, tyOwned, tyRef:
result = canAlias(arg, ret.lastSon, marker)
of tyProc:
result = ret.callConv == ccClosure
else:
result = false
proc isValueOnlyType(t: PType): bool =
# t doesn't contain pointers and references
proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr, tyVar, tyLent}
result = not types.searchTypeFor(t, wrap)
proc canAlias*(arg, ret: PType): bool =
if isValueOnlyType(arg):
# can alias only with unsafeAddr(arg.x) and we don't care if it is not safe
result = false
else:
var marker = initIntSet()
result = canAlias(arg, ret, marker)
proc checkIsolate*(n: PNode): bool =
if types.containsTyRef(n.typ):
# XXX Maybe require that 'n.typ' is acyclic. This is not much
# worse than the already exisiting inheritance and closure restrictions.
case n.kind
of nkCharLit..nkNilLit:
result = true
of nkCallKinds:
if n[0].typ.flags * {tfGcSafe, tfNoSideEffect} == {}:
return false
for i in 1..<n.len:
if checkIsolate(n[i]):
discard "fine, it is isolated already"
else:
let argType = n[i].typ
if argType != nil and not isCompileTimeOnly(argType) and containsTyRef(argType):
if argType.canAlias(n.typ):
return false
result = true
of nkIfStmt, nkIfExpr:
for it in n:
result = checkIsolate(it.lastSon)
if not result: break
of nkCaseStmt, nkObjConstr:
for i in 1..<n.len:
result = checkIsolate(n[i].lastSon)
if not result: break
of nkBracket, nkTupleConstr, nkPar:
for it in n:
result = checkIsolate(it)
if not result: break
of nkHiddenStdConv, nkHiddenSubConv, nkCast, nkConv:
result = checkIsolate(n[1])
of nkObjUpConv, nkObjDownConv, nkDotExpr:
result = checkIsolate(n[0])
of nkStmtList, nkStmtListExpr:
if n.len > 0:
result = checkIsolate(n[^1])
else:
result = false
else:
# unanalysable expression:
result = false
else:
# no ref, no cry:
result = true

View File

@@ -14,27 +14,28 @@ The JS code generator contains only 2 tricks:
Trick 1
-------
Some locations (for example 'var int') require "fat pointers" (``etyBaseIndex``)
Some locations (for example 'var int') require "fat pointers" (`etyBaseIndex`)
which are pairs (array, index). The derefence operation is then 'array[index]'.
Check ``mapType`` for the details.
Check `mapType` for the details.
Trick 2
-------
It is preferable to generate '||' and '&&' if possible since that is more
idiomatic and hence should be friendlier for the JS JIT implementation. However
code like ``foo and (let bar = baz())`` cannot be translated this way. Instead
the expressions need to be transformed into statements. ``isSimpleExpr``
code like `foo and (let bar = baz())` cannot be translated this way. Instead
the expressions need to be transformed into statements. `isSimpleExpr`
implements the required case distinction.
"""
import
ast, strutils, trees, magicsys, options,
nversion, msgs, idents, types, tables,
ropes, math, passes, ccgutils, wordrecg, renderer,
intsets, cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
transf, injectdestructors, sourcemap, json, sets
ast, trees, magicsys, options,
nversion, msgs, idents, types,
ropes, passes, ccgutils, wordrecg, renderer,
cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
transf, injectdestructors, sourcemap
import json, sets, math, tables, intsets, strutils
from modulegraphs import ModuleGraph, PPassContext
@@ -86,6 +87,7 @@ type
generatedSyms: IntSet
typeInfoGenerated: IntSet
unique: int # for temp identifier generation
inSystem: bool
PProc = ref TProc
TProc = object
@@ -159,6 +161,14 @@ proc newProc(globals: PGlobals, module: BModule, procDef: PNode,
extraIndent: int(procDef != nil))
if procDef != nil: result.prc = procDef[namePos].sym
proc initProcOptions(module: BModule): TOptions =
result = module.config.options
if PGlobals(module.graph.backend).inSystem:
result.excl(optStackTrace)
proc newInitProc(globals: PGlobals, module: BModule): PProc =
result = newProc(globals, module, nil, initProcOptions(module))
proc declareGlobal(p: PProc; id: int; r: Rope) =
if p.prc != nil and not p.declaredGlobals.containsOrIncl(id):
p.locals.addf("global $1;$n", [r])
@@ -184,7 +194,7 @@ proc mapType(typ: PType): TJSTypeKind =
of tyBool: result = etyBool
of tyFloat..tyFloat128: result = etyFloat
of tySet: result = etyObject # map a set to a table
of tyString, tySequence, tyOpt: result = etySeq
of tyString, tySequence: result = etySeq
of tyObject, tyArray, tyTuple, tyOpenArray, tyVarargs, tyUncheckedArray:
result = etyObject
of tyNil: result = etyNull
@@ -201,12 +211,11 @@ proc mapType(typ: PType): TJSTypeKind =
else: result = etyNone
of tyProc: result = etyProc
of tyCString: result = etyString
of tyOptDeprecated: doAssert false
proc mapType(p: PProc; typ: PType): TJSTypeKind =
result = mapType(typ)
var mangled = initSet[string]()
proc mangleName(m: BModule, s: PSym): Rope =
proc validJsName(name: string): bool =
result = true
@@ -240,11 +249,7 @@ proc mangleName(m: BModule, s: PSym): Rope =
while i < s.name.s.len:
let c = s.name.s[i]
case c
of 'A'..'Z':
if i > 0 and s.name.s[i-1] in {'a'..'z'}:
x.add '_'
x.add(chr(c.ord - 'A'.ord + 'a'.ord))
of 'a'..'z', '_', '0'..'9':
of 'A'..'Z', 'a'..'z', '_', '0'..'9':
x.add c
else:
x.add("HEX" & toHex(ord(c), 2))
@@ -261,11 +266,6 @@ proc mangleName(m: BModule, s: PSym): Rope =
result.add(rope(s.id))
s.loc.r = result
# TODO: optimize
let s = $result
if '_' in s:
mangled.incl(s)
proc escapeJSString(s: string): string =
result = newStringOfCap(s.len + s.len shr 2)
result.add("\"")
@@ -466,7 +466,48 @@ proc maybeMakeTemp(p: PProc, n: PNode; x: TCompRes): tuple[a, tmp: Rope] =
else:
(a: a, tmp: b)
template binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
proc maybeMakeTempAssignable(p: PProc, n: PNode; x: TCompRes): tuple[a, tmp: Rope] =
var
a = x.rdLoc
b = a
if needsTemp(p, n):
# if we have tmp just use it
if x.tmpLoc != nil and (mapType(n.typ) == etyBaseIndex or n.kind in {nkHiddenDeref, nkDerefExpr}):
b = "$1[0][$1[1]]" % [x.tmpLoc]
result = (a: a, tmp: b)
elif x.tmpLoc != nil and n.kind == nkBracketExpr:
# genArrayAddr
var
address, index: TCompRes
first: Int128
gen(p, n[0], address)
gen(p, n[1], index)
let (m1, tmp1) = maybeMakeTemp(p, n[0], address)
let typ = skipTypes(n[0].typ, abstractPtrs)
if typ.kind == tyArray:
first = firstOrd(p.config, typ[0])
if optBoundsCheck in p.options:
useMagic(p, "chckIndx")
if first == 0: # save a couple chars
index.res = "chckIndx($1, 0, ($2).length-1)" % [index.res, tmp1]
else:
index.res = "chckIndx($1, $2, ($3).length+($2)-1)-($2)" % [
index.res, rope(first), tmp1]
elif first != 0:
index.res = "($1)-($2)" % [index.res, rope(first)]
else:
discard # index.res = index.res
let (n1, tmp2) = maybeMakeTemp(p, n[1], index)
result = (a: "$1[$2]" % [m1, n1], tmp: "$1[$2]" % [tmp1, tmp2])
# could also put here: nkDotExpr -> genFieldAccess, nkCheckedFieldExpr -> genCheckedFieldOp
# but the uses of maybeMakeTempAssignable don't need them
else:
result = (a: a, tmp: b)
else:
result = (a: a, tmp: b)
template binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string,
reassign = false) =
# $1 and $2 in the `frmt` string bind to lhs and rhs of the expr,
# if $3 or $4 are present they will be substituted with temps for
# lhs and rhs respectively
@@ -478,8 +519,11 @@ template binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
var
a, tmp = x.rdLoc
b, tmp2 = y.rdLoc
when "$3" in frmt: (a, tmp) = maybeMakeTemp(p, n[1], x)
when "$4" in frmt: (b, tmp2) = maybeMakeTemp(p, n[2], y)
when reassign:
(a, tmp) = maybeMakeTempAssignable(p, n[1], x)
else:
when "$3" 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
@@ -496,13 +540,13 @@ template unsignedTrimmer(size: BiggestInt): Rope =
size.unsignedTrimmerJS
proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string,
reassign = false) =
reassign: static[bool] = false) =
var x, y: TCompRes
gen(p, n[1], x)
gen(p, n[2], y)
let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
if reassign:
let (a, tmp) = maybeMakeTemp(p, n[1], x)
when reassign:
let (a, tmp) = maybeMakeTempAssignable(p, n[1], x)
r.res = "$1 = (($5 $2 $3) $4)" % [a, rope op, y.rdLoc, trimmer, tmp]
else:
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
@@ -541,11 +585,10 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
gen(p, n[1], r)
xLoc = r.rdLoc
template applyFormat(frmtA, frmtB: string) =
if i == 0:
r.res = frmtA % [xLoc, yLoc]
else:
r.res = frmtB % [xLoc, yLoc]
template applyFormat(frmt) =
r.res = frmt % [xLoc, yLoc]
template applyFormat(frmtA, frmtB) =
if i == 0: applyFormat(frmtA) else: applyFormat(frmtB)
case op:
of mAddI: applyFormat("addInt($1, $2)", "($1 + $2)")
@@ -560,8 +603,16 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mMulF64: applyFormat("($1 * $2)", "($1 * $2)")
of mDivF64: applyFormat("($1 / $2)", "($1 / $2)")
of mShrI: applyFormat("", "")
of mShlI: applyFormat("($1 << $2)", "($1 << $2)")
of mAshrI: applyFormat("($1 >> $2)", "($1 >> $2)")
of mShlI:
if n[1].typ.size <= 4:
applyFormat("($1 << $2)", "($1 << $2)")
else:
applyFormat("($1 * Math.pow(2,$2))", "($1 * Math.pow(2,$2))")
of mAshrI:
if n[1].typ.size <= 4:
applyFormat("($1 >> $2)", "($1 >> $2)")
else:
applyFormat("Math.floor($1 / Math.pow(2,$2))", "Math.floor($1 / Math.pow(2,$2))")
of mBitandI: applyFormat("($1 & $2)", "($1 & $2)")
of mBitorI: applyFormat("($1 | $2)", "($1 | $2)")
of mBitxorI: applyFormat("($1 ^ $2)", "($1 ^ $2)")
@@ -607,9 +658,11 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mBoolToStr: applyFormat("nimBoolToStr($1)", "nimBoolToStr($1)")
of mIntToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
of mInt64ToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
of mFloatToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
of mFloatToStr:
useMagic(p, "nimFloatToString")
applyFormat "cstrToNimstr(nimFloatToString($1))"
of mCStrToStr: applyFormat("cstrToNimstr($1)", "cstrToNimstr($1)")
of mStrToStr, mUnown: applyFormat("$1", "$1")
of mStrToStr, mUnown, mIsolate: applyFormat("$1", "$1")
else:
assert false, $op
@@ -813,6 +866,7 @@ proc genRaiseStmt(p: PProc, n: PNode) =
proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
var
cond, stmt: TCompRes
totalRange = 0
genLineDir(p, n)
gen(p, n[0], cond)
let stringSwitch = skipTypes(n[0].typ, abstractVar).kind == tyString
@@ -832,6 +886,10 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
let e = it[j]
if e.kind == nkRange:
var v = copyNode(e[0])
inc(totalRange, int(e[1].intVal - v.intVal))
if totalRange > 65535:
localError(p.config, n.info,
"Your case statement contains too many branches, consider using if/else instead!")
while v.intVal <= e[1].intVal:
gen(p, v, cond)
lineF(p, "case $1:$n", [cond.rdLoc])
@@ -992,13 +1050,17 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
var a, b: TCompRes
var xtyp = mapType(p, x.typ)
# disable `[]=` for cstring
if x.kind == nkBracketExpr and x.len >= 2 and x[0].typ.skipTypes(abstractInst).kind == tyCString:
localError(p.config, x.info, "cstring doesn't support `[]=` operator")
gen(p, x, a)
genLineDir(p, y)
gen(p, y, b)
# we don't care if it's an etyBaseIndex (global) of a string, it's
# still a string that needs to be copied properly:
if x.typ.skipTypes(abstractInst).kind in {tySequence, tyOpt, tyString}:
if x.typ.skipTypes(abstractInst).kind in {tySequence, tyString}:
xtyp = etySeq
case xtyp
of etySeq:
@@ -1009,7 +1071,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
lineF(p, "$1 = nimCopy(null, $2, $3);$n",
[a.rdLoc, b.res, genTypeInfo(p, y.typ)])
of etyObject:
if x.typ.kind == tyVar or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
if x.typ.kind in {tyVar} or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
else:
useMagic(p, "nimCopy")
@@ -1022,8 +1084,15 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
lineF(p, "var $1 = $4; $2 = $1[0]; $3 = $1[1];$n", [tmp, a.address, a.res, b.rdLoc])
elif b.typ == etyBaseIndex:
lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res])
elif b.typ == etyNone:
internalAssert p.config, b.address == nil
lineF(p, "$# = [$#, 0];$n", [a.address, b.res])
elif x.typ.kind == tyVar and y.typ.kind == tyPtr:
lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res])
lineF(p, "$1 = $2;$n", [a.address, b.res])
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
else:
internalError(p.config, x.info, "genAsgn")
internalError(p.config, x.info, $("genAsgn", b.typ, a.typ))
else:
lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
else:
@@ -1040,7 +1109,7 @@ proc genFastAsgn(p: PProc, n: PNode) =
# See bug #5933. So we try to be more compatible with the C backend semantics
# here for 'shallowCopy'. This is an educated guess and might require further
# changes later:
let noCopy = n[0].typ.skipTypes(abstractInst).kind in {tySequence, tyOpt, tyString}
let noCopy = n[0].typ.skipTypes(abstractInst).kind in {tySequence, tyString}
genAsgnAux(p, n[0], n[1], noCopyNeeded=noCopy)
proc genSwap(p: PProc, n: PNode) =
@@ -1141,7 +1210,7 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) =
useMagic(p, "raiseFieldError")
useMagic(p, "makeNimstrLit")
let msg = genFieldError(field, disc)
let msg = genFieldDefect(field, disc)
lineF(p, "if ($1[$2.$3]$4undefined) { raiseFieldError(makeNimstrLit($5)); }$n",
setx.res, tmp, disc.loc.r, if negCheck: ~"!==" else: ~"===",
makeJSString(msg))
@@ -1171,9 +1240,13 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
first = firstOrd(p.config, typ[0])
if optBoundsCheck in p.options:
useMagic(p, "chckIndx")
r.res = "chckIndx($1, $2, ($3 != null ? $3.length : 0)+$2-1)-$2" % [b.res, rope(first), tmp]
if first == 0: # save a couple chars
r.res = "chckIndx($1, 0, ($2).length-1)" % [b.res, tmp]
else:
r.res = "chckIndx($1, $2, ($3).length+($2)-1)-($2)" % [
b.res, rope(first), tmp]
elif first != 0:
r.res = "($1)-$2" % [b.res, rope(first)]
r.res = "($1)-($2)" % [b.res, rope(first)]
else:
r.res = b.res
r.kind = resExpr
@@ -1219,6 +1292,10 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
let s = n[0].sym
if s.loc.r == nil: internalError(p.config, n.info, "genAddr: 3")
case s.kind
of skParam:
r.res = s.loc.r
r.address = nil
r.typ = etyNone
of skVar, skLet, skResult:
r.kind = resExpr
let jsType = mapType(p, n.typ)
@@ -1240,7 +1317,7 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
# 'var openArray' for instance produces an 'addr' but this is harmless:
gen(p, n[0], r)
#internalError(p.config, n.info, "genAddr: 4 " & renderTree(n))
else: internalError(p.config, n.info, "genAddr: 2")
else: internalError(p.config, n.info, $("genAddr: 2", s.kind))
of nkCheckedFieldExpr:
genCheckedFieldOp(p, n[0], n.typ, r)
of nkDotExpr:
@@ -1263,8 +1340,21 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
of nkObjDownConv:
gen(p, n[0], r)
of nkHiddenDeref:
gen(p, n[0][0], r)
else: internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
gen(p, n[0], r)
of nkHiddenAddr:
gen(p, n[0], r)
of nkStmtListExpr:
if n.len == 1: gen(p, n[0], r)
else: internalError(p.config, n[0].info, "genAddr for complex nkStmtListExpr")
of nkCallKinds:
if n[0].typ.kind == tyOpenArray:
# 'var openArray' for instance produces an 'addr' but this is harmless:
# namely toOpenArray(a, 1, 3)
gen(p, n[0], r)
else:
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
else:
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
proc attachProc(p: PProc; content: Rope; s: PSym) =
p.g.code.add(content)
@@ -1337,7 +1427,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
s.name.s)
discard mangleName(p.module, s)
r.res = s.loc.r
if lfNoDecl in s.loc.flags or s.magic != mNone or
if lfNoDecl in s.loc.flags or s.magic notin {mNone, mIsolate} or
{sfImportc, sfInfixCall} * s.flags != {}:
discard
elif s.kind == skMethod and s.getBody.kind == nkEmpty:
@@ -1644,7 +1734,9 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
result = putToSeq("[null, 0]", indirect)
else:
result = putToSeq("null", indirect)
of tySequence, tyOpt, tyString, tyCString, tyProc:
of tySequence, tyString:
result = putToSeq("[]", indirect)
of tyCString, tyProc:
result = putToSeq("null", indirect)
of tyStatic:
if t.n != nil:
@@ -1665,6 +1757,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
varCode: string
varName = mangleName(p.module, v)
useReloadingGuard = sfGlobal in v.flags and p.config.hcrOn
useGlobalPragmas = sfGlobal in v.flags and ({sfPure, sfThread} * v.flags != {})
if v.constraint.isNil:
if useReloadingGuard:
@@ -1672,6 +1765,10 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
lineF(p, "if ($1 === undefined) {$n", varName)
varCode = $varName
inc p.extraIndent
elif useGlobalPragmas:
lineF(p, "if (globalThis.$1 === undefined) {$n", varName)
varCode = $varName
inc p.extraIndent
else:
varCode = "var $2"
else:
@@ -1724,7 +1821,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
else:
line(p, runtimeFormat(varCode & " = $3;$n", [returnType, v.loc.r, s]))
if useReloadingGuard:
if useReloadingGuard or useGlobalPragmas:
dec p.extraIndent
lineF(p, "}$n")
@@ -1776,7 +1873,7 @@ proc genNewSeq(p: PProc, n: PNode) =
x.rdLoc, y.rdLoc, createVar(p, t, false)])
proc genOrd(p: PProc, n: PNode, r: var TCompRes) =
case skipTypes(n[1].typ, abstractVar).kind
case skipTypes(n[1].typ, abstractVar + abstractRange).kind
of tyEnum, tyInt..tyUInt64, tyChar: gen(p, n[1], r)
of tyBool: unaryExpr(p, n, r, "", "($1 ? 1:0)")
else: internalError(p.config, n.info, "genOrd")
@@ -1851,6 +1948,7 @@ proc genRepr(p: PProc, n: PNode, r: var TCompRes) =
genReprAux(p, n, r, "reprJSONStringify")
else:
genReprAux(p, n, r, "reprAny", genTypeInfo(p, t))
r.kind = resExpr
proc genOf(p: PProc, n: PNode, r: var TCompRes) =
var x: TCompRes
@@ -1875,7 +1973,7 @@ proc genReset(p: PProc, n: PNode) =
if x.typ == etyBaseIndex:
lineF(p, "$1 = null, $2 = 0;$n", [x.address, x.res])
else:
let (a, tmp) = maybeMakeTemp(p, n[1], x)
let (a, tmp) = maybeMakeTempAssignable(p, n[1], x)
lineF(p, "$1 = genericReset($3, $2);$n", [a,
genTypeInfo(p, n[1].typ), tmp])
@@ -1901,37 +1999,35 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
of mSwap: genSwap(p, n)
of mAppendStrCh:
binaryExpr(p, n, r, "addChar",
"if ($1 != null) { addChar($3, $2); } else { $3 = [$2]; }")
"addChar($1, $2);")
of mAppendStrStr:
var lhs, rhs: TCompRes
gen(p, n[1], lhs)
gen(p, n[2], rhs)
let rhsIsLit = n[2].kind in nkStrKinds
let (a, tmp) = maybeMakeTemp(p, n[1], lhs)
if skipTypes(n[1].typ, abstractVarRange).kind == tyCString:
r.res = "if ($1 != null) { $4 += $2; } else { $4 = $2$3; }" % [
a, rhs.rdLoc, if rhsIsLit: nil else: ~".slice()", tmp]
let (b, tmp) = maybeMakeTemp(p, n[2], rhs)
r.res = "if (null != $1) { if (null == $2) $2 = $3; else $2 += $3; }" %
[b, lhs.rdLoc, tmp]
else:
r.res = "if ($1 != null) { $4 = ($4).concat($2); } else { $4 = $2$3; }" % [
lhs.rdLoc, rhs.rdLoc, if rhsIsLit: nil else: ~".slice()", tmp]
let (a, tmp) = maybeMakeTemp(p, n[1], lhs)
r.res = "$1.push.apply($3, $2);" % [a, rhs.rdLoc, tmp]
r.kind = resExpr
of mAppendSeqElem:
var x, y: TCompRes
gen(p, n[1], x)
gen(p, n[2], y)
let (a, tmp) = maybeMakeTemp(p, n[1], x)
if mapType(n[2].typ) == etyBaseIndex:
let c = "[$1, $2]" % [y.address, y.res]
r.res = "if ($1 != null) { $3.push($2); } else { $3 = [$2]; }" % [a, c, tmp]
r.res = "$1.push($2);" % [x.rdLoc, c]
elif needsNoCopy(p, n[2]):
r.res = "if ($1 != null) { $3.push($2); } else { $3 = [$2]; }" % [a, y.rdLoc, tmp]
r.res = "$1.push($2);" % [x.rdLoc, y.rdLoc]
else:
useMagic(p, "nimCopy")
let c = getTemp(p, defineInLocals=false)
lineF(p, "var $1 = nimCopy(null, $2, $3);$n",
[c, y.rdLoc, genTypeInfo(p, n[2].typ)])
r.res = "if ($1 != null) { $3.push($2); } else { $3 = [$2]; }" % [a, c, tmp]
r.res = "$1.push($2);" % [x.rdLoc, c]
r.kind = resExpr
of mConStrStr:
genConStrStr(p, n, r)
@@ -1963,23 +2059,37 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
of mDestroy: discard "ignore calls to the default destructor"
of mOrd: genOrd(p, n, r)
of mLengthStr, mLengthSeq, mLengthOpenArray, mLengthArray:
unaryExpr(p, n, r, "", "($1 != null ? $2.length : 0)")
var x: TCompRes
gen(p, n[1], x)
if skipTypes(n[1].typ, abstractInst).kind == tyCString:
let (a, tmp) = maybeMakeTemp(p, n[1], x)
r.res = "(($1) == null ? 0 : ($2).length)" % [a, tmp]
else:
r.res = "($1).length" % [x.rdLoc]
r.kind = resExpr
of mHigh:
unaryExpr(p, n, r, "", "($1 != null ? ($2.length-1) : -1)")
var x: TCompRes
gen(p, n[1], x)
if skipTypes(n[1].typ, abstractInst).kind == tyCString:
let (a, tmp) = maybeMakeTemp(p, n[1], x)
r.res = "(($1) == null ? -1 : ($2).length - 1)" % [a, tmp]
else:
r.res = "($1).length - 1" % [x.rdLoc]
r.kind = resExpr
of mInc:
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
binaryUintExpr(p, n, r, "+", true)
else:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2")
else: binaryExpr(p, n, r, "addInt", "$1 = addInt($3, $2)")
else: binaryExpr(p, n, r, "addInt", "$1 = addInt($3, $2)", true)
of ast.mDec:
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
binaryUintExpr(p, n, r, "-", true)
else:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($3, $2)")
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($3, $2)", true)
of mSetLengthStr:
binaryExpr(p, n, r, "mnewString", "($1 == null ? $3 = mnewString($2) : $3.length = $2)")
binaryExpr(p, n, r, "mnewString", "($1.length = $2)")
of mSetLengthSeq:
var x, y: TCompRes
gen(p, n[1], x)
@@ -1987,8 +2097,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
let t = skipTypes(n[1].typ, abstractVar)[0]
let (a, tmp) = maybeMakeTemp(p, n[1], x)
let (b, tmp2) = maybeMakeTemp(p, n[2], y)
r.res = """if ($1 === null) $4 = [];
if ($4.length < $2) { for (var i=$4.length;i<$5;++i) $4.push($3); }
r.res = """if ($1.length < $2) { for (var i=$4.length;i<$5;++i) $4.push($3); }
else { $4.length = $5; }""" % [a, b, createVar(p, t, false), tmp, tmp2]
r.kind = resExpr
of mCard: unaryExpr(p, n, r, "SetCard", "SetCard($1)")
@@ -2206,7 +2315,7 @@ proc genProcBody(p: PProc, prc: PSym): Rope =
if hasFrameInfo(p):
result = frameCreate(p,
makeJSString(prc.owner.name.s & '.' & prc.name.s),
makeJSString(toFilename(p.config, prc.info)))
makeJSString(toFilenameOption(p.config, prc.info.fileIndex, foStacktrace)))
else:
result = nil
if p.beforeRetNeeded:
@@ -2335,8 +2444,7 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
r.res = "($1 $2)" % [r.res, trimmer]
elif toInt:
if fromInt:
let trimmer = unsignedTrimmer(dest.size)
r.res = "($1 $2)" % [r.res, trimmer]
return
elif fromUint:
if src.size == 4 and dest.size == 4:
# XXX prevent multi evaluations
@@ -2362,7 +2470,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
if r.kind != resCallee: r.kind = resNone
#r.address = nil
r.res = nil
case n.kind
of nkSym:
genSym(p, n, r)
@@ -2417,7 +2525,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
n.len >= 1:
genInfixCall(p, n, r)
else:
genCall(p, n, r)
genCall(p, n, r)
of nkClosure: gen(p, n[0], r)
of nkCurly: genSetConstr(p, n, r)
of nkBracket: genArrayConstr(p, n, r)
@@ -2443,7 +2551,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
let s = n[namePos].sym
discard mangleName(p.module, s)
r.res = s.loc.r
if lfNoDecl in s.loc.flags or s.magic != mNone: discard
if lfNoDecl in s.loc.flags or s.magic notin {mNone, mIsolate}: discard
elif not p.g.generatedSyms.containsOrIncl(s.id):
p.locals.add(genProc(p, s))
of nkType: r.res = genTypeInfo(p, n.typ)
@@ -2474,13 +2582,17 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
if n[0].kind != nkEmpty:
genLineDir(p, n)
gen(p, n[0], r)
r.res = "var _ = " & r.res
of nkAsmStmt: genAsmOrEmitStmt(p, n)
of nkTryStmt, nkHiddenTryStmt: genTry(p, n, r)
of nkRaiseStmt: genRaiseStmt(p, n)
of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt,
of nkTypeSection, nkCommentStmt, nkIncludeStmt,
nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt,
nkFromStmt, nkTemplateDef, nkMacroDef, nkStaticStmt,
nkMixinStmt, nkBindStmt: discard
of nkIteratorDef:
if n[0].sym.typ.callConv == TCallingConvention.ccClosure:
globalError(p.config, n.info, "Closure iterators are not supported by JS backend!")
of nkPragma: genPragma(p, n)
of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef:
var s = n[namePos].sym
@@ -2488,7 +2600,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
genSym(p, n[namePos], r)
r.res = nil
of nkGotoState, nkState:
internalError(p.config, n.info, "first class iterators not implemented")
globalError(p.config, n.info, "First class iterators not implemented")
of nkPragmaBlock: gen(p, n.lastSon, r)
of nkComesFrom:
discard "XXX to implement for better stack traces"
@@ -2502,20 +2614,14 @@ proc newModule(g: ModuleGraph; module: PSym): BModule =
g.backend = newGlobals()
result.graph = g
result.config = g.config
if sfSystemModule in module.flags:
PGlobals(g.backend).inSystem = true
proc genHeader(): Rope =
result = rope("""/* Generated by the Nim Compiler v$1 */
var framePtr = null;
var excHandler = 0;
var lastJSError = null;
if (typeof Int8Array === 'undefined') Int8Array = Array;
if (typeof Int16Array === 'undefined') Int16Array = Array;
if (typeof Int32Array === 'undefined') Int32Array = Array;
if (typeof Uint8Array === 'undefined') Uint8Array = Array;
if (typeof Uint16Array === 'undefined') Uint16Array = Array;
if (typeof Uint32Array === 'undefined') Uint32Array = Array;
if (typeof Float32Array === 'undefined') Float32Array = Array;
if (typeof Float64Array === 'undefined') Float64Array = Array;
""".unindent.format(VersionAsString))
proc addHcrInitGuards(p: PProc, n: PNode,
@@ -2545,7 +2651,7 @@ proc genModule(p: PProc, n: PNode) =
if optStackTrace in p.options:
p.body.add(frameCreate(p,
makeJSString("module " & p.module.module.name.s),
makeJSString(toFilename(p.config, p.module.module.info))))
makeJSString(toFilenameOption(p.config, p.module.module.info.fileIndex, foStacktrace))))
var transformedN = transformStmt(p.module.graph, p.module.module, n)
if sfInjectDestructors in p.module.module.flags:
transformedN = injectDestructorCalls(p.module.graph, p.module.module, transformedN)
@@ -2575,7 +2681,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
if passes.skipCodegen(m.config, n): return n
if m.module == nil: internalError(m.config, n.info, "myProcess")
let globals = PGlobals(m.graph.backend)
var p = newProc(globals, m, nil, m.module.options)
var p = newInitProc(globals, m)
p.unique = globals.unique
genModule(p, n)
p.g.code.add(p.locals)
@@ -2585,14 +2691,14 @@ proc wholeCode(graph: ModuleGraph; m: BModule): Rope =
let globals = PGlobals(graph.backend)
for prc in globals.forwarded:
if not globals.generatedSyms.containsOrIncl(prc.id):
var p = newProc(globals, m, nil, m.module.options)
var p = newInitProc(globals, m)
attachProc(p, prc)
var disp = generateMethodDispatchers(graph)
for i in 0..<disp.len:
let prc = disp[i].sym
if not globals.generatedSyms.containsOrIncl(prc.id):
var p = newProc(globals, m, nil, m.module.options)
var p = newInitProc(globals, m)
attachProc(p, prc)
result = globals.typeInfo & globals.constants & globals.code
@@ -2612,6 +2718,8 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
if sfMainModule in m.module.flags:
for destructorCall in graph.globalDestructors:
n.add destructorCall
if sfSystemModule in m.module.flags:
PGlobals(graph.backend).inSystem = false
if passes.skipCodegen(m.config, n): return n
if sfMainModule in m.module.flags:
var code = genHeader() & wholeCode(graph, m)
@@ -2619,10 +2727,10 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
if optSourcemap in m.config.globalOptions:
var map: SourceMap
(code, map) = genSourceMap($(code), mangled, outFile.string)
(code, map) = genSourceMap($(code), outFile.string)
writeFile(outFile.string & ".map", $(%map))
discard writeRopeIfNotEqual(code, outFile)
proc myOpen(graph: ModuleGraph; s: PSym): PPassContext =
result = newModule(graph, s)

View File

@@ -235,13 +235,14 @@ template isIterator*(owner: PSym): bool =
proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
## lambda lifting can be harmful for JS-like code generators.
let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
result = conf.cmd == cmdCompileToJS and not isCompileTime
result = conf.backend == backendJs and not isCompileTime
proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; owner: PSym) =
createTypeBoundOps(g, nil, refType.lastSon, info)
createTypeBoundOps(g, nil, refType, info)
if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions:
owner.flags.incl sfInjectDestructors
if owner.kind != skMacro:
createTypeBoundOps(g, nil, refType.lastSon, info)
createTypeBoundOps(g, nil, refType, info)
if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions:
owner.flags.incl sfInjectDestructors
proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
@@ -291,10 +292,11 @@ proc markAsClosure(g: ModuleGraph; owner: PSym; n: PNode) =
if illegalCapture(s):
localError(g.config, n.info,
("'$1' is of type <$2> which cannot be captured as it would violate memory" &
" safety, declared here: $3") % [s.name.s, typeToString(s.typ), g.config$s.info])
elif owner.typ.callConv notin {ccClosure, ccDefault}:
" safety, declared here: $3; using '-d:nimWorkaround14447' helps in some cases") %
[s.name.s, typeToString(s.typ), g.config$s.info])
elif not (owner.typ.callConv == ccClosure or owner.typ.callConv == ccNimCall and tfExplicitCallConv notin owner.typ.flags):
localError(g.config, n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" %
[s.name.s, owner.name.s, CallingConvToStr[owner.typ.callConv]])
[s.name.s, owner.name.s, $owner.typ.callConv])
incl(owner.typ.flags, tfCapturesEnv)
owner.typ.callConv = ccClosure
@@ -611,7 +613,8 @@ proc rawClosureCreation(owner: PSym;
let fieldAccess = indirectAccess(env, local, env.info)
# add ``env.param = param``
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info)
if owner.kind != skMacro:
createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info)
if tfHasAsgn in fieldAccess.typ.flags or optSeqDestructors in d.graph.config.globalOptions:
owner.flags.incl sfInjectDestructors
@@ -822,7 +825,8 @@ proc semCaptureSym*(s, owner: PSym) =
var o = owner.skipGenericOwner
while o != nil and o.kind != skModule:
if s.owner == o:
if owner.typ.callConv in {ccClosure, ccDefault} or owner.kind == skIterator:
if owner.typ.callConv == ccClosure or owner.kind == skIterator or
owner.typ.callConv == ccNimCall and tfExplicitCallConv notin owner.typ.flags:
owner.typ.callConv = ccClosure
propagateClosure(owner.skipGenericOwner, s.owner)
else:
@@ -847,14 +851,14 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo
fn.typ.callConv = oldCC
proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode =
# XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
# XXX backend == backendJs does not suffice! The compiletime stuff needs
# the transformation even when compiling to JS ...
# However we can do lifting for the stuff which is *only* compiletime.
let isCompileTime = sfCompileTime in fn.flags or fn.kind == skMacro
if body.kind == nkEmpty or (
g.config.cmd == cmdCompileToJS and not isCompileTime) or
g.config.backend == backendJs and not isCompileTime) or
fn.skipGenericOwner.kind != skModule:
# ignore forward declaration:

View File

@@ -35,7 +35,7 @@ type
Emitter* = object
config: ConfigRef
fid: FileIndex
lastTok: TTokType
lastTok: TokType
inquote, lastTokWasTerse: bool
semicolons: SemicolonKind
col, lastLineNumber, lineSpan, indentLevel, indWidth*, inSection: int
@@ -327,7 +327,7 @@ const
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}
tkIsnot, tkNot, tkOf, tkAs, tkFrom, tkDotDot, tkAnd, tkOr, tkXor}
template goodCol(col): bool = col >= em.maxLineLen div 2
@@ -402,7 +402,7 @@ proc endsInAlpha(em: Emitter): bool =
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; dontIndent: bool) =
proc emitComment(em: var Emitter; tok: Token; dontIndent: bool) =
var col = em.col
let lit = strip fileSection(em.config, em.fid, tok.commentOffsetA, tok.commentOffsetB)
em.lineSpan = countNewlines(lit)
@@ -417,7 +417,7 @@ proc emitComment(em: var Emitter; tok: TToken; dontIndent: bool) =
inc col
emitMultilineComment(em, lit, col, dontIndent)
proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
proc emitTok*(em: var Emitter; L: Lexer; tok: Token) =
template wasExportMarker(em): bool =
em.kinds.len > 0 and em.kinds[^1] == ltExportMarker
@@ -452,6 +452,9 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
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)
while em.indentStack[^1] > tok.indent:
discard em.indentStack.pop()
# aka: we are in an expression context:
let alignment = max(tok.indent - em.indentStack[^1], 0)
em.indentLevel = alignment + em.indentStack.high * em.indWidth
@@ -491,7 +494,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
wrSpace em
if not em.inquote:
wr(em, TokTypeToStr[tok.tokType], ltKeyword)
wr(em, $tok.tokType, ltKeyword)
if tok.tokType in {tkAnd, tkOr, tkIn, tkNotin}:
rememberSplit(splitIn)
wrSpace em
@@ -500,28 +503,28 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
wr(em, tok.ident.s, ltIdent)
of tkColon:
wr(em, TokTypeToStr[tok.tokType], ltOther)
wr(em, $tok.tokType, ltOther)
wrSpace em
of tkSemiColon, tkComma:
wr(em, TokTypeToStr[tok.tokType], ltOther)
wr(em, $tok.tokType, ltOther)
rememberSplit(splitComma)
wrSpace em
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], ltSomeParLe)
wr(em, $tok.tokType, ltSomeParLe)
rememberSplit(splitParLe)
of closedPars:
wr(em, TokTypeToStr[tok.tokType], ltSomeParRi)
wr(em, $tok.tokType, ltSomeParRi)
of tkColonColon:
wr(em, TokTypeToStr[tok.tokType], ltOther)
wr(em, $tok.tokType, ltOther)
of tkDot:
lastTokWasTerse = true
wr(em, TokTypeToStr[tok.tokType], ltOther)
wr(em, $tok.tokType, ltOther)
of tkEquals:
if not em.inquote and not em.endsInWhite: wrSpace(em)
wr(em, TokTypeToStr[tok.tokType], ltOther)
wr(em, $tok.tokType, ltOther)
if not em.inquote: wrSpace(em)
of tkOpr, tkDotDot:
if em.inquote or ((tok.strongSpaceA == 0 and tok.strongSpaceB == 0) and
@@ -541,7 +544,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
wrSpace(em)
of tkAccent:
if not em.inquote and endsInAlpha(em): wrSpace(em)
wr(em, TokTypeToStr[tok.tokType], ltOther)
wr(em, $tok.tokType, ltOther)
em.inquote = not em.inquote
of tkComment:
if not preventComment:

View File

@@ -30,42 +30,49 @@ const
# don't forget to update the 'highlite' module if these charsets should change
type
TTokType* = enum
tkInvalid, tkEof, # order is important here!
tkSymbol, # keywords:
tkAddr, tkAnd, tkAs, tkAsm,
tkBind, tkBlock, tkBreak, tkCase, tkCast,
tkConcept, tkConst, tkContinue, tkConverter,
tkDefer, tkDiscard, tkDistinct, tkDiv, tkDo,
tkElif, tkElse, tkEnd, tkEnum, tkExcept, tkExport,
tkFinally, tkFor, tkFrom, tkFunc,
tkIf, tkImport, tkIn, tkInclude, tkInterface,
tkIs, tkIsnot, tkIterator,
tkLet,
tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin,
tkObject, tkOf, tkOr, tkOut,
tkProc, tkPtr, tkRaise, tkRef, tkReturn,
tkShl, tkShr, tkStatic,
tkTemplate,
tkTry, tkTuple, tkType, tkUsing,
tkVar, tkWhen, tkWhile, tkXor,
tkYield, # end of keywords
tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit,
tkUIntLit, tkUInt8Lit, tkUInt16Lit, tkUInt32Lit, tkUInt64Lit,
tkFloatLit, tkFloat32Lit, tkFloat64Lit, tkFloat128Lit,
tkStrLit, tkRStrLit, tkTripleStrLit,
tkGStrLit, tkGTripleStrLit, tkCharLit, tkParLe, tkParRi, tkBracketLe,
tkBracketRi, tkCurlyLe, tkCurlyRi,
tkBracketDotLe, tkBracketDotRi, # [. and .]
tkCurlyDotLe, tkCurlyDotRi, # {. and .}
tkParDotLe, tkParDotRi, # (. and .)
tkComma, tkSemiColon,
tkColon, tkColonColon, tkEquals, tkDot, tkDotDot, tkBracketLeColon,
tkOpr, tkComment, tkAccent,
TokType* = enum
tkInvalid = "tkInvalid", tkEof = "[EOF]", # order is important here!
tkSymbol = "tkSymbol", # keywords:
tkAddr = "addr", tkAnd = "and", tkAs = "as", tkAsm = "asm",
tkBind = "bind", tkBlock = "block", tkBreak = "break", tkCase = "case", tkCast = "cast",
tkConcept = "concept", tkConst = "const", tkContinue = "continue", tkConverter = "converter",
tkDefer = "defer", tkDiscard = "discard", tkDistinct = "distinct", tkDiv = "div", tkDo = "do",
tkElif = "elif", tkElse = "else", tkEnd = "end", tkEnum = "enum", tkExcept = "except", tkExport = "export",
tkFinally = "finally", tkFor = "for", tkFrom = "from", tkFunc = "func",
tkIf = "if", tkImport = "import", tkIn = "in", tkInclude = "include", tkInterface = "interface",
tkIs = "is", tkIsnot = "isnot", tkIterator = "iterator",
tkLet = "let",
tkMacro = "macro", tkMethod = "method", tkMixin = "mixin", tkMod = "mod", tkNil = "nil", tkNot = "not", tkNotin = "notin",
tkObject = "object", tkOf = "of", tkOr = "or", tkOut = "out",
tkProc = "proc", tkPtr = "ptr", tkRaise = "raise", tkRef = "ref", tkReturn = "return",
tkShl = "shl", tkShr = "shr", tkStatic = "static",
tkTemplate = "template",
tkTry = "try", tkTuple = "tuple", tkType = "type", tkUsing = "using",
tkVar = "var", tkWhen = "when", tkWhile = "while", tkXor = "xor",
tkYield = "yield", # end of keywords
tkIntLit = "tkIntLit", tkInt8Lit = "tkInt8Lit", tkInt16Lit = "tkInt16Lit",
tkInt32Lit = "tkInt32Lit", tkInt64Lit = "tkInt64Lit",
tkUIntLit = "tkUIntLit", tkUInt8Lit = "tkUInt8Lit", tkUInt16Lit = "tkUInt16Lit",
tkUInt32Lit = "tkUInt32Lit", tkUInt64Lit = "tkUInt64Lit",
tkFloatLit = "tkFloatLit", tkFloat32Lit = "tkFloat32Lit",
tkFloat64Lit = "tkFloat64Lit", tkFloat128Lit = "tkFloat128Lit",
tkStrLit = "tkStrLit", tkRStrLit = "tkRStrLit", tkTripleStrLit = "tkTripleStrLit",
tkGStrLit = "tkGStrLit", tkGTripleStrLit = "tkGTripleStrLit", tkCharLit = "tkCharLit",
tkParLe = "(", tkParRi = ")", tkBracketLe = "[",
tkBracketRi = "]", tkCurlyLe = "{", tkCurlyRi = "}",
tkBracketDotLe = "[.", tkBracketDotRi = ".]",
tkCurlyDotLe = "{.", tkCurlyDotRi = ".}",
tkParDotLe = "(.", tkParDotRi = ".)",
tkComma = ",", tkSemiColon = ";",
tkColon = ":", tkColonColon = "::", tkEquals = "=",
tkDot = ".", tkDotDot = "..", tkBracketLeColon = "[:",
tkOpr, tkComment, tkAccent = "`",
# these are fake tokens used by renderer.nim
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr
TTokTypes* = set[TTokType]
TokTypes* = set[TokType]
const
weakTokens = {tkComma, tkSemiColon, tkColon,
@@ -74,53 +81,21 @@ const
# tokens that should not be considered for previousToken
tokKeywordLow* = succ(tkSymbol)
tokKeywordHigh* = pred(tkIntLit)
TokTypeToStr*: array[TTokType, string] = ["tkInvalid", "[EOF]",
"tkSymbol",
"addr", "and", "as", "asm",
"bind", "block", "break", "case", "cast",
"concept", "const", "continue", "converter",
"defer", "discard", "distinct", "div", "do",
"elif", "else", "end", "enum", "except", "export",
"finally", "for", "from", "func", "if",
"import", "in", "include", "interface", "is", "isnot", "iterator",
"let",
"macro", "method", "mixin", "mod",
"nil", "not", "notin", "object", "of", "or",
"out", "proc", "ptr", "raise", "ref", "return",
"shl", "shr", "static",
"template",
"try", "tuple", "type", "using",
"var", "when", "while", "xor",
"yield",
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
"tkUIntLit", "tkUInt8Lit", "tkUInt16Lit", "tkUInt32Lit", "tkUInt64Lit",
"tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkFloat128Lit",
"tkStrLit", "tkRStrLit",
"tkTripleStrLit", "tkGStrLit", "tkGTripleStrLit", "tkCharLit", "(",
")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)",
",", ";",
":", "::", "=", ".", "..", "[:",
"tkOpr", "tkComment", "`",
"tkSpaces", "tkInfixOpr",
"tkPrefixOpr", "tkPostfixOpr"]
type
TNumericalBase* = enum
NumericalBase* = enum
base10, # base10 is listed as the first element,
# so that it is the correct default value
base2, base8, base16
CursorPosition* {.pure.} = enum ## XXX remove this again
None, InToken, BeforeToken, AfterToken
TToken* = object # a Nim token
tokType*: TTokType # the type of the token
Token* = object # a Nim token
tokType*: TokType # the type of the token
indent*: int # the indentation; != -1 if the token has been
# preceded with indentation
ident*: PIdent # the parsed identifier
iNumber*: BiggestInt # the parsed integer literal
fNumber*: BiggestFloat # the parsed floating point literal
base*: TNumericalBase # the numerical base; only valid for int
base*: NumericalBase # the numerical base; only valid for int
# or float literals
strongSpaceA*: int8 # leading spaces of an operator
strongSpaceB*: int8 # trailing spaces of an operator
@@ -128,26 +103,25 @@ type
# documentation comments are here too
line*, col*: int
when defined(nimpretty):
offsetA*, offsetB*: int # used for pretty printing so that literals
# like 0b01 or r"\L" are unaffected
offsetA*, offsetB*: int # used for pretty printing so that literals
# like 0b01 or r"\L" are unaffected
commentOffsetA*, commentOffsetB*: int
TErrorHandler* = proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string)
TLexer* = object of TBaseLexer
ErrorHandler* = proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string)
Lexer* = object of TBaseLexer
fileIdx*: FileIndex
indentAhead*: int # if > 0 an indentation has already been read
# this is needed because scanning comments
# needs so much look-ahead
currLineIndent*: int
strongSpaces*, allowTabs*: bool
cursor*: CursorPosition
errorHandler*: TErrorHandler
errorHandler*: ErrorHandler
cache*: IdentCache
when defined(nimsuggest):
previousToken: TLineInfo
config*: ConfigRef
proc getLineInfo*(L: TLexer, tok: TToken): TLineInfo {.inline.} =
proc getLineInfo*(L: Lexer, tok: Token): TLineInfo {.inline.} =
result = newLineInfo(L.fileIdx, tok.line, tok.col)
when defined(nimpretty):
result.offsetA = tok.offsetA
@@ -155,8 +129,8 @@ proc getLineInfo*(L: TLexer, tok: TToken): TLineInfo {.inline.} =
result.commentOffsetA = tok.commentOffsetA
result.commentOffsetB = tok.commentOffsetB
proc isKeyword*(kind: TTokType): bool =
result = (kind >= tokKeywordLow) and (kind <= tokKeywordHigh)
proc isKeyword*(kind: TokType): bool =
(kind >= tokKeywordLow) and (kind <= tokKeywordHigh)
template ones(n): untyped = ((1 shl n)-1) # for utf-8 conversion
@@ -170,28 +144,26 @@ proc isNimIdentifier*(s: string): bool =
inc(i)
result = true
proc `$`*(tok: TToken): string =
proc `$`*(tok: Token): string =
case tok.tokType
of tkIntLit..tkInt64Lit: result = $tok.iNumber
of tkFloatLit..tkFloat64Lit: result = $tok.fNumber
of tkInvalid, tkStrLit..tkCharLit, tkComment: result = tok.literal
of tkParLe..tkColon, tkEof, tkAccent:
result = TokTypeToStr[tok.tokType]
of tkIntLit..tkInt64Lit: $tok.iNumber
of tkFloatLit..tkFloat64Lit: $tok.fNumber
of tkInvalid, tkStrLit..tkCharLit, tkComment: tok.literal
of tkParLe..tkColon, tkEof, tkAccent: $tok.tokType
else:
if tok.ident != nil:
result = tok.ident.s
tok.ident.s
else:
result = ""
""
proc prettyTok*(tok: TToken): string =
if isKeyword(tok.tokType): result = "keyword " & tok.ident.s
else: result = $tok
proc prettyTok*(tok: Token): string =
if isKeyword(tok.tokType): "keyword " & tok.ident.s
else: $tok
proc printTok*(conf: ConfigRef; tok: TToken) =
msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" &
TokTypeToStr[tok.tokType] & " " & $tok)
proc printTok*(conf: ConfigRef; tok: Token) =
msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" & $tok.tokType & " " & $tok)
proc initToken*(L: var TToken) =
proc initToken*(L: var Token) =
L.tokType = tkInvalid
L.iNumber = 0
L.indent = 0
@@ -204,7 +176,7 @@ proc initToken*(L: var TToken) =
L.commentOffsetA = 0
L.commentOffsetB = 0
proc fillToken(L: var TToken) =
proc fillToken(L: var Token) =
L.tokType = tkInvalid
L.iNumber = 0
L.indent = 0
@@ -217,7 +189,7 @@ proc fillToken(L: var TToken) =
L.commentOffsetA = 0
L.commentOffsetB = 0
proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream;
proc openLexer*(lex: var Lexer, fileIdx: FileIndex, inputstream: PLLStream;
cache: IdentCache; config: ConfigRef) =
openBaseLexer(lex, inputstream)
lex.fileIdx = fileIdx
@@ -229,36 +201,36 @@ proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream;
lex.previousToken.fileIndex = fileIdx
lex.config = config
proc openLexer*(lex: var TLexer, filename: AbsoluteFile, inputstream: PLLStream;
proc openLexer*(lex: var Lexer, filename: AbsoluteFile, inputstream: PLLStream;
cache: IdentCache; config: ConfigRef) =
openLexer(lex, fileInfoIdx(config, filename), inputstream, cache, config)
proc closeLexer*(lex: var TLexer) =
proc closeLexer*(lex: var Lexer) =
if lex.config != nil:
inc(lex.config.linesCompiled, lex.lineNumber)
closeBaseLexer(lex)
proc getLineInfo(L: TLexer): TLineInfo =
proc getLineInfo(L: Lexer): TLineInfo =
result = newLineInfo(L.fileIdx, L.lineNumber, getColNumber(L, L.bufpos))
proc dispMessage(L: TLexer; info: TLineInfo; msg: TMsgKind; arg: string) =
proc dispMessage(L: Lexer; info: TLineInfo; msg: TMsgKind; arg: string) =
if L.errorHandler.isNil:
msgs.message(L.config, info, msg, arg)
else:
L.errorHandler(L.config, info, msg, arg)
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
proc lexMessage*(L: Lexer, msg: TMsgKind, arg = "") =
L.dispMessage(getLineInfo(L), msg, arg)
proc lexMessageTok*(L: TLexer, msg: TMsgKind, tok: TToken, arg = "") =
proc lexMessageTok*(L: Lexer, msg: TMsgKind, tok: Token, arg = "") =
var info = newLineInfo(L.fileIdx, tok.line, tok.col)
L.dispMessage(info, msg, arg)
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
proc lexMessagePos(L: var Lexer, msg: TMsgKind, pos: int, arg = "") =
var info = newLineInfo(L.fileIdx, L.lineNumber, pos - L.lineStart)
L.dispMessage(info, msg, arg)
proc matchTwoChars(L: TLexer, first: char, second: set[char]): bool =
proc matchTwoChars(L: Lexer, first: char, second: set[char]): bool =
result = (L.buf[L.bufpos] == first) and (L.buf[L.bufpos + 1] in second)
template tokenBegin(tok, pos) {.dirty.} =
@@ -272,7 +244,6 @@ template tokenEnd(tok, pos) {.dirty.} =
let colB = getColNumber(L, pos)+1
if L.fileIdx == L.config.m.trackPos.fileIndex and L.config.m.trackPos.col in colA..colB and
L.lineNumber == L.config.m.trackPos.line.int and L.config.ideCmd in {ideSug, ideCon}:
L.cursor = CursorPosition.InToken
L.config.m.trackPos.col = colA.int16
colA = 0
when defined(nimpretty):
@@ -297,23 +268,22 @@ template tokenEndPrevious(tok, pos) =
let colB = getColNumber(L, pos)
if L.fileIdx == L.config.m.trackPos.fileIndex and L.config.m.trackPos.col in colA..colB and
L.lineNumber == L.config.m.trackPos.line.int and L.config.ideCmd in {ideSug, ideCon}:
L.cursor = CursorPosition.BeforeToken
L.config.m.trackPos = L.previousToken
L.config.m.trackPosAttached = true
colA = 0
when defined(nimpretty):
tok.offsetB = L.offsetBase + pos
template eatChar(L: var TLexer, t: var TToken, replacementChar: char) =
template eatChar(L: var Lexer, t: var Token, replacementChar: char) =
t.literal.add(replacementChar)
inc(L.bufpos)
template eatChar(L: var TLexer, t: var TToken) =
template eatChar(L: var Lexer, t: var Token) =
t.literal.add(L.buf[L.bufpos])
inc(L.bufpos)
proc getNumber(L: var TLexer, result: var TToken) =
proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: set[char]): Natural =
proc getNumber(L: var Lexer, result: var Token) =
proc matchUnderscoreChars(L: var Lexer, tok: var Token, chars: set[char]): Natural =
var pos = L.bufpos # use registers for pos, buf
result = 0
while true:
@@ -333,19 +303,19 @@ proc getNumber(L: var TLexer, result: var TToken) =
inc(pos)
L.bufpos = pos
proc matchChars(L: var TLexer, tok: var TToken, chars: set[char]) =
proc matchChars(L: var Lexer, tok: var Token, chars: set[char]) =
var pos = L.bufpos # use registers for pos, buf
while L.buf[pos] in chars:
tok.literal.add(L.buf[pos])
inc(pos)
L.bufpos = pos
proc lexMessageLitNum(L: var TLexer, msg: string, startpos: int, msgKind = errGenerated) =
proc lexMessageLitNum(L: var Lexer, msg: string, startpos: int, msgKind = errGenerated) =
# Used to get slightly human friendlier err messages.
const literalishChars = {'A'..'F', 'a'..'f', '0'..'9', 'X', 'x', 'o', 'O',
'c', 'C', 'b', 'B', '_', '.', '\'', 'd', 'i', 'u'}
var msgPos = L.bufpos
var t: TToken
var t: Token
t.literal = ""
L.bufpos = startpos # Use L.bufpos as pos because of matchChars
matchChars(L, t, literalishChars)
@@ -572,7 +542,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
try:
len = parseBiggestUInt(result.literal, iNumber)
except ValueError:
raise newException(OverflowError, "number out of range: " & $result.literal)
raise newException(OverflowDefect, "number out of range: " & $result.literal)
if len != result.literal.len:
raise newException(ValueError, "invalid integer: " & $result.literal)
result.iNumber = cast[int64](iNumber)
@@ -582,7 +552,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
try:
len = parseBiggestInt(result.literal, iNumber)
except ValueError:
raise newException(OverflowError, "number out of range: " & $result.literal)
raise newException(OverflowDefect, "number out of range: " & $result.literal)
if len != result.literal.len:
raise newException(ValueError, "invalid integer: " & $result.literal)
result.iNumber = iNumber
@@ -608,12 +578,12 @@ proc getNumber(L: var TLexer, result: var TToken) =
except ValueError:
lexMessageLitNum(L, "invalid number: '$1'", startpos)
except OverflowError, RangeError:
except OverflowDefect, RangeDefect:
lexMessageLitNum(L, "number out of range: '$1'", startpos)
tokenEnd(result, postPos-1)
L.bufpos = postPos
proc handleHexChar(L: var TLexer, xi: var int; position: range[0..4]) =
proc handleHexChar(L: var Lexer, xi: var int; position: range[0..4]) =
template invalid() =
lexMessage(L, errGenerated,
"expected a hex digit, but found: " & L.buf[L.bufpos] &
@@ -638,7 +608,7 @@ proc handleHexChar(L: var TLexer, xi: var int; position: range[0..4]) =
# Need to progress for `nim check`
inc(L.bufpos)
proc handleDecChars(L: var TLexer, xi: var int) =
proc handleDecChars(L: var Lexer, xi: var int) =
while L.buf[L.bufpos] in {'0'..'9'}:
xi = (xi * 10) + (ord(L.buf[L.bufpos]) - ord('0'))
inc(L.bufpos)
@@ -681,16 +651,11 @@ proc addUnicodeCodePoint(s: var string, i: int) =
s[pos+4] = chr(i shr 6 and ones(6) or 0b10_0000_00)
s[pos+5] = chr(i and ones(6) or 0b10_0000_00)
proc getEscapedChar(L: var TLexer, tok: var TToken) =
proc getEscapedChar(L: var Lexer, tok: var Token) =
inc(L.bufpos) # skip '\'
case L.buf[L.bufpos]
of 'n', 'N':
if L.config.oldNewlines:
if tok.tokType == tkCharLit:
lexMessage(L, errGenerated, "\\n not allowed in character literal")
tok.literal.add(L.config.target.tnl)
else:
tok.literal.add('\L')
tok.literal.add('\L')
inc(L.bufpos)
of 'p', 'P':
if tok.tokType == tkCharLit:
@@ -766,18 +731,13 @@ proc getEscapedChar(L: var TLexer, tok: var TToken) =
else: lexMessage(L, errGenerated, "invalid character constant")
else: lexMessage(L, errGenerated, "invalid character constant")
proc newString(s: cstring, len: int): string =
## XXX, how come there is no support for this?
result = newString(len)
for i in 0..<len:
result[i] = s[i]
proc handleCRLF(L: var TLexer, pos: int): int =
proc handleCRLF(L: var Lexer, pos: int): int =
template registerLine =
let col = L.getColNumber(pos)
if col > MaxLineLength:
lexMessagePos(L, hintLineTooLong, pos)
when not defined(nimpretty):
if col > MaxLineLength:
lexMessagePos(L, hintLineTooLong, pos)
case L.buf[pos]
of CR:
@@ -794,7 +754,7 @@ type
raw,
generalized
proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
proc getString(L: var Lexer, tok: var Token, mode: StringMode) =
var pos = L.bufpos
var line = L.lineNumber # save linenumber for better error message
tokenBegin(tok, pos - ord(mode == raw))
@@ -860,7 +820,7 @@ proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
inc(pos)
L.bufpos = pos
proc getCharacter(L: var TLexer, tok: var TToken) =
proc getCharacter(L: var Lexer, tok: var Token) =
tokenBegin(tok, L.bufpos)
inc(L.bufpos) # skip '
var c = L.buf[L.bufpos]
@@ -877,7 +837,7 @@ proc getCharacter(L: var TLexer, tok: var TToken) =
tokenEndIgnore(tok, L.bufpos)
inc(L.bufpos) # skip '
proc getSymbol(L: var TLexer, tok: var TToken) =
proc getSymbol(L: var Lexer, tok: var Token) =
var h: Hash = 0
var pos = L.bufpos
tokenBegin(tok, pos)
@@ -907,21 +867,21 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
(tok.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)):
tok.tokType = tkSymbol
else:
tok.tokType = TTokType(tok.ident.id + ord(tkSymbol))
tok.tokType = TokType(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,
proc endOperator(L: var Lexer, tok: var Token, pos: int,
hash: Hash) {.inline.} =
var h = !$hash
tok.ident = L.cache.getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
if (tok.ident.id < oprLow) or (tok.ident.id > oprHigh): tok.tokType = tkOpr
else: tok.tokType = TTokType(tok.ident.id - oprLow + ord(tkColon))
else: tok.tokType = TokType(tok.ident.id - oprLow + ord(tkColon))
L.bufpos = pos
proc getOperator(L: var TLexer, tok: var TToken) =
proc getOperator(L: var Lexer, tok: var Token) =
var pos = L.bufpos
tokenBegin(tok, pos)
var h: Hash = 0
@@ -941,18 +901,15 @@ proc getOperator(L: var TLexer, tok: var TToken) =
if L.buf[pos] in {CR, LF, nimlexbase.EndOfFile}:
tok.strongSpaceB = -1
proc getPrecedence*(tok: TToken, strongSpaces: bool): int =
proc getPrecedence*(tok: Token): int =
## Calculates the precedence of the given token.
template considerStrongSpaces(x): untyped =
x + (if strongSpaces: 100 - tok.strongSpaceA.int*10 else: 0)
case tok.tokType
of tkOpr:
let relevantChar = tok.ident.s[0]
# arrow like?
if tok.ident.s.len > 1 and tok.ident.s[^1] == '>' and
tok.ident.s[^2] in {'-', '~', '='}: return considerStrongSpaces(1)
tok.ident.s[^2] in {'-', '~', '='}: return 1
template considerAsgn(value: untyped) =
result = if tok.ident.s[^1] == '=': 1 else: value
@@ -968,15 +925,13 @@ proc getPrecedence*(tok: TToken, strongSpaces: bool): int =
of '?': result = 2
else: considerAsgn(2)
of tkDiv, tkMod, tkShl, tkShr: result = 9
of tkIn, tkNotin, tkIs, tkIsnot, tkOf, tkAs: result = 5
of tkDotDot: result = 6
of tkIn, tkNotin, tkIs, tkIsnot, tkOf, tkAs, tkFrom: result = 5
of tkAnd: result = 4
of tkOr, tkXor, tkPtr, tkRef: result = 3
else: return -10
result = considerStrongSpaces(result)
proc newlineFollows*(L: TLexer): bool =
proc newlineFollows*(L: Lexer): bool =
var pos = L.bufpos
while true:
case L.buf[pos]
@@ -992,7 +947,7 @@ proc newlineFollows*(L: TLexer): bool =
else:
break
proc skipMultiLineComment(L: var TLexer; tok: var TToken; start: int;
proc skipMultiLineComment(L: var Lexer; tok: var Token; start: int;
isDoc: bool) =
var pos = start
var toStrip = 0
@@ -1057,14 +1012,14 @@ proc skipMultiLineComment(L: var TLexer; tok: var TToken; start: int;
when defined(nimpretty):
tok.commentOffsetB = L.offsetBase + pos - 1
proc scanComment(L: var TLexer, tok: var TToken) =
proc scanComment(L: var Lexer, tok: var Token) =
var pos = L.bufpos
tok.tokType = tkComment
# iNumber contains the number of '\n' in the token
tok.iNumber = 0
assert L.buf[pos+1] == '#'
when defined(nimpretty):
tok.commentOffsetA = L.offsetBase + pos - 1
tok.commentOffsetA = L.offsetBase + pos
if L.buf[pos+2] == '[':
skipMultiLineComment(L, tok, pos+3, true)
@@ -1107,7 +1062,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
when defined(nimpretty):
tok.commentOffsetB = L.offsetBase + pos - 1
proc skip(L: var TLexer, tok: var TToken) =
proc skip(L: var Lexer, tok: var Token) =
var pos = L.bufpos
tokenBegin(tok, pos)
tok.strongSpaceA = 0
@@ -1179,7 +1134,7 @@ proc skip(L: var TLexer, tok: var TToken) =
tok.tokType = tkComment
tok.indent = commentIndent
proc rawGetTok*(L: var TLexer, tok: var TToken) =
proc rawGetTok*(L: var Lexer, tok: var Token) =
template atTokenEnd() {.dirty.} =
when defined(nimsuggest):
# we attach the cursor to the last *strong* token
@@ -1187,8 +1142,6 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
L.previousToken.line = tok.line.uint16
L.previousToken.col = tok.col.int16
when defined(nimsuggest):
L.cursor = CursorPosition.None
fillToken(tok)
if L.indentAhead >= 0:
tok.indent = L.indentAhead
@@ -1259,7 +1212,6 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
if L.fileIdx == L.config.m.trackPos.fileIndex and tok.col+1 == L.config.m.trackPos.col and
tok.line == L.config.m.trackPos.line.int and L.config.ideCmd == ideSug:
tok.tokType = tkDot
L.cursor = CursorPosition.InToken
L.config.m.trackPos.col = tok.col.int16
inc(L.bufpos)
atTokenEnd()
@@ -1332,8 +1284,8 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
proc getIndentWidth*(fileIdx: FileIndex, inputstream: PLLStream;
cache: IdentCache; config: ConfigRef): int =
var lex: TLexer
var tok: TToken
var lex: Lexer
var tok: Token
initToken(tok)
openLexer(lex, fileIdx, inputstream, cache, config)
var prevToken = tkEof
@@ -1347,11 +1299,11 @@ proc getIndentWidth*(fileIdx: FileIndex, inputstream: PLLStream;
proc getPrecedence*(ident: PIdent): int =
## assumes ident is binary operator already
var tok: TToken
var tok: Token
initToken(tok)
tok.ident = ident
tok.tokType =
if tok.ident.id in ord(tokKeywordLow) - ord(tkSymbol)..ord(tokKeywordHigh) - ord(tkSymbol):
TTokType(tok.ident.id + ord(tkSymbol))
TokType(tok.ident.id + ord(tkSymbol))
else: tkOpr
getPrecedence(tok, false)
getPrecedence(tok)

View File

@@ -10,9 +10,6 @@
## This module implements lifting for type-bound operations
## (``=sink``, ``=``, ``=destroy``, ``=deepCopy``).
# Todo:
# - use openArray instead of array to avoid over-specializations
import modulegraphs, lineinfos, idents, ast, renderer, semdata,
sighashes, lowerings, options, types, msgs, magicsys, tables
@@ -26,8 +23,9 @@ type
fn: PSym
asgnForType: PType
recurse: bool
filterDiscriminator: PSym # we generating destructor for case branch
addMemReset: bool # add wasMoved() call after destructor call
canRaise: bool
filterDiscriminator: PSym # we generating destructor for case branch
c: PContext # c can be nil, then we are called from lambdalifting!
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
@@ -42,6 +40,9 @@ proc at(a, i: PNode, elemType: PType): PNode =
result[1] = i
result.typ = elemType
proc destructorOverriden(t: PType): bool =
t.attachedOps[attachedDestructor] != nil and sfOverriden in t.attachedOps[attachedDestructor].flags
proc fillBodyTup(c: var TLiftCtx; t: PType; body, x, y: PNode) =
for i in 0..<t.len:
let lit = lowerings.newIntLit(c.g, x.info, i)
@@ -62,9 +63,18 @@ proc newAsgnStmt(le, ri: PNode): PNode =
result[0] = le
result[1] = ri
proc genBuiltin(g: ModuleGraph; magic: TMagic; name: string; i: PNode): PNode =
result = newNodeI(nkCall, i.info)
result.add createMagic(g, name, magic).newSymNode
result.add i
proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink}:
body.add newAsgnStmt(x, y)
elif c.kind == attachedDestructor and c.addMemReset:
let call = genBuiltin(c.g, mDefault, "default", x)
call.typ = t
body.add newAsgnStmt(x, call)
proc genAddr(g: ModuleGraph; x: PNode): PNode =
if x.kind == nkHiddenDeref:
@@ -74,12 +84,6 @@ proc genAddr(g: ModuleGraph; x: PNode): PNode =
result = newNodeIT(nkHiddenAddr, x.info, makeVarType(x.typ.owner, x.typ))
result.add x
proc genBuiltin(g: ModuleGraph; magic: TMagic; name: string; i: PNode): PNode =
result = newNodeI(nkCall, i.info)
result.add createMagic(g, name, magic).newSymNode
result.add i
proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode =
result = newNodeI(nkWhileStmt, c.info, 2)
let cmp = genBuiltin(c.g, mLtI, "<", i)
@@ -91,7 +95,7 @@ proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode =
proc genIf(c: var TLiftCtx; cond, action: PNode): PNode =
result = newTree(nkIfStmt, newTree(nkElifBranch, cond, action))
proc genContainerOf(c: TLiftCtx; objType: PType, field, x: PSym): PNode =
proc genContainerOf(c: TLiftCtx; objType: PType, field, x: PSym): PNode =
# generate: cast[ptr ObjType](cast[int](addr(x)) - offsetOf(objType.field))
let intType = getSysType(c.g, unknownLineInfo, tyInt)
@@ -104,7 +108,7 @@ proc genContainerOf(c: TLiftCtx; objType: PType, field, x: PSym): PNode =
let dotExpr = newNodeIT(nkDotExpr, c.info, x.typ)
dotExpr.add newNodeIT(nkType, c.info, objType)
dotExpr.add newSymNode(field)
let offsetOf = genBuiltin(c.g, mOffsetOf, "offsetof", dotExpr)
offsetOf.typ = intType
@@ -117,10 +121,12 @@ proc genContainerOf(c: TLiftCtx; objType: PType, field, x: PSym): PNode =
result.add newNodeIT(nkType, c.info, objPtr)
result.add minusExpr
proc destructorCall(c: TLiftCtx; op: PSym; x: PNode): PNode =
proc destructorCall(c: var TLiftCtx; op: PSym; x: PNode): PNode =
var destroy = newNodeIT(nkCall, x.info, op.typ[0])
destroy.add(newSymNode(op))
destroy.add genAddr(c.g, x)
if sfNeverRaises notin op.flags:
c.canRaise = true
if c.addMemReset:
result = newTree(nkStmtList, destroy, genBuiltin(c.g, mWasMoved, "wasMoved", x))
else:
@@ -140,9 +146,6 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool)
fillBody(c, f.typ, body, x.dotField(f), b)
of nkNilLit: discard
of nkRecCase:
let oldfilterDiscriminator = c.filterDiscriminator
if c.filterDiscriminator == n[0].sym:
c.filterDiscriminator = nil # we have found the case part, proceed as normal
# XXX This is only correct for 'attachedSink'!
var localEnforceDefaultOp = enforceDefaultOp
if c.kind == attachedSink:
@@ -154,8 +157,14 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool)
c.kind = prevKind
localEnforceDefaultOp = true
# copy the selector:
fillBodyObj(c, n[0], body, x, y, enforceDefaultOp = false)
if c.kind != attachedDestructor:
# copy the selector before case stmt, but destroy after case stmt
fillBodyObj(c, n[0], body, x, y, enforceDefaultOp = false)
let oldfilterDiscriminator = c.filterDiscriminator
if c.filterDiscriminator == n[0].sym:
c.filterDiscriminator = nil # we have found the case part, proceed as normal
# we need to generate a case statement:
var caseStmt = newNodeI(nkCaseStmt, c.info)
# XXX generate 'if' that checks same branches
@@ -174,7 +183,11 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool)
caseStmt.add(branch)
if emptyBranches != n.len-1:
body.add(caseStmt)
c.filterDiscriminator = oldfilterDiscriminator
if c.kind == attachedDestructor:
# destructor for selector is done after case stmt
fillBodyObj(c, n[0], body, x, y, enforceDefaultOp = false)
c.filterDiscriminator = oldfilterDiscriminator
of nkRecList:
for t in items(n): fillBodyObj(c, t, body, x, y, enforceDefaultOp)
else:
@@ -233,29 +246,37 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
else:
fillBodyObjTImpl(c, t, body, x, y)
proc newHookCall(g: ModuleGraph; op: PSym; x, y: PNode): PNode =
proc newHookCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode =
#if sfError in op.flags:
# localError(c.config, x.info, "usage of '$1' is a user-defined error" % op.name.s)
result = newNodeI(nkCall, x.info)
result.add newSymNode(op)
if sfNeverRaises notin op.flags:
c.canRaise = true
if op.typ.sons[1].kind == tyVar:
result.add genAddr(g, x)
result.add genAddr(c.g, x)
else:
result.add x
if y != nil:
result.add y
proc newOpCall(op: PSym; x: PNode): PNode =
proc newOpCall(c: var TLiftCtx; op: PSym; x: PNode): PNode =
result = newNodeIT(nkCall, x.info, op.typ[0])
result.add(newSymNode(op))
result.add x
if sfNeverRaises notin op.flags:
c.canRaise = true
proc newDeepCopyCall(op: PSym; x, y: PNode): PNode =
result = newAsgnStmt(x, newOpCall(op, y))
proc newDeepCopyCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode =
result = newAsgnStmt(x, newOpCall(c, op, y))
proc usesBuiltinArc(t: PType): bool =
proc wrap(t: PType): bool {.nimcall.} = ast.isGCedMem(t)
result = types.searchTypeFor(t, wrap)
proc useNoGc(c: TLiftCtx; t: PType): bool {.inline.} =
result = optSeqDestructors in c.g.config.globalOptions and
({tfHasGCedMem, tfHasOwned} * t.flags != {} or t.isGCedMem)
({tfHasGCedMem, tfHasOwned} * t.flags != {} or usesBuiltinArc(t))
proc requiresDestructor(c: TLiftCtx; t: PType): bool {.inline.} =
result = optSeqDestructors in c.g.config.globalOptions and
@@ -272,14 +293,20 @@ proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym =
proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
field: var PSym): bool =
if optSeqDestructors in c.g.config.globalOptions:
let op = field
if field != nil and sfOverriden in field.flags:
var op = field
let destructorOverriden = destructorOverriden(t)
if op != nil and op != c.fn and
(sfOverriden in op.flags or destructorOverriden):
if sfError in op.flags:
incl c.fn.flags, sfError
#else:
# markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
body.add newHookCall(c.g, op, x, y)
body.add newHookCall(c, op, x, y)
result = true
elif op == nil and destructorOverriden:
op = produceSym(c.g, c.c, t, c.kind, c.info)
body.add newHookCall(c, op, x, y)
result = true
elif tfHasAsgn in t.flags:
var op: PSym
@@ -308,7 +335,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
#debug(t)
#return false
assert op.ast[genericParamsPos].kind == nkEmpty
body.add newHookCall(c.g, op, x, y)
body.add newHookCall(c, op, x, y)
result = true
proc addDestructorCall(c: var TLiftCtx; orig: PType; body, x: PNode) =
@@ -359,7 +386,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
if op != nil:
#markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
body.add newDeepCopyCall(op, x, y)
body.add newDeepCopyCall(c, op, x, y)
result = true
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
@@ -372,6 +399,16 @@ proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
v.addVar(result, lowerings.newIntLit(c.g, body.info, first))
body.add v
proc declareTempOf(c: var TLiftCtx; body: PNode; value: PNode): PNode =
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
temp.typ = value.typ
incl(temp.flags, sfFromGeneric)
var v = newNodeI(nkVarSection, c.info)
result = newSymNode(temp)
v.addVar(result, value)
body.add v
proc addIncStmt(c: var TLiftCtx; body, i: PNode) =
let incCall = genBuiltin(c.g, mInc, "inc", i)
incCall.add lowerings.newIntLit(c.g, c.info, 1)
@@ -398,13 +435,17 @@ proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
result = newTree(nkCall, newSymNode(op, x.info), x, lenCall)
proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let counterIdx = body.len
let i = declareCounter(c, body, toInt64(firstOrd(c.g.config, t)))
let whileLoop = genWhileLoop(c, i, x)
let elemType = t.lastSon
let b = if c.kind == attachedTrace: y else: y.at(i, elemType)
fillBody(c, elemType, whileLoop[1], x.at(i, elemType), b)
addIncStmt(c, whileLoop[1], i)
body.add whileLoop
if whileLoop[1].len > 0:
addIncStmt(c, whileLoop[1], i)
body.add whileLoop
else:
body.sons.setLen counterIdx
proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
@@ -427,9 +468,11 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
forallElements(c, t, body, x, y)
body.add genBuiltin(c.g, mDestroy, "destroy", x)
of attachedTrace:
# follow all elements:
forallElements(c, t, body, x, y)
if canFormAcycle(t.elemType):
# follow all elements:
forallElements(c, t, body, x, y)
of attachedDispose:
forallElements(c, t, body, x, y)
body.add genBuiltin(c.g, mDestroy, "destroy", x)
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
@@ -444,8 +487,10 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
of attachedAsgn, attachedDeepCopy:
doAssert t.assignment != nil
body.add newHookCall(c.g, t.assignment, x, y)
# XXX: replace these with assertions.
if t.assignment == nil:
return # protect from recursion
body.add newHookCall(c, t.assignment, x, y)
of attachedSink:
# we always inline the move for better performance:
let moveCall = genBuiltin(c.g, mMove, "move", x)
@@ -456,14 +501,18 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# alternatively we could do this:
when false:
doAssert t.asink != nil
body.add newHookCall(c.g, t.asink, x, y)
body.add newHookCall(c, t.asink, x, y)
of attachedDestructor:
doAssert t.destructor != nil
body.add destructorCall(c, t.destructor, x)
of attachedTrace:
body.add newHookCall(c.g, t.attachedOps[c.kind], x, y)
if t.attachedOps[c.kind] == nil:
return # protect from recursion
body.add newHookCall(c, t.attachedOps[c.kind], x, y)
of attachedDispose:
body.add newHookCall(c.g, t.attachedOps[c.kind], x, nil)
if t.attachedOps[c.kind] == nil:
return # protect from recursion
body.add newHookCall(c, t.attachedOps[c.kind], x, nil)
proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
@@ -481,54 +530,93 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
discard "strings are atomic and have no inner elements that are to trace"
proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
#[ bug #15753 is really subtle. Usually the classical write barrier for reference
counting looks like this::
incRef source # increment first; this takes care of self-assignments1
decRef dest
dest[] = source
However, 'decRef dest' might trigger a cycle collection and then the collector
traverses the graph. It is crucial that when it follows the pointers the assignment
'dest[] = source' already happened so that we don't do trial deletion on a wrong
graph -- this causes premature freeing of objects! The correct barrier looks like
this::
let tmp = dest
incRef source
dest[] = source
decRef tmp
]#
var actions = newNodeI(nkStmtList, c.info)
let elemType = t.lastSon
if isFinal(elemType):
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x)
else:
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x)
createTypeBoundOps(c.g, c.c, elemType, c.info)
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(elemType)
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(t)
let tmp =
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
declareTempOf(c, body, x)
else:
x
if isFinal(elemType):
addDestructorCall(c, elemType, actions, genDeref(tmp, nkDerefExpr))
var alignOf = genBuiltin(c.g, mAlignOf, "alignof", newNodeIT(nkType, c.info, elemType))
alignOf.typ = getSysType(c.g, c.info, tyInt)
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, tmp, alignOf)
else:
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(tmp, nkDerefExpr))
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, tmp)
var cond: PNode
if isCyclic:
if isFinal(elemType):
let typInfo = genBuiltin(c.g, mGetTypeInfo, "getTypeInfo", newNodeIT(nkType, x.info, elemType))
let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
typInfo.typ = getSysType(c.g, c.info, tyPointer)
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, x, typInfo)
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, tmp, typInfo)
else:
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, x)
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, tmp)
else:
cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x)
cond.typ = getSysType(c.g, x.info, tyBool)
case c.kind
of attachedSink:
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
if isCyclic:
body.add newAsgnStmt(x, y)
body.add genIf(c, cond, actions)
else:
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
of attachedAsgn:
body.add genIf(c, y, callCodegenProc(c.g,
if isCyclic: "nimIncRefCyclic" else: "nimIncRef", c.info, y))
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
if isCyclic:
body.add newAsgnStmt(x, y)
body.add genIf(c, cond, actions)
else:
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
of attachedDestructor:
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, newNodeIT(nkNilLit, body.info, t))
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace:
if isFinal(elemType):
let typInfo = genBuiltin(c.g, mGetTypeInfo, "getTypeInfo", newNodeIT(nkType, x.info, elemType))
typInfo.typ = getSysType(c.g, c.info, tyPointer)
body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x), typInfo, y)
else:
# If the ref is polymorphic we have to account for this
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x), y)
if isCyclic:
if isFinal(elemType):
let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
typInfo.typ = getSysType(c.g, c.info, tyPointer)
body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x), typInfo, y)
else:
# If the ref is polymorphic we have to account for this
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x), y)
#echo "can follow ", elemType, " static ", isFinal(elemType)
of attachedDispose:
# this is crucial! dispose is like =destroy but we don't follow refs
# as that is dealt within the cycle collector.
if not isCyclic:
body.add genIf(c, cond, actions)
when false:
let cond = copyTree(x)
cond.typ = getSysType(c.g, x.info, tyBool)
@@ -541,19 +629,30 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let xenv = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
xenv.typ = getSysType(c.g, c.info, tyPointer)
let isCyclic = c.g.config.selectedGC == gcOrc
let tmp =
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
declareTempOf(c, body, xenv)
else:
xenv
var actions = newNodeI(nkStmtList, c.info)
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xenv)
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, tmp)
let decRefProc =
if c.g.config.selectedGC == gcOrc: "nimDecRefIsLastCyclicDyn"
if isCyclic: "nimDecRefIsLastCyclicDyn"
else: "nimDecRefIsLast"
let cond = callCodegenProc(c.g, decRefProc, c.info, xenv)
let cond = callCodegenProc(c.g, decRefProc, c.info, tmp)
cond.typ = getSysType(c.g, x.info, tyBool)
case c.kind
of attachedSink:
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
if isCyclic:
body.add newAsgnStmt(x, y)
body.add genIf(c, cond, actions)
else:
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
of attachedAsgn:
let yenv = genBuiltin(c.g, mAccessEnv, "accessEnv", y)
yenv.typ = getSysType(c.g, c.info, tyPointer)
@@ -561,11 +660,14 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if c.g.config.selectedGC == gcOrc: "nimIncRefCyclic"
else: "nimIncRef"
body.add genIf(c, yenv, callCodegenProc(c.g, incRefProc, c.info, yenv))
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
if isCyclic:
body.add newAsgnStmt(x, y)
body.add genIf(c, cond, actions)
else:
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
of attachedDestructor:
body.add genIf(c, cond, actions)
body.add newAsgnStmt(xenv, newNodeIT(nkNilLit, body.info, xenv.typ))
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace:
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(xenv), y)
@@ -594,7 +696,6 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# prevent wrong "dangling refs exist" problems:
var actions = newNodeI(nkStmtList, c.info)
actions.add callCodegenProc(c.g, "nimDecWeakRef", c.info, x)
actions.add newAsgnStmt(x, newNodeIT(nkNilLit, body.info, t))
let des = genIf(c, x, actions)
if body.len == 0:
body.add des
@@ -612,7 +713,9 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if isFinal(elemType):
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x)
var alignOf = genBuiltin(c.g, mAlignOf, "alignof", newNodeIT(nkType, c.info, elemType))
alignOf.typ = getSysType(c.g, c.info, tyInt)
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x, alignOf)
else:
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x)
@@ -623,7 +726,6 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add newAsgnStmt(x, y)
of attachedDestructor:
body.add genIf(c, x, actions)
body.add newAsgnStmt(x, newNodeIT(nkNilLit, body.info, t))
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace, attachedDispose: discard
@@ -653,10 +755,7 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
body.add newAsgnStmt(x, y)
of attachedDestructor:
var actions = newNodeI(nkStmtList, c.info)
actions.add callCodegenProc(c.g, "nimDecWeakRef", c.info, xx)
actions.add newAsgnStmt(xx, newNodeIT(nkNilLit, body.info, xx.typ))
let des = genIf(c, xx, actions)
let des = genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
if body.len == 0:
body.add des
else:
@@ -676,7 +775,6 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add newAsgnStmt(x, y)
of attachedDestructor:
body.add genIf(c, xx, actions)
body.add newAsgnStmt(xx, newNodeIT(nkNilLit, body.info, xx.typ))
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace, attachedDispose: discard
@@ -684,7 +782,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case t.kind
of tyNone, tyEmpty, tyVoid: discard
of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString,
tyPtr, tyOpt, tyUncheckedArray, tyVar, tyLent:
tyPtr, tyUncheckedArray, tyVar, tyLent:
defaultOp(c, t, body, x, y)
of tyRef:
if c.g.config.selectedGC in {gcArc, gcOrc}:
@@ -760,12 +858,13 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
tyGenericParam, tyGenericBody, tyNil, tyUntyped, tyTyped,
tyTypeDesc, tyGenericInvocation, tyForward:
tyTypeDesc, tyGenericInvocation, tyForward, tyStatic:
#internalError(c.g.config, c.info, "assignment requested for type: " & typeToString(t))
discard
of tyOrdinal, tyRange, tyInferred,
tyGenericInst, tyStatic, tyAlias, tySink:
tyGenericInst, tyAlias, tySink:
fillBody(c, lastSon(t), body, x, y)
of tyOptDeprecated: doAssert false
proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
kind: TTypeAttachedOp; info: TLineInfo): PSym =
@@ -776,11 +875,11 @@ proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
typ.attachedOps[kind] = baseType.attachedOps[kind]
result = typ.attachedOps[kind]
proc symPrototype(g: ModuleGraph; typ: PType; kind: TTypeAttachedOp;
proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
info: TLineInfo): PSym =
let procname = getIdent(g.cache, AttachedOpToStr[kind])
result = newSym(skProc, procname, typ.owner, info)
result = newSym(skProc, procname, owner, info)
let dest = newSym(skParam, getIdent(g.cache, "dest"), result, info)
let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"), result, info)
dest.typ = makeVarType(typ.owner, typ)
@@ -789,7 +888,7 @@ proc symPrototype(g: ModuleGraph; typ: PType; kind: TTypeAttachedOp;
else:
src.typ = typ
result.typ = newProcType(info, typ.owner)
result.typ = newProcType(info, owner)
result.typ.addParam dest
if kind notin {attachedDestructor, attachedDispose}:
result.typ.addParam src
@@ -809,7 +908,10 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
if typ.kind == tyDistinct:
return produceSymDistinctType(g, c, typ, kind, info)
result = symPrototype(g, typ, kind, info)
result = typ.attachedOps[kind]
if result == nil:
result = symPrototype(g, typ, typ.owner, kind, info)
var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType:typ)
a.fn = result
@@ -821,11 +923,10 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
# register this operation already:
typ.attachedOps[kind] = result
if kind == attachedSink and typ.attachedOps[attachedDestructor] != nil and
sfOverriden in typ.attachedOps[attachedDestructor].flags:
if kind == attachedSink and destructorOverriden(typ):
## compiler can use a combination of `=destroy` and memCopy for sink op
dest.flags.incl sfCursor
result.ast[bodyPos].add newOpCall(typ.attachedOps[attachedDestructor], d[0])
result.ast[bodyPos].add newOpCall(a, typ.attachedOps[attachedDestructor], d[0])
result.ast[bodyPos].add newAsgnStmt(d, src)
else:
var tk: TTypeKind
@@ -840,11 +941,12 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
fillStrOp(a, typ, result.ast[bodyPos], d, src)
else:
fillBody(a, typ, result.ast[bodyPos], d, src)
if not a.canRaise: incl result.flags, sfNeverRaises
proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym, info: TLineInfo): PSym =
assert(typ.kind == tyObject)
result = symPrototype(g, field.typ, attachedDestructor, info)
assert(typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject)
result = symPrototype(g, field.typ, typ.owner, attachedDestructor, info)
var a = TLiftCtx(info: info, g: g, kind: attachedDestructor, asgnForType: typ)
a.fn = result
a.asgnForType = typ
@@ -861,6 +963,7 @@ proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym,
result.ast[bodyPos].add v
let placeHolder = newNodeIT(nkSym, info, getSysType(g, info, tyPointer))
fillBody(a, typ, result.ast[bodyPos], d, placeHolder)
if not a.canRaise: incl result.flags, sfNeverRaises
template liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
@@ -899,11 +1002,6 @@ template inst(field, t) =
proc isTrival(s: PSym): bool {.inline.} =
s == nil or (s.ast != nil and s.ast[bodyPos].len == 0)
proc isEmptyContainer(g: ModuleGraph, t: PType): bool =
(t.kind == tyArray and lengthOrd(g.config, t[0]) == 0) or
(t.kind == tySequence and t[0].kind == tyError)
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.
@@ -912,7 +1010,7 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
incl orig.flags, tfCheckedForDestructor
let skipped = orig.skipTypes({tyGenericInst, tyAlias, tySink})
if isEmptyContainer(skipped): return
if isEmptyContainer(skipped) or skipped.kind == tyStatic: return
let h = sighashes.hashType(skipped, {CoType, CoConsiderOwned, CoDistinct})
var canon = g.canonTypes.getOrDefault(h)
@@ -932,9 +1030,18 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
let lastAttached = if g.config.selectedGC == gcOrc: attachedDispose
else: attachedSink
# bug #15122: We need to produce all prototypes before entering the
# mind boggling recursion. Hacks like these imply we shoule rewrite
# this module.
var generics: array[attachedDestructor..attachedDispose, bool]
for k in attachedDestructor..lastAttached:
generics[k] = canon.attachedOps[k] != nil
if not generics[k]:
canon.attachedOps[k] = symPrototype(g, canon, canon.owner, k, info)
# we generate the destructor first so that other operators can depend on it:
for k in attachedDestructor..lastAttached:
if canon.attachedOps[k] == nil:
if not generics[k]:
discard produceSym(g, c, canon, k, info)
else:
inst(canon.attachedOps[k], canon)

View File

@@ -10,10 +10,20 @@
## This module contains the ``TMsgKind`` enum as well as the
## ``TLineInfo`` object.
import ropes, tables, pathutils
import ropes, tables, pathutils, hashes
const
explanationsBaseUrl* = "https://nim-lang.org/docs"
explanationsBaseUrl* = "https://nim-lang.github.io/Nim"
# was: "https://nim-lang.org/docs" but we're now usually showing devel docs
# instead of latest release docs.
proc createDocLink*(urlSuffix: string): string =
# os.`/` is not appropriate for urls.
result = explanationsBaseUrl
if urlSuffix.len > 0 and urlSuffix[0] == '/':
result.add urlSuffix
else:
result.add "/" & urlSuffix
type
TMsgKind* = enum
@@ -23,40 +33,43 @@ type
errGeneralParseError,
errNewSectionExpected,
errInvalidDirectiveX,
errProveInit,
errProveInit, # deadcode
errGenerated,
errUser,
warnCannotOpenFile,
warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit,
warnDeprecated, warnConfigDeprecated,
warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel,
warnUnknownSubstitutionX, warnLanguageXNotSupported,
warnFieldXNotSupported, warnCommentXIgnored,
warnTypelessParam,
warnUseBase, warnWriteToForeignHeap, warnUnsafeCode,
warnUnusedImportX,
warnInheritFromException,
warnEachIdentIsTuple,
warnUnsafeSetLen,
warnUnsafeDefault,
warnProveInit, warnProveField, warnProveIndex,
warnStaticIndexCheck, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
warnInconsistentSpacing, warnCaseTransition, warnCycleCreated,
warnObservableStores,
warnResultUsed,
warnUser,
hintSuccess, hintSuccessX, hintCC,
hintLineTooLong, hintXDeclaredButNotUsed,
hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern,
hintExecuting, hintLinking, hintDependency,
hintSource, hintPerformance, hintStackTrace, hintGCStats,
hintGlobalVar, hintExpandMacro,
hintUser, hintUserRaw,
hintExtendedContext
warnCannotOpenFile = "CannotOpenFile", warnOctalEscape = "OctalEscape",
warnXIsNeverRead = "XIsNeverRead", warnXmightNotBeenInit = "XmightNotBeenInit",
warnDeprecated = "Deprecated", warnConfigDeprecated = "ConfigDeprecated",
warnSmallLshouldNotBeUsed = "SmallLshouldNotBeUsed", warnUnknownMagic = "UnknownMagic",
warnRedefinitionOfLabel = "RedefinitionOfLabel", warnUnknownSubstitutionX = "UnknownSubstitutionX",
warnLanguageXNotSupported = "LanguageXNotSupported", warnFieldXNotSupported = "FieldXNotSupported",
warnCommentXIgnored = "CommentXIgnored", warnTypelessParam = "TypelessParam",
warnUseBase = "UseBase", warnWriteToForeignHeap = "WriteToForeignHeap",
warnUnsafeCode = "UnsafeCode", warnUnusedImportX = "UnusedImport",
warnInheritFromException = "InheritFromException", warnEachIdentIsTuple = "EachIdentIsTuple",
warnUnsafeSetLen = "UnsafeSetLen", warnUnsafeDefault = "UnsafeDefault",
warnProveInit = "ProveInit", warnProveField = "ProveField", warnProveIndex = "ProveIndex",
warnUnreachableElse = "UnreachableElse", warnUnreachableCode = "UnreachableCode",
warnStaticIndexCheck = "IndexCheck", warnGcUnsafe = "GcUnsafe", warnGcUnsafe2 = "GcUnsafe2",
warnUninit = "Uninit", warnGcMem = "GcMem", warnDestructor = "Destructor",
warnLockLevel = "LockLevel", warnResultShadowed = "ResultShadowed",
warnInconsistentSpacing = "Spacing", warnCaseTransition = "CaseTransition",
warnCycleCreated = "CycleCreated", warnObservableStores = "ObservableStores",
warnResultUsed = "ResultUsed",
warnUser = "User",
hintSuccess = "Success", hintSuccessX = "SuccessX", hintCC = "CC",
hintLineTooLong = "LineTooLong", hintXDeclaredButNotUsed = "XDeclaredButNotUsed",
hintXCannotRaiseY = "XCannotRaiseY", hintConvToBaseNotNeeded = "ConvToBaseNotNeeded",
hintConvFromXtoItselfNotNeeded = "ConvFromXtoItselfNotNeeded", hintExprAlwaysX = "ExprAlwaysX",
hintQuitCalled = "QuitCalled", hintProcessing = "Processing", hintCodeBegin = "CodeBegin",
hintCodeEnd = "CodeEnd", hintConf = "Conf", hintPath = "Path",
hintConditionAlwaysTrue = "CondTrue", hintConditionAlwaysFalse = "CondFalse", hintName = "Name",
hintPattern = "Pattern", hintExecuting = "Exec", hintLinking = "Link", hintDependency = "Dependency",
hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace",
hintGCStats = "GCStats", hintGlobalVar = "GlobalVar", hintExpandMacro = "ExpandMacro",
hintUser = "User", hintUserRaw = "UserRaw", hintExtendedContext = "ExtendedContext",
hintMsgOrigin = "MsgOrigin", # since 1.3.5
const
MsgKindToStr*: array[TMsgKind, string] = [
@@ -69,7 +82,7 @@ const
errGeneralParseError: "general parse error",
errNewSectionExpected: "new section expected",
errInvalidDirectiveX: "invalid directive: '$1'",
errProveInit: "Cannot prove that '$1' is initialized.",
errProveInit: "Cannot prove that '$1' is initialized.", # deadcode
errGenerated: "$1",
errUser: "$1",
warnCannotOpenFile: "cannot open '$1'",
@@ -99,10 +112,12 @@ const
warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
warnProveField: "cannot prove that field '$1' is accessible",
warnProveIndex: "cannot prove index '$1' is valid",
warnUnreachableElse: "unreachable else, all cases are already covered",
warnUnreachableCode: "unreachable code after 'return' statement or '{.noReturn.}' proc",
warnStaticIndexCheck: "$1",
warnGcUnsafe: "not GC-safe: '$1'",
warnGcUnsafe2: "$1",
warnUninit: "'$1' might not have been initialized",
warnUninit: "use explicit initialization of '$1' for clarity",
warnGcMem: "'$1' uses GC'ed memory",
warnDestructor: "usage of a type with a destructor in a non destructible context. This will become a compile time error in the future.",
warnLockLevel: "$1",
@@ -115,10 +130,11 @@ const
warnUser: "$1",
hintSuccess: "operation successful: $#",
# keep in sync with `testament.isSuccess`
hintSuccessX: "$loc LOC; $sec sec; $mem; $build build; proj: $project; out: $output",
hintSuccessX: "${loc} lines; ${sec}s; $mem; $build build; proj: $project; out: $output",
hintCC: "CC: $1",
hintLineTooLong: "line too long",
hintXDeclaredButNotUsed: "'$1' is declared but not used",
hintXCannotRaiseY: "$1",
hintConvToBaseNotNeeded: "conversion to base object is not needed",
hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless",
hintExprAlwaysX: "expression evaluates always to '$1'",
@@ -144,34 +160,7 @@ const
hintUser: "$1",
hintUserRaw: "$1",
hintExtendedContext: "$1",
]
const
WarningsToStr* = ["CannotOpenFile", "OctalEscape",
"XIsNeverRead", "XmightNotBeenInit",
"Deprecated", "ConfigDeprecated",
"SmallLshouldNotBeUsed", "UnknownMagic",
"RedefinitionOfLabel", "UnknownSubstitutionX",
"LanguageXNotSupported", "FieldXNotSupported",
"CommentXIgnored",
"TypelessParam", "UseBase", "WriteToForeignHeap",
"UnsafeCode", "UnusedImport", "InheritFromException",
"EachIdentIsTuple",
"UnsafeSetLen", "UnsafeDefault",
"ProveInit", "ProveField", "ProveIndex",
"IndexCheck", "GcUnsafe", "GcUnsafe2", "Uninit",
"GcMem", "Destructor", "LockLevel", "ResultShadowed",
"Spacing", "CaseTransition", "CycleCreated",
"ObservableStores", "ResultUsed", "User"]
HintsToStr* = [
"Success", "SuccessX", "CC", "LineTooLong",
"XDeclaredButNotUsed",
"ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
"Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency",
"Source", "Performance", "StackTrace", "GCStats", "GlobalVar", "ExpandMacro",
"User", "UserRaw", "ExtendedContext",
hintMsgOrigin: "$1",
]
const
@@ -184,20 +173,16 @@ const
hintMin* = hintSuccess
hintMax* = high(TMsgKind)
static:
doAssert HintsToStr.len == ord(hintMax) - ord(hintMin) + 1
doAssert WarningsToStr.len == ord(warnMax) - ord(warnMin) + 1
type
TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints
TNoteKinds* = set[TNoteKind]
proc computeNotesVerbosity(): array[0..3, TNoteKinds] =
result[3] = {low(TNoteKind)..high(TNoteKind)} - {warnResultUsed}
result[3] = {low(TNoteKind)..high(TNoteKind)} - {warnObservableStores, warnResultUsed}
result[2] = result[3] - {hintStackTrace, warnUninit, hintExtendedContext}
result[1] = result[2] - {warnProveField, warnProveIndex,
warnGcUnsafe, hintPath, hintDependency, hintCodeBegin, hintCodeEnd,
hintSource, hintGlobalVar, hintGCStats}
hintSource, hintGlobalVar, hintGCStats, hintMsgOrigin}
result[0] = result[1] - {hintSuccessX, hintSuccess, hintConf,
hintProcessing, hintPattern, hintExecuting, hintLinking, hintCC}
@@ -252,6 +237,9 @@ type
proc `==`*(a, b: FileIndex): bool {.borrow.}
proc hash*(i: TLineInfo): Hash =
hash (i.line.int, i.col.int, i.fileIndex.int)
proc raiseRecoverableError*(msg: string) {.noinline.} =
raise newException(ERecoverableError, msg)

View File

@@ -71,12 +71,9 @@ proc beautifyName(s: string, k: TSymKind): string =
proc differ*(line: string, a, b: int, x: string): string =
proc substrEq(s: string, pos, last: int, substr: string): bool =
var i = 0
while i < substr.len and pos+i <= last and s[pos+i] == substr[i]:
inc i
return i == substr.len
let last = min(b, line.len)
result = true
for i in 0..<substr.len:
if pos+i > last or s[pos+i] != substr[i]: return false
result = ""
if not substrEq(line, a, b, x):
@@ -84,11 +81,6 @@ proc differ*(line: string, a, b: int, x: string): string =
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:
lintReport(conf, info, beau, s)
proc nep1CheckDefImpl(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
# operators stay as they are:
if k in {skResult, skTemp} or s.name.s[0] notin Letters: return
@@ -136,6 +128,6 @@ proc styleCheckUse*(conf: ConfigRef; info: TLineInfo; s: PSym) =
lintReport(conf, info, newName, oldName)
proc checkPragmaUse*(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragmaName: string) =
let wanted = canonPragmaSpelling(w)
let wanted = $w
if pragmaName != wanted:
lintReport(conf, info, wanted, pragmaName)

View File

@@ -91,8 +91,15 @@ proc skipAlias*(s: PSym; n: PNode; conf: ConfigRef): PSym =
message(conf, n.info, warnDeprecated, "use " & result.name.s & " instead; " &
s.name.s & " is deprecated")
proc isShadowScope*(s: PScope): bool {.inline.} = s.parent != nil and s.parent.depthLevel == s.depthLevel
proc localSearchInScope*(c: PContext, s: PIdent): PSym =
result = strTableGet(c.currentScope.symbols, s)
var scope = c.currentScope
result = strTableGet(scope.symbols, s)
while result == nil and scope.isShadowScope:
# We are in a shadow scope, check in the parent too
scope = scope.parent
result = strTableGet(scope.symbols, s)
proc searchInScopes*(c: PContext, s: PIdent): PSym =
for scope in walkScopes(c.currentScope):
@@ -231,6 +238,23 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
addOverloadableSymAt(c, scope, sym)
addInterfaceDeclAux(c, sym)
proc openShadowScope*(c: PContext) =
c.currentScope = PScope(parent: c.currentScope,
symbols: newStrTable(),
depthLevel: c.scopeDepth)
proc closeShadowScope*(c: PContext) =
c.closeScope
proc mergeShadowScope*(c: PContext) =
let shadowScope = c.currentScope
c.rawCloseScope
for sym in shadowScope.symbols:
if sym.kind in OverloadableSyms:
c.addInterfaceOverloadableSymAt(c.currentScope, sym)
else:
c.addInterfaceDecl(sym)
when defined(nimfix):
# when we cannot find the identifier, retry with a changed identifier:
proc altSpelling(x: PIdent): PIdent =
@@ -316,8 +340,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
fixSpelling(n, ident, searchInScopes)
errorUndeclaredIdentifier(c, n.info, ident.s)
result = errorSym(c, n)
elif checkAmbiguity in flags and result != nil and
contains(c.ambiguousSymbols, result.id):
elif checkAmbiguity in flags and result != nil and result.id in c.ambiguousSymbols:
errorUseQualifier(c, n.info, result)
of nkSym:
result = n.sym

View File

@@ -59,6 +59,13 @@ proc newFastAsgnStmt*(le, ri: PNode): PNode =
result[0] = le
result[1] = ri
proc newFastMoveStmt*(g: ModuleGraph, le, ri: PNode): PNode =
result = newNodeI(nkFastAsgn, le.info, 2)
result[0] = le
result[1] = newNodeIT(nkCall, ri.info, ri.typ)
result[1].add newSymNode(getSysMagic(g, ri.info, "move", mMove))
result[1].add ri
proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
assert n.kind == nkVarTuple
let value = n.lastSon
@@ -129,6 +136,7 @@ proc lowerSwap*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
var temp = newSym(skVar, getIdent(g.cache, genPrefix), owner, n.info, owner.options)
temp.typ = n[1].typ
incl(temp.flags, sfFromGeneric)
incl(temp.flags, sfGenSym)
var v = newNodeI(nkVarSection, n.info)
let tempAsNode = newSymNode(temp)
@@ -151,7 +159,7 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType
else:
rawAddSon(result, getCompilerProc(g, "RootObj").typ)
result.n = newNodeI(nkRecList, info)
let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info)),
let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info) & "_" & $owner.name.s),
owner, info, owner.options)
incl s.flags, sfAnon
s.typ = result
@@ -362,14 +370,3 @@ proc genLen*(g: ModuleGraph; n: PNode): PNode =
result[0] = newSymNode(getSysMagic(g, n.info, "len", mLengthSeq))
result[1] = n
proc hoistExpr*(varSection, expr: PNode, name: PIdent, owner: PSym): PSym =
result = newSym(skLet, name, owner, varSection.info, owner.options)
result.flags.incl sfHoisted
result.typ = expr.typ
var varDef = newNodeI(nkIdentDefs, varSection.info, 3)
varDef[0] = newSymNode(result)
varDef[1] = newNodeI(nkEmpty, varSection.info)
varDef[2] = expr
varSection.add varDef

View File

@@ -19,7 +19,7 @@ import
cgen, json, nversion,
platform, nimconf, passaux, depends, vm, idgen,
modules,
modulegraphs, tables, rod, lineinfos, pathutils
modulegraphs, tables, rod, lineinfos, pathutils, vmprofiler
when not defined(leanCompiler):
import jsgen, docgen, docgen2
@@ -51,7 +51,7 @@ proc commandGenDepend(graph: ModuleGraph) =
' ' & changeFileExt(project, "dot").string)
proc commandCheck(graph: ModuleGraph) =
graph.config.errorMax = high(int) # do not stop after first error
graph.config.setErrorMaxHighMaybe
defineSymbol(graph.config.symbols, "nimcheck")
semanticPasses(graph) # use an empty backend for semantic checking only
compileProject(graph)
@@ -59,7 +59,7 @@ proc commandCheck(graph: ModuleGraph) =
when not defined(leanCompiler):
proc commandDoc2(graph: ModuleGraph; json: bool) =
handleDocOutputOptions graph.config
graph.config.errorMax = high(int) # do not stop after first error
graph.config.setErrorMaxHighMaybe
semanticPasses(graph)
if json: registerPass(graph, docgen2JsonPass)
else: registerPass(graph, docgen2Pass)
@@ -68,16 +68,7 @@ when not defined(leanCompiler):
proc commandCompileToC(graph: ModuleGraph) =
let conf = graph.config
if conf.outDir.isEmpty:
conf.outDir = conf.projectPath
if conf.outFile.isEmpty:
let targetName = if optGenDynLib in conf.globalOptions:
platform.OS[conf.target.targetOS].dllFrmt % conf.projectName
else:
conf.projectName & platform.OS[conf.target.targetOS].exeExt
conf.outFile = RelativeFile targetName
setOutFile(conf)
extccomp.initVars(conf)
semanticPasses(graph)
registerPass(graph, cgenPass)
@@ -108,13 +99,13 @@ proc commandJsonScript(graph: ModuleGraph) =
let proj = changeFileExt(graph.config.projectFull, "")
extccomp.runJsonBuildInstructions(graph.config, proj)
when not defined(leanCompiler):
proc commandCompileToJS(graph: ModuleGraph) =
proc commandCompileToJS(graph: ModuleGraph) =
when defined(leanCompiler):
globalError(graph.config, unknownLineInfo, "compiler wasn't built with JS code generator")
else:
let conf = graph.config
conf.exc = excCpp
if conf.outDir.isEmpty:
conf.outDir = conf.projectPath
if conf.outFile.isEmpty:
conf.outFile = RelativeFile(conf.projectName & ".js")
@@ -122,7 +113,6 @@ when not defined(leanCompiler):
setTarget(graph.config.target, osJS, cpuJS)
#initDefines()
defineSymbol(graph.config.symbols, "ecmascript") # For backward compatibility
defineSymbol(graph.config.symbols, "js")
semanticPasses(graph)
registerPass(graph, JSgenPass)
compileProject(graph)
@@ -139,7 +129,7 @@ proc interactivePasses(graph: ModuleGraph) =
registerPass(graph, evalPass)
proc commandInteractive(graph: ModuleGraph) =
graph.config.errorMax = high(int) # do not stop after first error
graph.config.setErrorMaxHighMaybe
interactivePasses(graph)
compileSystemModule(graph)
if graph.config.commandArgs.len > 0:
@@ -159,8 +149,8 @@ proc commandScan(cache: IdentCache, config: ConfigRef) =
var stream = llStreamOpen(f, fmRead)
if stream != nil:
var
L: TLexer
tok: TToken
L: Lexer
tok: Token
initToken(tok)
openLexer(L, f, stream, cache, config)
while true:
@@ -184,63 +174,103 @@ proc mainCommand*(graph: ModuleGraph) =
conf.lastCmdTime = epochTime()
conf.searchPaths.add(conf.libpath)
setId(100)
case conf.command.normalize
of "c", "cc", "compile", "compiletoc":
# compile means compileToC currently
conf.cmd = cmdCompileToC
if conf.exc == excNone: conf.exc = excSetjmp
defineSymbol(graph.config.symbols, "c")
commandCompileToC(graph)
of "cpp", "compiletocpp":
conf.cmd = cmdCompileToCpp
if conf.exc == excNone: conf.exc = excCpp
defineSymbol(graph.config.symbols, "cpp")
commandCompileToC(graph)
of "objc", "compiletooc":
conf.cmd = cmdCompileToOC
defineSymbol(graph.config.symbols, "objc")
commandCompileToC(graph)
of "run":
conf.cmd = cmdRun
when hasTinyCBackend:
extccomp.setCC(conf, "tcc", unknownLineInfo)
commandCompileToC(graph)
else:
rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc")
of "js", "compiletojs":
when defined(leanCompiler):
quit "compiler wasn't built with JS code generator"
else:
conf.cmd = cmdCompileToJS
proc customizeForBackend(backend: TBackend) =
## Sets backend specific options but don't compile to backend yet in
## case command doesn't require it. This must be called by all commands.
if conf.backend == backendInvalid:
# only set if wasn't already set, to allow override via `nim c -b:cpp`
conf.backend = backend
defineSymbol(graph.config.symbols, $conf.backend)
case conf.backend
of backendC:
if conf.exc == excNone: conf.exc = excSetjmp
of backendCpp:
if conf.exc == excNone: conf.exc = excCpp
of backendObjc: discard
of backendJs:
if conf.hcrOn:
# XXX: At the moment, system.nim cannot be compiled in JS mode
# with "-d:useNimRtl". The HCR option has been processed earlier
# and it has added this define implictly, so we must undo that here.
# A better solution might be to fix system.nim
undefSymbol(conf.symbols, "useNimRtl")
commandCompileToJS(graph)
of "doc0":
of backendInvalid: doAssert false
if conf.selectedGC in {gcArc, gcOrc} and conf.backend != backendCpp:
conf.exc = excGoto
var commandAlreadyProcessed = false
proc compileToBackend(backend: TBackend, cmd = cmdCompileToBackend) =
commandAlreadyProcessed = true
conf.cmd = cmd
customizeForBackend(backend)
case conf.backend
of backendC: commandCompileToC(graph)
of backendCpp: commandCompileToC(graph)
of backendObjc: commandCompileToC(graph)
of backendJs: commandCompileToJS(graph)
of backendInvalid: doAssert false
template docLikeCmd(body) =
when defined(leanCompiler):
quit "compiler wasn't built with documentation generator"
else:
wantMainModule(conf)
conf.cmd = cmdDoc
loadConfigs(DocConfig, cache, conf)
commandDoc(cache, conf)
of "doc2", "doc":
conf.setNoteDefaults(warnLockLevel, false) # issue #13218
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # issue #13218
# because currently generates lots of false positives due to conflation
# of labels links in doc comments, eg for random.rand:
# ## * `rand proc<#rand,Rand,Natural>`_ that returns an integer
# ## * `rand proc<#rand,Rand,range[]>`_ that returns a float
when defined(leanCompiler):
quit "compiler wasn't built with documentation generator"
else:
conf.cmd = cmdDoc
loadConfigs(DocConfig, cache, conf)
defineSymbol(conf.symbols, "nimdoc")
body
block: ## command prepass
var docLikeCmd2 = false # includes what calls `docLikeCmd` + some more
case conf.command.normalize
of "r": conf.globalOptions.incl {optRun, optUseNimcache}
of "doc0", "doc2", "doc", "rst2html", "rst2tex", "jsondoc0", "jsondoc2",
"jsondoc", "ctags", "buildindex": docLikeCmd2 = true
else: discard
if conf.outDir.isEmpty:
# doc like commands can generate a lot of files (especially with --project)
# so by default should not end up in $PWD nor in $projectPath.
conf.outDir = block:
var ret = if optUseNimcache in conf.globalOptions: getNimcacheDir(conf)
else: conf.projectPath
doAssert ret.string.isAbsolute # `AbsoluteDir` is not a real guarantee
if docLikeCmd2: ret = ret / htmldocsDir
ret
## process all backend commands
case conf.command.normalize
of "c", "cc", "compile", "compiletoc": compileToBackend(backendC) # compile means compileToC currently
of "cpp", "compiletocpp": compileToBackend(backendCpp)
of "objc", "compiletooc": compileToBackend(backendObjc)
of "js", "compiletojs": compileToBackend(backendJs)
of "r": compileToBackend(backendC) # different from `"run"`!
of "run":
when hasTinyCBackend:
extccomp.setCC(conf, "tcc", unknownLineInfo)
if conf.backend notin {backendC, backendInvalid}:
rawMessage(conf, errGenerated, "'run' requires c backend, got: '$1'" % $conf.backend)
compileToBackend(backendC, cmd = cmdRun)
else:
rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc")
else: customizeForBackend(backendC) # fallback for other commands
## process all other commands
case conf.command.normalize # synchronize with `cmdUsingHtmlDocs`
of "doc0": docLikeCmd commandDoc(cache, conf)
of "doc2", "doc":
docLikeCmd():
conf.setNoteDefaults(warnLockLevel, false) # issue #13218
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # issue #13218
# because currently generates lots of false positives due to conflation
# of labels links in doc comments, e.g. for random.rand:
# ## * `rand proc<#rand,Rand,Natural>`_ that returns an integer
# ## * `rand proc<#rand,Rand,range[]>`_ that returns a float
commandDoc2(graph, false)
if optGenIndex in conf.globalOptions and optWholeProject in conf.globalOptions:
commandBuildIndex(conf, $conf.outDir)
of "rst2html":
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # similar to issue #13218
when defined(leanCompiler):
@@ -256,41 +286,10 @@ proc mainCommand*(graph: ModuleGraph) =
conf.cmd = cmdRst2tex
loadConfigs(DocTexConfig, cache, conf)
commandRst2TeX(cache, conf)
of "jsondoc0":
when defined(leanCompiler):
quit "compiler wasn't built with documentation generator"
else:
wantMainModule(conf)
conf.cmd = cmdDoc
loadConfigs(DocConfig, cache, conf)
wantMainModule(conf)
defineSymbol(conf.symbols, "nimdoc")
commandJson(cache, conf)
of "jsondoc2", "jsondoc":
when defined(leanCompiler):
quit "compiler wasn't built with documentation generator"
else:
conf.cmd = cmdDoc
loadConfigs(DocConfig, cache, conf)
wantMainModule(conf)
defineSymbol(conf.symbols, "nimdoc")
commandDoc2(graph, true)
of "ctags":
when defined(leanCompiler):
quit "compiler wasn't built with documentation generator"
else:
wantMainModule(conf)
conf.cmd = cmdDoc
loadConfigs(DocConfig, cache, conf)
defineSymbol(conf.symbols, "nimdoc")
commandTags(cache, conf)
of "buildindex":
when defined(leanCompiler):
quit "compiler wasn't built with documentation generator"
else:
conf.cmd = cmdDoc
loadConfigs(DocConfig, cache, conf)
commandBuildIndex(cache, conf)
of "jsondoc0": docLikeCmd commandJson(cache, conf)
of "jsondoc2", "jsondoc": docLikeCmd commandDoc2(graph, true)
of "ctags": docLikeCmd commandTags(cache, conf)
of "buildindex": docLikeCmd commandBuildIndex(conf, $conf.projectFull, conf.outFile)
of "gendepend":
conf.cmd = cmdGenDepend
commandGenDepend(graph)
@@ -309,12 +308,10 @@ proc mainCommand*(graph: ModuleGraph) =
var hints = newJObject() # consider factoring with `listHints`
for a in hintMin..hintMax:
let key = lineinfos.HintsToStr[ord(a) - ord(hintMin)]
hints[key] = %(a in conf.notes)
hints[$a] = %(a in conf.notes)
var warnings = newJObject()
for a in warnMin..warnMax:
let key = lineinfos.WarningsToStr[ord(a) - ord(warnMin)]
warnings[key] = %(a in conf.notes)
warnings[$a] = %(a in conf.notes)
var dumpdata = %[
(key: "version", val: %VersionAsString),
@@ -366,7 +363,9 @@ proc mainCommand*(graph: ModuleGraph) =
conf.cmd = cmdDump
of "jsonscript":
conf.cmd = cmdJsonScript
setOutFile(graph.config)
commandJsonScript(graph)
elif commandAlreadyProcessed: discard # already handled
else:
rawMessage(conf, errGenerated, "invalid command: " & conf.command)
@@ -381,8 +380,18 @@ proc mainCommand*(graph: ModuleGraph) =
else: "Debug"
let sec = formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3)
let project = if optListFullPaths in conf.globalOptions: $conf.projectFull else: $conf.projectName
var output = $conf.absOutFile
var output: string
if optCompileOnly in conf.globalOptions and conf.cmd != cmdJsonScript:
output = $conf.jsonBuildFile
elif conf.outFile.isEmpty and conf.cmd notin {cmdJsonScript, cmdCompileToBackend, cmdDoc}:
# for some cmd we expect a valid absOutFile
output = "unknownOutput"
else:
output = $conf.absOutFile
if optListFullPaths notin conf.globalOptions: output = output.AbsoluteFile.extractFilename
if optProfileVM in conf.globalOptions:
echo conf.dump(conf.vmProfileData)
rawMessage(conf, hintSuccessX, [
"loc", loc,
"sec", sec,
@@ -399,5 +408,3 @@ proc mainCommand*(graph: ModuleGraph) =
echo " int tries: ", gCacheIntTries
echo " efficiency: ", formatFloat(1-(gCacheMisses.float/gCacheTries.float),
ffDecimal, 3)
resetAttributes(conf)

View File

@@ -31,7 +31,7 @@ import ast, intsets, tables, options, lineinfos, hashes, idents,
type
SigHash* = distinct MD5Digest
ModuleGraph* = ref object
ModuleGraph* {.acyclic.} = ref object
modules*: seq[PSym] ## indexed by int32 fileIdx
packageSyms*: TStrTable
deps*: IntSet # the dependency graph or potentially its transitive closure.
@@ -72,9 +72,7 @@ type
onDefinitionResolveForward*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
onUsage*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
globalDestructors*: seq[PNode]
proofEngine*: proc (graph: ModuleGraph; assumptions: seq[PNode]; toProve: PNode): (bool, string) {.nimcall.}
requirementsCheck*: proc (graph: ModuleGraph; assumptions: seq[PNode];
call, requirement: PNode): (bool, string) {.nimcall.}
strongSemCheck*: proc (graph: ModuleGraph; owner: PSym; body: PNode) {.nimcall.}
compatibleProps*: proc (graph: ModuleGraph; formal, actual: PType): bool {.nimcall.}
TPassContext* = object of RootObj # the pass's context

View File

@@ -91,8 +91,7 @@ when false:
if result.len > 0: return result
proc scriptableImport(pkg, sub: string; info: TLineInfo): string =
result = resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info)
if result.isNil: result = ""
resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info)
proc lookupPackage(pkg, subdir: PNode): string =
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
@@ -112,8 +111,7 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
try:
result =
pathSubs(conf, n.strVal, toFullPath(conf, n.info).splitFile().dir)
result = pathSubs(conf, n.strVal, toFullPath(conf, n.info).splitFile().dir)
except ValueError:
localError(conf, n.info, "invalid path: " & n.strVal)
result = n.strVal

View File

@@ -17,22 +17,29 @@ import
proc resetSystemArtifacts*(g: ModuleGraph) =
magicsys.resetSysTypes(g)
proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; filename: AbsoluteFile) =
template getModuleIdent(graph: ModuleGraph, filename: AbsoluteFile): PIdent =
getIdent(graph.cache, splitFile(filename).name)
proc getPackage(graph: ModuleGraph; fileIdx: FileIndex): PSym =
## returns package symbol (skPackage) for yet to be defined module for fileIdx
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
let name = getModuleIdent(graph, filename)
let info = newLineInfo(fileIdx, 1, 1)
let
pck = getPackageName(graph.config, filename.string)
pck2 = if pck.len > 0: pck else: "unknown"
pack = getIdent(graph.cache, pck2)
var packSym = graph.packageSyms.strTableGet(pack)
if packSym == nil:
packSym = newSym(skPackage, getIdent(graph.cache, pck2), nil, result.info)
packSym = newSym(skPackage, getIdent(graph.cache, pck2), nil, info)
initStrTable(packSym.tab)
graph.packageSyms.strTableAdd(packSym)
else:
let existing = strTableGet(packSym.tab, result.name)
if existing != nil and existing.info.fileIndex != result.info.fileIndex:
let existing = strTableGet(packSym.tab, name)
if existing != nil and existing.info.fileIndex != info.fileIndex:
when false:
# we used to produce an error:
localError(graph.config, result.info,
localError(graph.config, info,
"module names need to be unique per Nimble package; module clashes with " &
toFullPath(graph.config, existing.info.fileIndex))
else:
@@ -40,10 +47,13 @@ proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; fil
# to resolve the conflicts:
let pck3 = fakePackageName(graph.config, filename)
# this makes the new `packSym`'s owner be the original `packSym`
packSym = newSym(skPackage, getIdent(graph.cache, pck3), packSym, result.info)
packSym = newSym(skPackage, getIdent(graph.cache, pck3), packSym, info)
initStrTable(packSym.tab)
graph.packageSyms.strTableAdd(packSym)
result = packSym
proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; filename: AbsoluteFile) =
let packSym = getPackage(graph, fileIdx)
result.owner = packSym
result.position = int fileIdx
@@ -60,13 +70,15 @@ proc newModule(graph: ModuleGraph; fileIdx: FileIndex): PSym =
# We cannot call ``newSym`` here, because we have to circumvent the ID
# mechanism, which we do in order to assign each module a persistent ID.
result = PSym(kind: skModule, id: -1, # for better error checking
name: getIdent(graph.cache, splitFile(filename).name),
name: getModuleIdent(graph, filename),
info: newLineInfo(fileIdx, 1, 1))
if not isNimIdentifier(result.name.s):
rawMessage(graph.config, errGenerated, "invalid module name: " & result.name.s)
partialInitModule(result, graph, fileIdx, filename)
proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): PSym =
var flags = flags
if fileIdx == graph.config.projectMainIdx2: flags.incl sfMainModule
result = graph.getModule(fileIdx)
if result == nil:
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
@@ -74,7 +86,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P
result = r
if result == nil:
result = newModule(graph, fileIdx)
result.flags = result.flags + flags
result.flags.incl flags
result.id = id
registerModule(graph, result)
else:
@@ -104,7 +116,7 @@ proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym =
# localError(result.info, errAttemptToRedefine, result.name.s)
# restore the notes for outer module:
graph.config.notes =
if s.owner.id == graph.config.mainPackageId or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
if s.getnimblePkgId == graph.config.mainPackageId or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
else: graph.config.foreignPackageNotes
proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PNode =
@@ -125,7 +137,7 @@ proc compileSystemModule*(graph: ModuleGraph) =
proc wantMainModule*(conf: ConfigRef) =
if conf.projectFull.isEmpty:
fatal(conf, newLineInfo(conf, AbsoluteFile"command line", 1, 1), errGenerated,
fatal(conf, newLineInfo(conf, AbsoluteFile(commandLineDesc), 1, 1), errGenerated,
"command expects a filename")
conf.projectMainIdx = fileInfoIdx(conf, addFileExt(conf.projectFull, NimExt))
@@ -135,7 +147,12 @@ proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
wantMainModule(conf)
let systemFileIdx = fileInfoIdx(conf, conf.libpath / RelativeFile"system.nim")
let projectFile = if projectFileIdx == InvalidFileIdx: conf.projectMainIdx else: projectFileIdx
conf.projectMainIdx2 = projectFile
let packSym = getPackage(graph, projectFile)
graph.config.mainPackageId = packSym.getnimblePkgId
graph.importStack.add projectFile
if projectFile == systemFileIdx:
discard graph.compileModule(projectFile, {sfMainModule, sfSystemModule})
else:

View File

@@ -10,6 +10,17 @@
import
options, strutils, os, tables, ropes, terminal, macros,
lineinfos, pathutils
import std/private/miscdollars
import strutils2
type InstantiationInfo* = typeof(instantiationInfo())
template instLoc(): InstantiationInfo = instantiationInfo(-2, fullPaths = true)
template flushDot(conf, stdorr) =
## safe to call multiple times
if conf.lastMsgWasDot:
conf.lastMsgWasDot = false
write(stdorr, "\n")
proc toCChar*(c: char; result: var string) =
case c
@@ -34,7 +45,6 @@ proc makeCString*(s: string): Rope =
res.add('\"')
result.add(rope(res))
proc newFileInfo(fullPath: AbsoluteFile, projPath: RelativeFile): TFileInfo =
result.fullPath = fullPath
#shallow(result.fullPath)
@@ -57,6 +67,12 @@ when defined(nimpretty):
proc fileSection*(conf: ConfigRef; fid: FileIndex; a, b: int): string =
substr(conf.m.fileInfos[fid.int].fullContent, a, b)
proc canonicalCase(path: var string) =
## the idea is to only use this for checking whether a path is already in
## the table but otherwise keep the original case
when FileSystemCaseSensitive: discard
else: toLowerAscii(path)
proc fileInfoKnown*(conf: ConfigRef; filename: AbsoluteFile): bool =
var
canon: AbsoluteFile
@@ -64,6 +80,7 @@ proc fileInfoKnown*(conf: ConfigRef; filename: AbsoluteFile): bool =
canon = canonicalizePath(conf, filename)
except OSError:
canon = filename
canon.string.canonicalCase
result = conf.m.filenameToIndexTbl.hasKey(canon.string)
proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile; isKnownFile: var bool): FileIndex =
@@ -80,15 +97,19 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile; isKnownFile: var bool
# This flag indicates that we are working with such a path here
pseudoPath = true
if conf.m.filenameToIndexTbl.hasKey(canon.string):
var canon2: string
forceCopy(canon2, canon.string) # because `canon` may be shallow
canon2.canonicalCase
if conf.m.filenameToIndexTbl.hasKey(canon2):
isKnownFile = true
result = conf.m.filenameToIndexTbl[canon.string]
result = conf.m.filenameToIndexTbl[canon2]
else:
isKnownFile = false
result = conf.m.fileInfos.len.FileIndex
conf.m.fileInfos.add(newFileInfo(canon, if pseudoPath: RelativeFile filename
else: relativeTo(canon, conf.projectPath)))
conf.m.filenameToIndexTbl[canon.string] = result
conf.m.filenameToIndexTbl[canon2] = result
proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile): FileIndex =
var dummy: bool
@@ -108,6 +129,7 @@ proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =
proc newLineInfo*(conf: ConfigRef; filename: AbsoluteFile, line, col: int): TLineInfo {.inline.} =
result = newLineInfo(fileInfoIdx(conf, filename), line, col)
const gCmdLineInfo* = newLineInfo(commandLineIdx, 1, 1)
proc concat(strings: openArray[string]): string =
var totalLen = 0
@@ -132,7 +154,6 @@ proc suggestQuit*() =
# this format is understood by many text editors: it is the same that
# Borland and Freepascal use
const
PosFormat = "$1($2, $3) "
KindFormat = " [$1]"
KindColor = fgCyan
ErrorTitle = "Error: "
@@ -145,6 +166,7 @@ const
# but column numbers start with 0, however most editors expect
# first column to be 1, so we need to +1 here
ColOffset* = 1
commandLineDesc* = "command line"
proc getInfoContextLen*(conf: ConfigRef): int = return conf.m.msgContext.len
proc setInfoContextLen*(conf: ConfigRef; L: int) = setLen(conf.m.msgContext, L)
@@ -160,9 +182,6 @@ proc getInfoContext*(conf: ConfigRef; index: int): TLineInfo =
if i >=% conf.m.msgContext.len: result = unknownLineInfo
else: result = conf.m.msgContext[i].info
const
commandLineDesc = "command line"
template toFilename*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil:
(if fileIdx == commandLineIdx: commandLineDesc else: "???")
@@ -213,16 +232,36 @@ template toFullPath*(conf: ConfigRef; info: TLineInfo): string =
template toFullPathConsiderDirty*(conf: ConfigRef; info: TLineInfo): string =
string toFullPathConsiderDirty(conf, info.fileIndex)
type FilenameOption* = enum
foAbs # absolute path, e.g.: /pathto/bar/foo.nim
foRelProject # relative to project path, e.g.: ../foo.nim
foMagicSauce # magic sauce, shortest of (foAbs, foRelProject)
foName # lastPathPart, e.g.: foo.nim
foStacktrace # if optExcessiveStackTrace: foAbs else: foName
proc toFilenameOption*(conf: ConfigRef, fileIdx: FileIndex, opt: FilenameOption): string =
case opt
of foAbs: result = toFullPath(conf, fileIdx)
of foRelProject: result = toProjPath(conf, fileIdx)
of foMagicSauce:
let
absPath = toFullPath(conf, fileIdx)
relPath = toProjPath(conf, fileIdx)
result = if (optListFullPaths in conf.globalOptions) or
(relPath.len > absPath.len) or
(relPath.count("..") > 2):
absPath
else:
relPath
of foName: result = toProjPath(conf, fileIdx).lastPathPart
of foStacktrace:
if optExcessiveStackTrace in conf.globalOptions:
result = toFilenameOption(conf, fileIdx, foAbs)
else:
result = toFilenameOption(conf, fileIdx, foName)
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
toFilenameOption(conf, info, foMagicSauce)
template toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
toMsgFilename(conf, info.fileIndex)
@@ -233,10 +272,11 @@ proc toLinenumber*(info: TLineInfo): int {.inline.} =
proc toColumn*(info: TLineInfo): int {.inline.} =
result = info.col
proc toFileLineCol(info: InstantiationInfo): string {.inline.} =
result.toLocation(info.filename, info.line, info.column + ColOffset)
proc toFileLineCol*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
# consider calling `helpers.lineInfoToString` instead
result = toMsgFilename(conf, info) & "(" & $info.line & ", " &
$(info.col + ColOffset) & ")"
result.toLocation(toMsgFilename(conf, info), info.line.int, info.col.int + ColOffset)
proc `$`*(conf: ConfigRef; info: TLineInfo): string = toFileLineCol(conf, info)
@@ -261,15 +301,16 @@ proc msgWriteln*(conf: ConfigRef; s: string, flags: MsgFlags = {}) =
## This is used for 'nim dump' etc. where we don't have nimsuggest
## support.
#if conf.cmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
if not isNil(conf.writelnHook) and msgSkipHook notin flags:
conf.writelnHook(s)
elif optStdout in conf.globalOptions or msgStdout in flags:
if eStdOut in conf.m.errorOutputs:
flushDot(conf, stdout)
writeLine(stdout, s)
flushFile(stdout)
else:
if eStdErr in conf.m.errorOutputs:
flushDot(conf, stderr)
writeLine(stderr, s)
# On Windows stderr is fully-buffered when piped, regardless of C std.
when defined(windows):
@@ -298,40 +339,48 @@ macro callStyledWriteLineStderr(args: varargs[typed]): untyped =
result.add(bindSym"stderr")
for arg in children(args[0][1]):
result.add(arg)
when false:
# not needed because styledWriteLine already ends with resetAttributes
result = newStmtList(result, newCall(bindSym"resetAttributes", bindSym"stderr"))
template callWritelnHook(args: varargs[string, `$`]) =
conf.writelnHook concat(args)
proc msgWrite(conf: ConfigRef; s: string) =
if conf.m.errorOutputs != {}:
let stdOrr =
if optStdout in conf.globalOptions:
stdout
else:
stderr
write(stdOrr, s)
flushFile(stdOrr)
conf.lastMsgWasDot = true # subsequent writes need `flushDot`
template styledMsgWriteln*(args: varargs[typed]) =
if not isNil(conf.writelnHook):
callIgnoringStyle(callWritelnHook, nil, args)
elif optStdout in conf.globalOptions:
if eStdOut in conf.m.errorOutputs:
flushDot(conf, stdout)
callIgnoringStyle(writeLine, stdout, args)
flushFile(stdout)
else:
if eStdErr in conf.m.errorOutputs:
if optUseColors in conf.globalOptions:
callStyledWriteLineStderr(args)
else:
callIgnoringStyle(writeLine, stderr, args)
# On Windows stderr is fully-buffered when piped, regardless of C std.
when defined(windows):
flushFile(stderr)
elif eStdErr in conf.m.errorOutputs:
flushDot(conf, stderr)
if optUseColors in conf.globalOptions:
callStyledWriteLineStderr(args)
else:
callIgnoringStyle(writeLine, stderr, args)
# On Windows stderr is fully-buffered when piped, regardless of C std.
when defined(windows):
flushFile(stderr)
proc coordToStr(coord: int): string =
if coord == -1: result = "???"
else: result = $coord
proc msgKindToString*(kind: TMsgKind): string =
proc msgKindToString*(kind: TMsgKind): string = MsgKindToStr[kind]
# later versions may provide translated error messages
result = MsgKindToStr[kind]
proc getMessageStr(msg: TMsgKind, arg: string): string =
result = msgKindToString(msg) % [arg]
proc getMessageStr(msg: TMsgKind, arg: string): string = msgKindToString(msg) % [arg]
type
TErrorHandling = enum doNothing, doAbort, doRaise
type TErrorHandling* = enum doNothing, doAbort, doRaise
proc log*(s: string) =
var f: File
@@ -345,16 +394,18 @@ proc quit(conf: ConfigRef; msg: TMsgKind) {.gcsafe.} =
if stackTraceAvailable() and isNil(conf.writelnHook):
writeStackTrace()
else:
styledMsgWriteln(fgRed, "No stack traceback available\n" &
"To create a stacktrace, rerun compilation with ./koch temp " &
conf.command & " <file>")
styledMsgWriteln(fgRed, """
No stack traceback available
To create a stacktrace, rerun compilation with './koch temp $1 <file>', see $2 for details""" %
[conf.command, "intern.html#debugging-the-compiler".createDocLink])
quit 1
proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string) =
if msg >= fatalMin and msg <= fatalMax:
if conf.cmd == cmdIdeTools: log(s)
quit(conf, msg)
if msg >= errMin and msg <= errMax:
if msg >= errMin and msg <= errMax or
(msg in warnMin..warnMax and msg in conf.warningAsErrors):
inc(conf.errorCounter)
conf.exitcode = 1'i8
if conf.errorCounter >= conf.errorMax:
@@ -385,80 +436,34 @@ proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) =
instantiationFrom
else:
instantiationOfFrom.format(context.detail)
styledMsgWriteln(styleBright,
PosFormat % [toMsgFilename(conf, context.info),
coordToStr(context.info.line.int),
coordToStr(context.info.col+ColOffset)],
resetStyle,
message)
styledMsgWriteln(styleBright, conf.toFileLineCol(context.info), " ", resetStyle, message)
info = context.info
proc ignoreMsgBecauseOfIdeTools(conf: ConfigRef; msg: TMsgKind): bool =
msg >= errGenerated and conf.cmd == cmdIdeTools and optIdeDebug notin conf.globalOptions
proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
var
title: string
color: ForegroundColor
kind: string
sev: Severity
case msg
of errMin..errMax:
sev = Severity.Error
writeContext(conf, unknownLineInfo)
title = ErrorTitle
color = ErrorColor
of warnMin..warnMax:
sev = Severity.Warning
if not conf.hasWarn(msg): return
writeContext(conf, unknownLineInfo)
title = WarningTitle
color = WarningColor
kind = WarningsToStr[ord(msg) - ord(warnMin)]
inc(conf.warnCounter)
of hintMin..hintMax:
sev = Severity.Hint
if not conf.hasHint(msg): return
title = HintTitle
color = HintColor
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
inc(conf.hintCounter)
let s = msgKindToString(msg) % args
if conf.structuredErrorHook != nil:
conf.structuredErrorHook(conf, unknownLineInfo,
s & (if kind.len > 0: KindFormat % kind else: ""), sev)
if not ignoreMsgBecauseOfIdeTools(conf, msg):
if kind.len > 0:
styledMsgWriteln(color, title, resetStyle, s,
KindColor, `%`(KindFormat, kind))
else:
styledMsgWriteln(color, title, resetStyle, s)
handleError(conf, msg, doAbort, s)
proc rawMessage*(conf: ConfigRef; msg: TMsgKind, arg: string) =
rawMessage(conf, msg, [arg])
proc resetAttributes*(conf: ConfigRef) =
if {optUseColors, optStdout} * conf.globalOptions == {optUseColors}:
terminal.resetAttributes(stderr)
proc addSourceLine(conf: ConfigRef; fileIdx: FileIndex, line: string) =
conf.m.fileInfos[fileIdx.int32].lines.add line
proc sourceLine*(conf: ConfigRef; i: TLineInfo): string =
if i.fileIndex.int32 < 0: return ""
if conf.m.fileInfos[i.fileIndex.int32].lines.len == 0:
proc numLines*(conf: ConfigRef, fileIdx: FileIndex): int =
## xxx there's an off by 1 error that should be fixed; if a file ends with "foo" or "foo\n"
## it will return same number of lines (ie, a trailing empty line is discounted)
result = conf.m.fileInfos[fileIdx.int32].lines.len
if result == 0:
try:
for line in lines(toFullPathConsiderDirty(conf, i)):
addSourceLine conf, i.fileIndex, line.string
for line in lines(toFullPathConsiderDirty(conf, fileIdx).string):
addSourceLine conf, fileIdx, line.string
except IOError:
discard
assert i.fileIndex.int32 < conf.m.fileInfos.len
result = conf.m.fileInfos[fileIdx.int32].lines.len
proc sourceLine*(conf: ConfigRef; i: TLineInfo): string =
## 1-based index (matches editor line numbers); 1st line is for i.line = 1
## last valid line is `numLines` inclusive
if i.fileIndex.int32 < 0: return ""
let num = numLines(conf, i.fileIndex)
# can happen if the error points to EOF:
if i.line.int > conf.m.fileInfos[i.fileIndex.int32].lines.len: return ""
if i.line.int > num: return ""
result = conf.m.fileInfos[i.fileIndex.int32].lines[i.line.int-1]
@@ -473,101 +478,127 @@ proc formatMsg*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string): s
of warnMin..warnMax: WarningTitle
of hintMin..hintMax: HintTitle
else: ErrorTitle
result = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
coordToStr(info.col+ColOffset)] &
title &
getMessageStr(msg, arg)
conf.toFileLineCol(info) & " " & title & getMessageStr(msg, arg)
proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
eh: TErrorHandling) =
proc liMessage*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
eh: TErrorHandling, info2: InstantiationInfo, isRaw = false) {.noinline.} =
var
title: string
color: ForegroundColor
kind: string
ignoreMsg = false
sev: Severity
let kind = if msg in warnMin..hintMax and msg != hintUserRaw: $msg else: "" # xxx not sure why hintUserRaw is special
case msg
of errMin..errMax:
sev = Severity.Error
writeContext(conf, info)
title = ErrorTitle
color = ErrorColor
# we try to filter error messages so that not two error message
# in the same file and line are produced:
#ignoreMsg = lastError == info and eh != doAbort
conf.m.lastError = info
when false:
# we try to filter error messages so that not two error message
# in the same file and line are produced:
# xxx `lastError` is only used in this disabled code; but could be useful to revive
ignoreMsg = conf.m.lastError == info and info != unknownLineInfo and eh != doAbort
if info != unknownLineInfo: conf.m.lastError = info
of warnMin..warnMax:
sev = Severity.Warning
ignoreMsg = not conf.hasWarn(msg)
if msg in conf.warningAsErrors:
ignoreMsg = false
title = ErrorTitle
else:
title = WarningTitle
if not ignoreMsg: writeContext(conf, info)
title = WarningTitle
color = WarningColor
kind = WarningsToStr[ord(msg) - ord(warnMin)]
inc(conf.warnCounter)
of hintMin..hintMax:
sev = Severity.Hint
ignoreMsg = not conf.hasHint(msg)
title = HintTitle
color = HintColor
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
inc(conf.hintCounter)
let x = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
coordToStr(info.col+ColOffset)]
let s = getMessageStr(msg, arg)
let s = if isRaw: arg else: getMessageStr(msg, arg)
if not ignoreMsg:
let loc = if info != unknownLineInfo: conf.toFileLineCol(info) & " " else: ""
var kindmsg = if kind.len > 0: KindFormat % kind else: ""
if conf.structuredErrorHook != nil:
conf.structuredErrorHook(conf, info, s & (if kind.len > 0: KindFormat % kind else: ""), sev)
conf.structuredErrorHook(conf, info, s & kindmsg, sev)
if not ignoreMsgBecauseOfIdeTools(conf, msg):
if kind.len > 0:
styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s,
KindColor, `%`(KindFormat, kind))
if msg == hintProcessing:
msgWrite(conf, ".")
else:
styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s)
if conf.hasHint(hintSource):
conf.writeSurroundingSrc(info)
styledMsgWriteln(styleBright, loc, resetStyle, color, title, resetStyle, s, KindColor, kindmsg)
if conf.hasHint(hintSource) and info != unknownLineInfo:
conf.writeSurroundingSrc(info)
if hintMsgOrigin in conf.mainPackageNotes:
styledMsgWriteln(styleBright, toFileLineCol(info2), resetStyle,
" compiler msg initiated here", KindColor,
KindFormat % $hintMsgOrigin,
resetStyle)
handleError(conf, msg, eh, s)
proc fatal*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
# this fixes bug #7080 so that it is at least obvious 'fatal'
# was executed.
template rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
let arg = msgKindToString(msg) % args
liMessage(conf, unknownLineInfo, msg, arg, eh = doAbort, instLoc(), isRaw = true)
template rawMessage*(conf: ConfigRef; msg: TMsgKind, arg: string) =
liMessage(conf, unknownLineInfo, msg, arg, eh = doAbort, instLoc())
template fatal*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
# this fixes bug #7080 so that it is at least obvious 'fatal' was executed.
conf.m.errorOutputs = {eStdOut, eStdErr}
liMessage(conf, info, msg, arg, doAbort)
liMessage(conf, info, msg, arg, doAbort, instLoc())
proc globalError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(conf, info, msg, arg, doRaise)
template globalAssert*(conf: ConfigRef; cond: untyped, info: TLineInfo = unknownLineInfo, arg = "") =
## avoids boilerplate
if not cond:
var arg2 = "'$1' failed" % [astToStr(cond)]
if arg.len > 0: arg2.add "; " & astToStr(arg) & ": " & arg
liMessage(conf, info, errGenerated, arg2, doRaise, instLoc())
proc globalError*(conf: ConfigRef; info: TLineInfo, arg: string) =
liMessage(conf, info, errGenerated, arg, doRaise)
template globalError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
## `local` means compilation keeps going until errorMax is reached (via `doNothing`),
## `global` means it stops.
liMessage(conf, info, msg, arg, doRaise, instLoc())
proc localError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(conf, info, msg, arg, doNothing)
template globalError*(conf: ConfigRef; info: TLineInfo, arg: string) =
liMessage(conf, info, errGenerated, arg, doRaise, instLoc())
proc localError*(conf: ConfigRef; info: TLineInfo, arg: string) =
liMessage(conf, info, errGenerated, arg, doNothing)
template localError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(conf, info, msg, arg, doNothing, instLoc())
proc localError*(conf: ConfigRef; info: TLineInfo, format: string, params: openArray[string]) =
localError(conf, info, format % params)
template localError*(conf: ConfigRef; info: TLineInfo, arg: string) =
liMessage(conf, info, errGenerated, arg, doNothing, instLoc())
proc message*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(conf, info, msg, arg, doNothing)
template localError*(conf: ConfigRef; info: TLineInfo, format: string, params: openArray[string]) =
liMessage(conf, info, errGenerated, format % params, doNothing, instLoc())
proc internalError*(conf: ConfigRef; info: TLineInfo, errMsg: string) =
template message*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(conf, info, msg, arg, doNothing, instLoc())
proc internalErrorImpl(conf: ConfigRef; info: TLineInfo, errMsg: string, info2: InstantiationInfo) =
if conf.cmd == cmdIdeTools and conf.structuredErrorHook.isNil: return
writeContext(conf, info)
liMessage(conf, info, errInternal, errMsg, doAbort)
liMessage(conf, info, errInternal, errMsg, doAbort, info2)
proc internalError*(conf: ConfigRef; errMsg: string) =
if conf.cmd == cmdIdeTools and conf.structuredErrorHook.isNil: return
writeContext(conf, unknownLineInfo)
rawMessage(conf, errInternal, errMsg)
template internalError*(conf: ConfigRef; info: TLineInfo, errMsg: string) =
internalErrorImpl(conf, info, errMsg, instLoc())
template assertNotNil*(conf: ConfigRef; e): untyped =
if e == nil: internalError(conf, $instantiationInfo())
e
template internalError*(conf: ConfigRef; errMsg: string) =
internalErrorImpl(conf, unknownLineInfo, errMsg, instLoc())
template internalAssert*(conf: ConfigRef, e: bool) =
if not e: internalError(conf, $instantiationInfo())
# xxx merge with `globalAssert`
if not e:
const info2 = instLoc()
let arg = info2.toFileLineCol
internalErrorImpl(conf, unknownLineInfo, arg, info2)
template lintReport*(conf: ConfigRef; info: TLineInfo, beau, got: string) =
let m = "'$2' should be: '$1'" % [beau, got]
let msg = if optStyleError in conf.globalOptions: errGenerated else: hintName
liMessage(conf, info, msg, m, doNothing, instLoc())
proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope =
if i.fileIndex.int32 < 0:
@@ -577,25 +608,9 @@ proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope =
else:
result = conf.m.fileInfos[i.fileIndex.int32].quotedName
proc listWarnings*(conf: ConfigRef) =
msgWriteln(conf, "Warnings:")
for warn in warnMin..warnMax:
msgWriteln(conf, " [$1] $2" % [
if warn in conf.notes: "x" else: " ",
lineinfos.WarningsToStr[ord(warn) - ord(warnMin)]
])
template listMsg(title, r) =
msgWriteln(conf, title)
for a in r: msgWriteln(conf, " [$1] $2" % [if a in conf.notes: "x" else: " ", $a])
proc listHints*(conf: ConfigRef) =
msgWriteln(conf, "Hints:")
for hint in hintMin..hintMax:
msgWriteln(conf, " [$1] $2" % [
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)
proc listWarnings*(conf: ConfigRef) = listMsg("Warnings:", warnMin..warnMax)
proc listHints*(conf: ConfigRef) = listMsg("Hints:", hintMin..hintMax)

View File

@@ -22,3 +22,7 @@ define:useStdoutAsStdmsg
#define:useNodeIds
#gc:markAndSweep
@if nimHasWarningObservableStores:
warning[ObservableStores]: off
@end

View File

@@ -22,9 +22,10 @@ import
commands, options, msgs,
extccomp, strutils, os, main, parseopt,
idents, lineinfos, cmdlinehelper,
pathutils
pathutils, modulegraphs
include nodejs
from browsers import openDefaultBrowser
from nodejs import findNodeJs
when hasTinyCBackend:
import tccgen
@@ -33,20 +34,6 @@ when defined(profiler) or defined(memProfiler):
{.hint: "Profiling support is turned on!".}
import nimprof
proc prependCurDir(f: AbsoluteFile): AbsoluteFile =
when defined(unix):
if os.isAbsolute(f.string): result = f
else: result = AbsoluteFile("./" & f.string)
else:
result = f
proc addCmdPrefix*(result: var string, kind: CmdLineKind) =
# consider moving this to std/parseopt
case kind
of cmdLongOption: result.add "--"
of cmdShortOption: result.add "-"
of cmdArgument, cmdEnd: discard
proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
var p = parseopt.initOptParser(cmd)
var argsCount = 0
@@ -66,7 +53,7 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
config.commandLine.add ':'
config.commandLine.add p.val.quoteShell
if p.key == " ":
if p.key == "": # `-` was passed to indicate main project is stdin
p.key = "-"
if processArgument(pass, p, argsCount, config): break
else:
@@ -77,14 +64,13 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
if processArgument(pass, p, argsCount, config): break
if pass == passCmd2:
if {optRun, optWasNimscript} * config.globalOptions == {} and
config.arguments.len > 0 and config.command.normalize notin ["run", "e"]:
config.arguments.len > 0 and config.command.normalize notin ["run", "e", "r"]:
rawMessage(config, errGenerated, errArgsNeedRunOption)
proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
let self = NimProg(
supportsStdinFile: true,
processCmdLine: processCmdLine,
mainCommand: mainCommand
processCmdLine: processCmdLine
)
self.initDefinesProg(conf, "nim_compiler")
if paramCount() == 0:
@@ -92,7 +78,9 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
return
self.processCmdLineAndProjectPath(conf)
if not self.loadConfigsAndRunMainCommand(cache, conf): return
var graph = newModuleGraph(cache, conf)
if not self.loadConfigsAndRunMainCommand(cache, conf, graph): return
mainCommand(graph)
if conf.hasHint(hintGCStats): echo(GC_getStatistics())
#echo(GC_getStatistics())
if conf.errorCounter != 0: return
@@ -100,11 +88,23 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
if conf.cmd == cmdRun:
tccgen.run(conf, conf.arguments)
if optRun in conf.globalOptions:
var ex = quoteShell conf.absOutFile
if conf.cmd == cmdCompileToJS:
execExternalProgram(conf, findNodeJs() & " " & ex & ' ' & conf.arguments)
let output = conf.absOutFile
case conf.cmd
of cmdCompileToBackend:
var cmdPrefix = ""
case conf.backend
of backendC, backendCpp, backendObjc: discard
of backendJs: cmdPrefix = findNodeJs() & " "
else: doAssert false, $conf.backend
execExternalProgram(conf, cmdPrefix & output.quoteShell & ' ' & conf.arguments)
of cmdDoc, cmdRst2html:
if conf.arguments.len > 0:
# reserved for future use
rawMessage(conf, errGenerated, "'$1 cannot handle arguments" % [$conf.cmd])
openDefaultBrowser($output)
else:
execExternalProgram(conf, ex & ' ' & conf.arguments)
# support as needed
rawMessage(conf, errGenerated, "'$1 cannot handle --run" % [$conf.cmd])
when declared(GC_setMaxPause):
GC_setMaxPause 2_000

View File

@@ -134,30 +134,3 @@ proc nimblePath*(conf: ConfigRef; path: AbsoluteDir, info: TLineInfo) =
if i != -1:
conf.nimblePaths.delete(i)
conf.nimblePaths.insert(path, 0)
when isMainModule:
proc v(s: string): Version = s.newVersion
# #head is special in the sense that it's assumed to always be newest.
doAssert v"1.0" < v"#head"
doAssert v"1.0" < v"1.1"
doAssert v"1.0.1" < v"1.1"
doAssert v"1" < v"1.1"
doAssert v"#aaaqwe" < v"1.1" # We cannot assume that a branch is newer.
doAssert v"#a111" < v"#head"
let conf = newConfigRef()
var rr = newStringTable()
addPackage conf, rr, "irc-#a111", unknownLineInfo
addPackage conf, rr, "irc-#head", unknownLineInfo
addPackage conf, rr, "irc-0.1.0", unknownLineInfo
#addPackage conf, rr, "irc", unknownLineInfo
#addPackage conf, rr, "another", unknownLineInfo
addPackage conf, rr, "another-0.1", unknownLineInfo
addPackage conf, rr, "ab-0.1.3", unknownLineInfo
addPackage conf, rr, "ab-0.1", unknownLineInfo
addPackage conf, rr, "justone-1.0", unknownLineInfo
doAssert toSeq(rr.chosen) ==
@["irc-#head", "another-0.1", "ab-0.1.3", "justone-1.0"]

View File

@@ -16,13 +16,13 @@ import
# ---------------- configuration file parser -----------------------------
# we use Nim's scanner here to save space and work
proc ppGetTok(L: var TLexer, tok: var TToken) =
proc ppGetTok(L: var Lexer, tok: var Token) =
# simple filter
rawGetTok(L, tok)
while tok.tokType in {tkComment}: rawGetTok(L, tok)
proc parseExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool
proc parseAtom(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
proc parseExpr(L: var Lexer, tok: var Token; config: ConfigRef): bool
proc parseAtom(L: var Lexer, tok: var Token; config: ConfigRef): bool =
if tok.tokType == tkParLe:
ppGetTok(L, tok)
result = parseExpr(L, tok, config)
@@ -35,21 +35,21 @@ proc parseAtom(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
result = isDefined(config, tok.ident.s)
ppGetTok(L, tok)
proc parseAndExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
proc parseAndExpr(L: var Lexer, tok: var Token; config: ConfigRef): bool =
result = parseAtom(L, tok, config)
while tok.tokType == tkAnd:
ppGetTok(L, tok) # skip "and"
var b = parseAtom(L, tok, config)
result = result and b
proc parseExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
proc parseExpr(L: var Lexer, tok: var Token; config: ConfigRef): bool =
result = parseAndExpr(L, tok, config)
while tok.tokType == tkOr:
ppGetTok(L, tok) # skip "or"
var b = parseAndExpr(L, tok, config)
result = result or b
proc evalppIf(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
proc evalppIf(L: var Lexer, tok: var Token; config: ConfigRef): bool =
ppGetTok(L, tok) # skip 'if' or 'elif'
result = parseExpr(L, tok, config)
if tok.tokType == tkColon: ppGetTok(L, tok)
@@ -57,7 +57,7 @@ proc evalppIf(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
#var condStack: seq[bool] = @[]
proc doEnd(L: var TLexer, tok: var TToken; condStack: var seq[bool]) =
proc doEnd(L: var Lexer, tok: var Token; condStack: var seq[bool]) =
if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if")
ppGetTok(L, tok) # skip 'end'
setLen(condStack, high(condStack))
@@ -66,21 +66,21 @@ type
TJumpDest = enum
jdEndif, jdElseEndif
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest; config: ConfigRef;
proc jumpToDirective(L: var Lexer, tok: var Token, dest: TJumpDest; config: ConfigRef;
condStack: var seq[bool])
proc doElse(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) =
proc doElse(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) =
if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if")
ppGetTok(L, tok)
if tok.tokType == tkColon: ppGetTok(L, tok)
if condStack[high(condStack)]: jumpToDirective(L, tok, jdEndif, config, condStack)
proc doElif(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) =
proc doElif(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) =
if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if")
var res = evalppIf(L, tok, config)
if condStack[high(condStack)] or not res: jumpToDirective(L, tok, jdElseEndif, config, condStack)
else: condStack[high(condStack)] = true
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest; config: ConfigRef;
proc jumpToDirective(L: var Lexer, tok: var Token, dest: TJumpDest; config: ConfigRef;
condStack: var seq[bool]) =
var nestedIfs = 0
while true:
@@ -110,7 +110,7 @@ proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest; config: Co
else:
ppGetTok(L, tok)
proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) =
proc parseDirective(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) =
ppGetTok(L, tok) # skip @
case whichKeyword(tok.ident)
of wIf:
@@ -149,16 +149,16 @@ proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef; condStack
else:
lexMessage(L, errGenerated, "invalid directive: '$1'" % $tok)
proc confTok(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) =
proc confTok(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) =
ppGetTok(L, tok)
while tok.ident != nil and tok.ident.s == "@":
parseDirective(L, tok, config, condStack) # else: give the token to the parser
proc checkSymbol(L: TLexer, tok: TToken) =
proc checkSymbol(L: Lexer, tok: Token) =
if tok.tokType notin {tkSymbol..tkInt64Lit, tkStrLit..tkTripleStrLit}:
lexMessage(L, errGenerated, "expected identifier, but got: " & $tok)
proc parseAssignment(L: var TLexer, tok: var TToken;
proc parseAssignment(L: var Lexer, tok: var Token;
config: ConfigRef; condStack: var seq[bool]) =
if tok.ident != nil:
if tok.ident.s == "-" or tok.ident.s == "--":
@@ -211,8 +211,8 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
proc readConfigFile*(filename: AbsoluteFile; cache: IdentCache;
config: ConfigRef): bool =
var
L: TLexer
tok: TToken
L: Lexer
tok: Token
stream: PLLStream
stream = llStreamOpen(filename, fmRead)
if stream != nil:

View File

@@ -10,9 +10,9 @@
## exposes the Nim VM to clients.
import
ast, astalgo, modules, passes, condsyms,
options, sem, semdata, llstream, vm, vmdef,
modulegraphs, idents, os, pathutils, passaux,
scriptconfig
options, sem, semdata, llstream, lineinfos, vm,
vmdef, modulegraphs, idents, os, pathutils,
passaux, scriptconfig
type
Interpreter* = ref object ## Use Nim as an interpreter with this object
@@ -81,6 +81,9 @@ proc findNimStdLib*(): string =
## Returns "" on failure.
try:
let nimexe = os.findExe("nim")
# this can't work with choosenim shims, refs https://github.com/dom96/choosenim/issues/189
# it'd need `nim dump --dump.format:json . | jq -r .libpath`
# which we should simplify as `nim dump --key:libpath`
if nimexe.len == 0: return ""
result = nimexe.splitPath()[0] /../ "lib"
if not fileExists(result / "system.nim"):
@@ -93,20 +96,22 @@ proc findNimStdLib*(): string =
proc findNimStdLibCompileTime*(): string =
## Same as ``findNimStdLib`` but uses source files used at compile time,
## and asserts on error.
const sourcePath = currentSourcePath()
result = sourcePath.parentDir.parentDir / "lib"
const exe = getCurrentCompilerExe()
result = exe.splitFile.dir.parentDir / "lib"
doAssert fileExists(result / "system.nim"), "result:" & result
proc createInterpreter*(scriptName: string;
searchPaths: openArray[string];
flags: TSandboxFlags = {}): Interpreter =
flags: TSandboxFlags = {},
defines = @[("nimscript", "true")],
registerOps = true): Interpreter =
var conf = newConfigRef()
var cache = newIdentCache()
var graph = newModuleGraph(cache, conf)
connectCallbacks(graph)
initDefines(conf.symbols)
defineSymbol(conf.symbols, "nimscript")
defineSymbol(conf.symbols, "nimconfig")
for define in defines:
defineSymbol(conf.symbols, define[0], define[1])
registerPass(graph, semPass)
registerPass(graph, evalPass)
@@ -119,6 +124,8 @@ proc createInterpreter*(scriptName: string;
var vm = newCtx(m, cache, graph)
vm.mode = emRepl
vm.features = flags
if registerOps:
vm.registerAdditionalOps() # Required to register parts of stdlib modules
graph.vm = vm
graph.compileSystemModule()
result = Interpreter(mainModule: m, graph: graph, scriptName: scriptName)
@@ -127,9 +134,15 @@ proc destroyInterpreter*(i: Interpreter) =
## destructor.
discard "currently nothing to do."
proc registerErrorHook*(i: Interpreter, hook:
proc (config: ConfigRef; info: TLineInfo; msg: string;
severity: Severity) {.gcsafe.}) =
i.graph.config.structuredErrorHook = hook
proc runRepl*(r: TLLRepl;
searchPaths: openArray[string];
supportNimscript: bool) =
## deadcode but please don't remove... might be revived
var conf = newConfigRef()
var cache = newIdentCache()
var graph = newModuleGraph(cache, conf)
@@ -139,7 +152,7 @@ proc runRepl*(r: TLLRepl;
if conf.libpath.isEmpty: conf.libpath = AbsoluteDir p
conf.cmd = cmdInteractive
conf.errorMax = high(int)
conf.setErrorMaxHighMaybe
initDefines(conf.symbols)
defineSymbol(conf.symbols, "nimscript")
if supportNimscript: defineSymbol(conf.symbols, "nimconfig")

View File

@@ -39,7 +39,9 @@ const
type
TBaseLexer* = object of RootObj
bufpos*: int
buf*: string
buf*: cstring
bufStorage: string
bufLen: int
stream*: PLLStream # we read from this stream
lineNumber*: int # the current line number
# private data:
@@ -75,8 +77,8 @@ proc fillBuffer(L: var TBaseLexer) =
oldBufLen: int
# we know here that pos == L.sentinel, but not if this proc
# is called the first time by initBaseLexer()
assert(L.sentinel < L.buf.len)
toCopy = L.buf.len - L.sentinel - 1
assert(L.sentinel < L.bufLen)
toCopy = L.bufLen - L.sentinel - 1
assert(toCopy >= 0)
if toCopy > 0:
moveMem(addr L.buf[0], addr L.buf[L.sentinel + 1], toCopy)
@@ -90,7 +92,7 @@ proc fillBuffer(L: var TBaseLexer) =
# compute sentinel:
dec(s) # BUGFIX (valgrind)
while true:
assert(s < L.buf.len)
assert(s < L.bufLen)
while (s >= 0) and not (L.buf[s] in NewLines): dec(s)
if s >= 0:
# we found an appropriate character for a sentinel:
@@ -99,16 +101,18 @@ proc fillBuffer(L: var TBaseLexer) =
else:
# rather than to give up here because the line is too long,
# double the buffer's size and try again:
oldBufLen = L.buf.len
L.buf.setLen(L.buf.len * 2)
assert(L.buf.len - oldBufLen == oldBufLen)
oldBufLen = L.bufLen
L.bufLen = L.bufLen * 2
L.bufStorage.setLen(L.bufLen)
L.buf = L.bufStorage
assert(L.bufLen - oldBufLen == oldBufLen)
charsRead = llStreamRead(L.stream, addr(L.buf[oldBufLen]),
oldBufLen)
if charsRead < oldBufLen:
L.buf[oldBufLen + charsRead] = EndOfFile
L.sentinel = oldBufLen + charsRead
break
s = L.buf.len - 1
s = L.bufLen - 1
proc fillBaseLexer(L: var TBaseLexer, pos: int): int =
assert(pos <= L.sentinel)
@@ -142,7 +146,9 @@ proc openBaseLexer(L: var TBaseLexer, inputstream: PLLStream, bufLen = 8192) =
assert(bufLen > 0)
L.bufpos = 0
L.offsetBase = 0
L.buf = newString(bufLen)
L.bufStorage = newString(bufLen)
L.buf = L.bufStorage
L.bufLen = bufLen
L.sentinel = bufLen - 1
L.lineStart = 0
L.lineNumber = 1 # lines start at 1
@@ -156,9 +162,9 @@ proc getColNumber(L: TBaseLexer, pos: int): int =
proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
result = ""
var i = L.lineStart
while not (L.buf[i] in {CR, LF, EndOfFile}):
result.add(L.buf[i])
inc(i)
result.add("\n")
while L.buf[i] notin {CR, LF, EndOfFile}:
result.add L.buf[i]
inc i
result.add "\n"
if marker:
result.add(spaces(getColNumber(L, L.bufpos)) & '^' & "\n")
result.add spaces(getColNumber(L, L.bufpos)) & '^' & "\n"

47
compiler/nimpaths.nim Normal file
View File

@@ -0,0 +1,47 @@
##[
Represents absolute paths, but using a symbolic variables (eg $nimr) which can be
resolved at runtime; this avoids hardcoding at compile time absolute paths so
that the project root can be relocated.
xxx consider some refactoring with $nim/testament/lib/stdtest/specialpaths.nim;
specialpaths is simpler because it doesn't need variables to be relocatable at
runtime (eg for use in testament)
interpolation variables:
$nimr: such that `$nimr/lib/system.nim` exists (avoids confusion with $nim binary)
in compiler, it's obtainable via getPrefixDir(); for other tools (eg koch),
this could be getCurrentDir() or getAppFilename().parentDir.parentDir,
depending on use case
Unstable API
]##
import os, strutils
const
docCss* = "$nimr/doc/nimdoc.css"
docHackNim* = "$nimr/tools/dochack/dochack.nim"
docHackJs* = docHackNim.changeFileExt("js")
docHackJsFname* = docHackJs.lastPathPart
theindexFname* = "theindex.html"
nimdocOutCss* = "nimdoc.out.css"
# `out` to make it easier to use with gitignore in user's repos
htmldocsDirname* = "htmldocs"
dotdotMangle* = "_._" ## refs #13223
# if this changes, make sure it's consistent with `esc` and `escapeLink`
# lots of other obvious options won't work, see #14454; `_` could work too
proc interp*(path: string, nimr: string): string =
result = path % ["nimr", nimr]
doAssert '$' notin result, $(path, nimr, result) # avoids un-interpolated variables in output
proc getDocHacksJs*(nimr: string, nim = getCurrentCompilerExe(), forceRebuild = false): string =
## return absolute path to dochack.js, rebuilding if it doesn't exist or if
## `forceRebuild`.
let docHackJs2 = docHackJs.interp(nimr = nimr)
if forceRebuild or not docHackJs2.fileExists:
let cmd = "$nim js -d:release $file" % ["nim", nim.quoteShell, "file", docHackNim.interp(nimr = nimr).quoteShell]
echo "getDocHacksJs: cmd: " & cmd
doAssert execShellCmd(cmd) == 0, $(cmd)
doAssert docHackJs2.fileExists
result = docHackJs2

View File

@@ -58,18 +58,18 @@ proc someInSet*(s: PNode, a, b: PNode): bool =
return true
result = false
proc toBitSet*(conf: ConfigRef; s: PNode, b: var TBitSet) =
proc toBitSet*(conf: ConfigRef; s: PNode): TBitSet =
var first, j: Int128
first = firstOrd(conf, s.typ[0])
bitSetInit(b, int(getSize(conf, s.typ)))
bitSetInit(result, int(getSize(conf, s.typ)))
for i in 0..<s.len:
if s[i].kind == nkRange:
j = getOrdValue(s[i][0], first)
while j <= getOrdValue(s[i][1], first):
bitSetIncl(b, toInt64(j - first))
bitSetIncl(result, toInt64(j - first))
inc(j)
else:
bitSetIncl(b, toInt64(getOrdValue(s[i]) - first))
bitSetIncl(result, toInt64(getOrdValue(s[i]) - first))
proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): PNode =
var
@@ -106,9 +106,8 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
inc(e)
template nodeSetOp(a, b: PNode, op: untyped) {.dirty.} =
var x, y: TBitSet
toBitSet(conf, a, x)
toBitSet(conf, b, y)
var x = toBitSet(conf, a)
let y = toBitSet(conf, b)
op(x, y)
result = toTreeSet(conf, x, a.typ, a.info)
@@ -118,31 +117,26 @@ proc intersectSets*(conf: ConfigRef; a, b: PNode): PNode = nodeSetOp(a, b, bitSe
proc symdiffSets*(conf: ConfigRef; a, b: PNode): PNode = nodeSetOp(a, b, bitSetSymDiff)
proc containsSets*(conf: ConfigRef; a, b: PNode): bool =
var x, y: TBitSet
toBitSet(conf, a, x)
toBitSet(conf, b, y)
let x = toBitSet(conf, a)
let y = toBitSet(conf, b)
result = bitSetContains(x, y)
proc equalSets*(conf: ConfigRef; a, b: PNode): bool =
var x, y: TBitSet
toBitSet(conf, a, x)
toBitSet(conf, b, y)
let x = toBitSet(conf, a)
let y = toBitSet(conf, b)
result = bitSetEquals(x, y)
proc complement*(conf: ConfigRef; a: PNode): PNode =
var x: TBitSet
toBitSet(conf, a, x)
var x = toBitSet(conf, a)
for i in 0..high(x): x[i] = not x[i]
result = toTreeSet(conf, x, a.typ, a.info)
proc deduplicate*(conf: ConfigRef; a: PNode): PNode =
var x: TBitSet
toBitSet(conf, a, x)
let x = toBitSet(conf, a)
result = toTreeSet(conf, x, a.typ, a.info)
proc cardSet*(conf: ConfigRef; a: PNode): BiggestInt =
var x: TBitSet
toBitSet(conf, a, x)
let x = toBitSet(conf, a)
result = bitSetCard(x)
proc setHasRange*(s: PNode): bool =

287
compiler/optimizer.nim Normal file
View File

@@ -0,0 +1,287 @@
#
#
# The Nim Compiler
# (c) Copyright 2020 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Optimizer:
## - elide 'wasMoved(x); destroy(x)' pairs
## - recognize "all paths lead to 'wasMoved(x)'"
import
ast, renderer, idents, intsets
from trees import exprStructuralEquivalent
const
nfMarkForDeletion = nfNone # faster than a lookup table
type
BasicBlock = object
wasMovedLocs: seq[PNode]
kind: TNodeKind
hasReturn, hasBreak: bool
label: PSym # can be nil
parent: ptr BasicBlock
Con = object
somethingTodo: bool
inFinally: int
proc nestedBlock(parent: var BasicBlock; kind: TNodeKind): BasicBlock =
BasicBlock(wasMovedLocs: @[], kind: kind, hasReturn: false, hasBreak: false,
label: nil, parent: addr(parent))
proc breakStmt(b: var BasicBlock; n: PNode) =
var it = addr(b)
while it != nil:
it.wasMovedLocs.setLen 0
it.hasBreak = true
if n.kind == nkSym:
if it.label == n.sym: break
else:
# unnamed break leaves the block is nkWhileStmt or the like:
if it.kind in {nkWhileStmt, nkBlockStmt, nkBlockExpr}: break
it = it.parent
proc returnStmt(b: var BasicBlock) =
b.hasReturn = true
var it = addr(b)
while it != nil:
it.wasMovedLocs.setLen 0
it = it.parent
proc mergeBasicBlockInfo(parent: var BasicBlock; this: BasicBlock) {.inline.} =
if this.hasReturn:
parent.wasMovedLocs.setLen 0
parent.hasReturn = true
proc wasMovedTarget(matches: var IntSet; branch: seq[PNode]; moveTarget: PNode): bool =
result = false
for i in 0..<branch.len:
if exprStructuralEquivalent(branch[i][1].skipAddr, moveTarget,
strictSymEquality = true):
result = true
matches.incl i
proc intersect(summary: var seq[PNode]; branch: seq[PNode]) =
# keep all 'wasMoved(x)' calls in summary that are also in 'branch':
var i = 0
var matches = initIntSet()
while i < summary.len:
if wasMovedTarget(matches, branch, summary[i][1].skipAddr):
inc i
else:
summary.del i
for m in matches:
summary.add branch[m]
proc invalidateWasMoved(c: var BasicBlock; x: PNode) =
var i = 0
while i < c.wasMovedLocs.len:
if exprStructuralEquivalent(c.wasMovedLocs[i][1].skipAddr, x,
strictSymEquality = true):
c.wasMovedLocs.del i
else:
inc i
proc wasMovedDestroyPair(c: var Con; b: var BasicBlock; d: PNode) =
var i = 0
while i < b.wasMovedLocs.len:
if exprStructuralEquivalent(b.wasMovedLocs[i][1].skipAddr, d[1].skipAddr,
strictSymEquality = true):
b.wasMovedLocs[i].flags.incl nfMarkForDeletion
c.somethingTodo = true
d.flags.incl nfMarkForDeletion
b.wasMovedLocs.del i
else:
inc i
proc analyse(c: var Con; b: var BasicBlock; n: PNode) =
case n.kind
of nkCallKinds:
var special = false
var reverse = false
if n[0].kind == nkSym:
let s = n[0].sym
if s.magic == mWasMoved:
b.wasMovedLocs.add n
special = true
elif s.name.s == "=destroy":
if c.inFinally > 0 and (b.hasReturn or b.hasBreak):
discard "cannot optimize away the destructor"
else:
c.wasMovedDestroyPair b, n
special = true
elif s.name.s == "=sink":
reverse = true
if not special:
if not reverse:
for i in 0 ..< n.len:
analyse(c, b, n[i])
else:
#[ Test tmatrix.test3:
Prevent this from being elided. We should probably
find a better solution...
`=sink`(b, - (
let blitTmp = b;
wasMoved(b);
blitTmp + a)
`=destroy`(b)
]#
for i in countdown(n.len-1, 0):
analyse(c, b, n[i])
if canRaise(n[0]): returnStmt(b)
of nkSym:
# any usage of the location before destruction implies we
# cannot elide the 'wasMoved(x)':
b.invalidateWasMoved n
of nkNone..pred(nkSym), succ(nkSym)..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef,
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
discard "do not follow the construct"
of nkAsgn, nkFastAsgn:
# reverse order, see remark for `=sink`:
analyse(c, b, n[1])
analyse(c, b, n[0])
of nkIfStmt, nkIfExpr:
let isExhaustive = n[^1].kind in {nkElse, nkElseExpr}
var wasMovedSet: seq[PNode] = @[]
for i in 0 ..< n.len:
var branch = nestedBlock(b, n[i].kind)
analyse(c, branch, n[i])
mergeBasicBlockInfo(b, branch)
if isExhaustive:
if i == 0:
wasMovedSet = move(branch.wasMovedLocs)
else:
wasMovedSet.intersect(branch.wasMovedLocs)
for i in 0..<wasMovedSet.len:
b.wasMovedLocs.add wasMovedSet[i]
of nkCaseStmt:
let isExhaustive = skipTypes(n[0].typ,
abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString} or
n[^1].kind == nkElse
analyse(c, b, n[0])
var wasMovedSet: seq[PNode] = @[]
for i in 1 ..< n.len:
var branch = nestedBlock(b, n[i].kind)
analyse(c, branch, n[i])
mergeBasicBlockInfo(b, branch)
if isExhaustive:
if i == 1:
wasMovedSet = move(branch.wasMovedLocs)
else:
wasMovedSet.intersect(branch.wasMovedLocs)
for i in 0..<wasMovedSet.len:
b.wasMovedLocs.add wasMovedSet[i]
of nkTryStmt:
for i in 0 ..< n.len:
var tryBody = nestedBlock(b, nkTryStmt)
analyse(c, tryBody, n[i])
mergeBasicBlockInfo(b, tryBody)
of nkWhileStmt:
analyse(c, b, n[0])
var loopBody = nestedBlock(b, nkWhileStmt)
analyse(c, loopBody, n[1])
mergeBasicBlockInfo(b, loopBody)
of nkBlockStmt, nkBlockExpr:
var blockBody = nestedBlock(b, n.kind)
if n[0].kind == nkSym:
blockBody.label = n[0].sym
analyse(c, blockBody, n[1])
mergeBasicBlockInfo(b, blockBody)
of nkBreakStmt:
breakStmt(b, n[0])
of nkReturnStmt, nkRaiseStmt:
for child in n: analyse(c, b, child)
returnStmt(b)
of nkFinally:
inc c.inFinally
for child in n: analyse(c, b, child)
dec c.inFinally
else:
for child in n: analyse(c, b, child)
proc opt(c: Con; n, parent: PNode; parentPos: int) =
template recurse() =
let x = shallowCopy(n)
for i in 0 ..< n.len:
opt(c, n[i], x, i)
parent[parentPos] = x
case n.kind
of nkCallKinds:
if nfMarkForDeletion in n.flags:
parent[parentPos] = newNodeI(nkEmpty, n.info)
else:
recurse()
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef,
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState, nkTypeOfExpr,
nkMixinStmt, nkBindStmt:
parent[parentPos] = n
else:
recurse()
proc optimize*(n: PNode): PNode =
# optimize away simple 'wasMoved(x); destroy(x)' pairs.
#[ Unfortunately this optimization is only really safe when no exceptions
are possible, see for example:
proc main(inp: string; cond: bool) =
if cond:
try:
var s = ["hi", inp & "more"]
for i in 0..4:
use s
consume(s)
wasMoved(s)
finally:
destroy(s)
Now assume 'use' raises, then we shouldn't do the 'wasMoved(s)'
]#
var c: Con
var b: BasicBlock
analyse(c, b, n)
if c.somethingTodo:
result = shallowCopy(n)
for i in 0 ..< n.safeLen:
opt(c, n[i], result, i)
else:
result = n

View File

@@ -9,7 +9,7 @@
import
os, strutils, strtabs, sets, lineinfos, platform,
prefixmatches, pathutils
prefixmatches, pathutils, nimpaths, tables
from terminal import isatty
from times import utc, fromUnix, local, getTime, format, DateTime
@@ -19,13 +19,13 @@ const
useEffectSystem* = true
useWriteTracking* = false
hasFFI* = defined(nimHasLibFFI)
copyrightYear* = "2020"
copyrightYear* = "2021"
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, optRefCheck,
optOverflowCheck, optRefCheck,
optNaNCheck, optInfCheck, optStaticBoundsCheck, optStyleCheck,
optAssert, optLineDir, optWarns, optHints,
optOptimizeSpeed, optOptimizeSize,
@@ -39,10 +39,9 @@ type # please make sure we have under 32 options
# evaluation
optTrMacros, # en/disable pattern matching
optMemTracker,
optLaxStrings,
optNilSeqs,
optOldAst,
optSinkInference # 'sink T' inference
optCursorInference
TOptions* = set[TOption]
@@ -57,6 +56,7 @@ type # please make sure we have under 32 options
optGenScript, # generate a script file to compile the *.c files
optGenMapping, # generate a mapping file
optRun, # run the compiled project
optUseNimcache, # save artifacts (including binary) in $nimcache
optStyleHint, # check that the names adhere to NEP-1
optStyleError, # enforce that the names adhere to NEP-1
optStyleUsages, # only enforce consistent **usages** of the symbol
@@ -78,7 +78,7 @@ type # please make sure we have under 32 options
optIdeTerse # idetools: use terse descriptions
optExcessiveStackTrace # fully qualified module filenames
optShowAllMismatches # show all overloading resolution candidates
optWholeProject # for 'doc2': output any dependency
optWholeProject # for 'doc': output any dependency
optDocInternal # generate documentation for non-exported symbols
optMixedMode # true if some module triggered C++ codegen
optListFullPaths # use full paths in toMsgFilename
@@ -91,12 +91,14 @@ type # please make sure we have under 32 options
# implementation
optOwnedRefs # active if the Nim compiler knows about 'owned'.
optMultiMethods
optNimV019
optBenchmarkVM # Enables cpuTime() in the VM
optProduceAsm # produce assembler code
optPanics # turn panics (sysFatal) into a process termination
optNimV1Emulation # emulate Nim v1.0
optNimV12Emulation # emulate Nim v1.2
optSourcemap
optProfileVM # enable VM profiler
optEnableDeepCopy # ORC specific: enable 'deepcopy' for all types.
TGlobalOptions* = set[TGlobalOption]
@@ -104,12 +106,26 @@ const
harmlessOptions* = {optForceFullMake, optNoLinking, optRun,
optUseColors, optStdout}
type
TBackend* = enum
backendInvalid = "" # for parseEnum
backendC = "c"
backendCpp = "cpp" # was cmdCompileToCpp
backendJs = "js" # was cmdCompileToJS
backendObjc = "objc" # was cmdCompileToOC
# backendNimscript = "nimscript" # this could actually work
# backendLlvm = "llvm" # probably not well supported; was cmdCompileToLLVM
type
TCommands* = enum # Nim's commands
# **keep binary compatible**
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
cmdCompileToJS,
cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
cmdNone,
cmdCompileToC, # deadcode
cmdCompileToCpp, # deadcode
cmdCompileToOC, # deadcode
cmdCompileToJS, # deadcode
cmdCompileToLLVM, # deadcode
cmdInterpret, cmdPretty, cmdDoc,
cmdGenDepend, cmdDump,
cmdCheck, # semantic checking for whole project
cmdParse, # parse a single file (for debugging)
@@ -121,11 +137,11 @@ type
cmdInteractive, # start interactive session
cmdRun, # run the project via TCC backend
cmdJsonScript # compile a .json build file
cmdCompileToBackend, # compile to backend in TBackend
TStringSeq* = seq[string]
TGCMode* = enum # the selected GC
gcUnselected, gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcArc, gcOrc,
gcHooks,
gcRefc, gcV2, gcGo
gcUnselected, gcNone, gcBoehm, gcRegions, gcArc, gcOrc,
gcMarkAndSweep, gcHooks, gcRefc, gcV2, gcGo
# gcRefc and the GCs that follow it use a write barrier,
# as far as usesWriteBarrier() is concerned
@@ -141,13 +157,16 @@ type
destructor,
notnil,
dynamicBindSym,
forLoopMacros,
forLoopMacros, # not experimental anymore; remains here for backwards compatibility
caseStmtMacros,
codeReordering,
compiletimeFFI,
## This requires building nim with `-d:nimHasLibFFI`
## which itself requires `nimble install libffi`, see #10150
## Note: this feature can't be localized with {.push.}
vmopsDanger,
strictFuncs,
views
LegacyFeature* = enum
allowSemcheckedAstModification,
@@ -163,8 +182,8 @@ type
disabledSf, writeOnlySf, readOnlySf, v2Sf
TSystemCC* = enum
ccNone, ccGcc, ccNintendoSwitch, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc,
ccTcc, ccPcc, ccUcc, ccIcl, ccIcc, ccClangCl
ccNone, ccGcc, ccNintendoSwitch, ccLLVM_Gcc, ccCLang, ccBcc, ccVcc,
ccTcc, ccEnv, ccIcl, ccIcc, ccClangCl
ExceptionSystem* = enum
excNone, # no exception system selected yet
@@ -204,15 +223,24 @@ type
version*: int
Suggestions* = seq[Suggest]
ConfigRef* = ref object ## every global configuration
ProfileInfo* = object
time*: float
count*: int
ProfileData* = ref object
data*: TableRef[TLineInfo, ProfileInfo]
ConfigRef* {.acyclic.} = ref object ## every global configuration
## fields marked with '*' are subject to
## the incremental compilation mechanisms
## (+) means "part of the dependency"
backend*: TBackend # set via `nim x` or `nim --backend:x`
target*: Target # (+)
linesCompiled*: int # all lines that have been compiled
options*: TOptions # (+)
globalOptions*: TGlobalOptions # (+)
macrosToExpand*: StringTableRef
arcToExpand*: StringTableRef
m*: MsgConfig
evalTemplateCounter*: int
evalMacroCounter*: int
@@ -239,6 +267,7 @@ type
cmdlineNotes*: TNoteKinds # notes that have been set/unset from cmdline
foreignPackageNotes*: TNoteKinds
notes*: TNoteKinds # notes after resolving all logic(defaults, verbosity)/cmdline/configs
warningAsErrors*: TNoteKinds
mainPackageNotes*: TNoteKinds
mainPackageId*: int
errorCounter*: int
@@ -256,13 +285,16 @@ type
lazyPaths*: seq[AbsoluteDir]
outFile*: RelativeFile
outDir*: AbsoluteDir
jsonBuildFile*: AbsoluteFile
prefixDir*, libpath*, nimcacheDir*: AbsoluteDir
dllOverrides, moduleOverrides*, cfileSpecificOptions*: StringTableRef
projectName*: string # holds a name like 'nim'
projectPath*: AbsoluteDir # holds a path like /home/alice/projects/nim/compiler/
projectFull*: AbsoluteFile # projectPath/projectName
projectIsStdin*: bool # whether we're compiling from stdin
lastMsgWasDot*: bool # the last compiler message was a single '.'
projectMainIdx*: FileIndex # the canonical path id of the main module
projectMainIdx2*: FileIndex # consider merging with projectMainIdx
command*: string # the main command (e.g. cc, check, scan, etc)
commandArgs*: seq[string] # any arguments after the main command
commandLine*: string
@@ -273,6 +305,7 @@ type
docSeeSrcUrl*: string # if empty, no seeSrc will be generated. \
# The string uses the formatting variables `path` and `line`.
docRoot*: string ## see nim --fullhelp for --docRoot
docCmd*: string ## see nim --fullhelp for --docCmd
# the used compiler
cIncludes*: seq[AbsoluteDir] # directories to search for included files
@@ -295,6 +328,15 @@ type
structuredErrorHook*: proc (config: ConfigRef; info: TLineInfo; msg: string;
severity: Severity) {.closure, gcsafe.}
cppCustomNamespace*: string
vmProfileData*: ProfileData
proc assignIfDefault*[T](result: var T, val: T, def = default(T)) =
## if `result` was already assigned to a value (that wasn't `def`), this is a noop.
if result == def: result = val
template setErrorMaxHighMaybe*(conf: ConfigRef) =
## do not stop after first error (but honor --errorMax if provided)
assignIfDefault(conf.errorMax, high(int))
proc setNoteDefaults*(conf: ConfigRef, note: TNoteKind, enabled = true) =
template fun(op) =
@@ -309,7 +351,10 @@ proc setNote*(conf: ConfigRef, note: TNoteKind, enabled = true) =
if enabled: incl(conf.notes, note) else: excl(conf.notes, note)
proc hasHint*(conf: ConfigRef, note: TNoteKind): bool =
optHints in conf.options and note in conf.notes
if optHints notin conf.options: false
elif note in {hintConf}: # could add here other special notes like hintSource
note in conf.mainPackageNotes
else: note in conf.notes
proc hasWarn*(conf: ConfigRef, note: TNoteKind): bool {.inline.} =
optWarns in conf.options and note in conf.notes
@@ -325,14 +370,14 @@ template depConfigFields*(fn) {.dirty.} =
const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel}
const
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck,
optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck,
optStyleCheck}
DefaultOptions* = {optObjCheck, optFieldCheck, optRangeCheck,
optBoundsCheck, optOverflowCheck, optAssert, optWarns, optRefCheck,
optHints, optStackTrace, optLineTrace, # consider adding `optStackTraceMsgs`
optTrMacros, optNilCheck, optStyleCheck, optSinkInference}
optTrMacros, optStyleCheck, optCursorInference}
DefaultGlobalOptions* = {optThreadAnalysis,
optExcessiveStackTrace, optListFullPaths}
@@ -360,6 +405,9 @@ template newPackageCache*(): untyped =
else:
modeCaseSensitive)
proc newProfileData(): ProfileData =
ProfileData(data: newTable[TLineInfo, ProfileInfo]())
proc newConfigRef*(): ConfigRef =
result = ConfigRef(
selectedGC: gcRefc,
@@ -368,6 +416,7 @@ proc newConfigRef*(): ConfigRef =
options: DefaultOptions,
globalOptions: DefaultGlobalOptions,
macrosToExpand: newStringTable(modeStyleInsensitive),
arcToExpand: newStringTable(modeStyleInsensitive),
m: initMsgConfig(),
evalExpr: "",
cppDefines: initHashSet[string](),
@@ -401,7 +450,7 @@ proc newConfigRef*(): ConfigRef =
cIncludes: @[], # directories to search for included files
cLibs: @[], # directories to search for lib files
cLinkedLibs: @[], # libraries to link
backend: backendInvalid,
externalToLink: @[],
linkOptionsCmd: "",
compileOptionsCmd: @[],
@@ -412,6 +461,7 @@ proc newConfigRef*(): ConfigRef =
arguments: "",
suggestMaxResults: 10_000,
maxLoopIterationsVM: 10_000_000,
vmProfileData: newProfileData(),
)
setTargetFromSystem(result.target)
# enable colors by default on terminals
@@ -449,7 +499,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
osQnx, osAtari, osAix,
osHaiku, osVxWorks, osSolaris, osNetbsd,
osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos,
osAndroid, osNintendoSwitch}
osAndroid, osNintendoSwitch, osFreeRTOS}
of "linux":
result = conf.target.targetOS in {osLinux, osAndroid}
of "bsd":
@@ -465,6 +515,10 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
of "sunos": result = conf.target.targetOS == osSolaris
of "nintendoswitch":
result = conf.target.targetOS == osNintendoSwitch
of "freertos":
result = conf.target.targetOS == osFreeRTOS
of "lwip":
result = conf.target.targetOS in {osFreeRTOS}
of "littleendian": result = CPU[conf.target.targetCPU].endian == platform.littleEndian
of "bigendian": result = CPU[conf.target.targetCPU].endian == platform.bigEndian
of "cpu8": result = CPU[conf.target.targetCPU].bit == 8
@@ -499,8 +553,9 @@ const
DefaultConfigNims* = RelativeFile"config.nims"
DocConfig* = RelativeFile"nimdoc.cfg"
DocTexConfig* = RelativeFile"nimdoc.tex.cfg"
const oKeepVariableNames* = true
htmldocsDir* = htmldocsDirname.RelativeDir
docRootDefault* = "@default" # using `@` instead of `$` to avoid shell quoting complications
oKeepVariableNames* = true
proc mainCommandArg*(conf: ConfigRef): string =
## This is intended for commands like check or parse
@@ -521,21 +576,23 @@ proc setConfigVar*(conf: ConfigRef; key, val: string) =
conf.configVars[key] = val
proc getOutFile*(conf: ConfigRef; filename: RelativeFile, ext: string): AbsoluteFile =
conf.outDir / changeFileExt(filename, ext)
# explains regression https://github.com/nim-lang/Nim/issues/6583#issuecomment-625711125
# Yet another reason why "" should not mean "."; `""/something` should raise
# instead of implying "" == "." as it's bug prone.
doAssert conf.outDir.string.len > 0
result = conf.outDir / changeFileExt(filename, ext)
proc absOutFile*(conf: ConfigRef): AbsoluteFile =
doAssert not conf.outDir.isEmpty
doAssert not conf.outFile.isEmpty
result = conf.outDir / conf.outFile
when defined(posix):
if dirExists(result.string):
result.string.add ".out"
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
result = conf.outDir / conf.outFile
when defined(posix):
if dirExists(result.string):
result.string.add ".out"
result = conf.absOutFile
createDir result.string.parentDir
proc getPrefixDir*(conf: ConfigRef): AbsoluteDir =
## Gets the prefix dir, usually the parent directory where the binary resides.
@@ -575,17 +632,6 @@ proc setDefaultLibpath*(conf: ConfigRef) =
proc canonicalizePath*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
result = AbsoluteFile path.string.expandFilename
proc shortenDir*(conf: ConfigRef; dir: string): string {.
deprecated: "use 'relativeTo' instead".} =
## returns the interesting part of a dir
var prefix = conf.projectPath.string & DirSep
if startsWith(dir, prefix):
return substr(dir, prefix.len)
prefix = getPrefixDir(conf).string & DirSep
if startsWith(dir, prefix):
return substr(dir, prefix.len)
result = dir
proc removeTrailingDirSep*(path: string): string =
if (path.len > 0) and (path[^1] == DirSep):
result = substr(path, 0, path.len - 2)
@@ -613,7 +659,7 @@ proc getNimcacheDir*(conf: ConfigRef): AbsoluteDir =
# XXX projectName should always be without a file extension!
result = if not conf.nimcacheDir.isEmpty:
conf.nimcacheDir
elif conf.cmd == cmdCompileToJS:
elif conf.backend == backendJs:
conf.projectPath / genSubDir
else:
AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name &
@@ -643,12 +689,10 @@ iterator nimbleSubs*(conf: ConfigRef; p: string): string =
proc toGeneratedFile*(conf: ConfigRef; path: AbsoluteFile,
ext: string): AbsoluteFile =
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
let (head, tail) = splitPath(path.string)
result = getNimcacheDir(conf) / RelativeFile changeFileExt(tail, ext)
result = getNimcacheDir(conf) / RelativeFile path.string.splitPath.tail.changeFileExt(ext)
proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
createSubDir: bool = true): AbsoluteFile =
let (head, tail) = splitPath(f.string)
let subdir = getNimcacheDir(conf)
if createSubDir:
try:
@@ -656,7 +700,7 @@ proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
except OSError:
writeLine(stdout, "cannot create directory: " & subdir.string)
quit(1)
result = subdir / RelativeFile tail
result = subdir / RelativeFile f.string.splitPath.tail
#echo "completeGeneratedFilePath(", f, ") = ", result
proc rawFindFile(conf: ConfigRef; f: RelativeFile; suppressStdlib: bool): AbsoluteFile =
@@ -706,7 +750,7 @@ proc getRelativePathFromConfigPath*(conf: ConfigRef; f: AbsoluteFile): RelativeF
proc findFile*(conf: ConfigRef; f: string; suppressStdlib = false): AbsoluteFile =
if f.isAbsolute:
result = if f.existsFile: AbsoluteFile(f) else: AbsoluteFile""
result = if f.fileExists: AbsoluteFile(f) else: AbsoluteFile""
else:
result = rawFindFile(conf, RelativeFile f, suppressStdlib)
if result.isEmpty:
@@ -720,7 +764,8 @@ proc findFile*(conf: ConfigRef; f: string; suppressStdlib = false): AbsoluteFile
const stdlibDirs = [
"pure", "core", "arch",
"pure/collections",
"pure/concurrency", "impure",
"pure/concurrency",
"pure/unidecode", "impure",
"wrappers", "wrappers/linenoise",
"windows", "posix", "js"]
@@ -841,3 +886,18 @@ proc floatInt64Align*(conf: ConfigRef): int16 =
# to 4bytes (except with -malign-double)
return 4
return 8
proc setOutFile*(conf: ConfigRef) =
proc libNameTmpl(conf: ConfigRef): string {.inline.} =
result = if conf.target.targetOS == osWindows: "$1.lib" else: "lib$1.a"
if conf.outFile.isEmpty:
let base = conf.projectName
let targetName =
if optGenDynLib in conf.globalOptions:
platform.OS[conf.target.targetOS].dllFrmt % base
elif optGenStaticLib in conf.globalOptions:
libNameTmpl(conf) % base
else:
base & platform.OS[conf.target.targetOS].exeExt
conf.outFile = RelativeFile targetName

View File

@@ -16,7 +16,7 @@ iterator myParentDirs(p: string): string =
yield current
proc getNimbleFile*(conf: ConfigRef; path: string): string =
## returns absolute path to nimble file, eg: /pathto/cligen.nimble
## returns absolute path to nimble file, e.g.: /pathto/cligen.nimble
var parents = 0
block packageSearch:
for d in myParentDirs(path):
@@ -28,8 +28,6 @@ proc getNimbleFile*(conf: ConfigRef; path: string): string =
result = file
break packageSearch
# we also store if we didn't find anything:
when not defined(nimNoNilSeqs):
if result.isNil: result = ""
for d in myParentDirs(path):
#echo "set cache ", d, " |", result, "|", parents
conf.packageCache[d] = result
@@ -37,7 +35,7 @@ proc getNimbleFile*(conf: ConfigRef; path: string): string =
if parents <= 0: break
proc getPackageName*(conf: ConfigRef; path: string): string =
## returns nimble package name, eg: `cligen`
## returns nimble package name, e.g.: `cligen`
let path = getNimbleFile(conf, path)
result = path.splitFile.name

View File

@@ -99,14 +99,14 @@ proc compileConstraints(p: PNode, result: var TPatternCode; conf: ConfigRef) =
else:
# check all symkinds:
internalAssert conf, int(high(TSymKind)) < 255
for i in low(TSymKind)..high(TSymKind):
for i in TSymKind:
if cmpIgnoreStyle(($i).substr(2), spec) == 0:
result.add(ppSymKind)
result.add(chr(i.ord))
return
# check all nodekinds:
internalAssert conf, int(high(TNodeKind)) < 255
for i in low(TNodeKind)..high(TNodeKind):
for i in TNodeKind:
if cmpIgnoreStyle($i, spec) == 0:
result.add(ppNodeKind)
result.add(chr(i.ord))
@@ -200,7 +200,7 @@ proc exprRoot*(n: PNode): PSym =
if it.len > 0 and it.typ != nil: it = it.lastSon
else: break
of nkCallKinds:
if it.typ != nil and it.typ.kind == tyVar and it.len > 1:
if it.typ != nil and it.typ.kind in {tyVar, tyLent} and it.len > 1:
# See RFC #7373, calls returning 'var T' are assumed to
# return a view into the first argument (if there is one):
it = it[1]
@@ -214,7 +214,7 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
result = arNone
case n.kind
of nkEmpty:
if n.typ != nil and n.typ.kind == tyVar:
if n.typ != nil and n.typ.kind in {tyVar}:
result = arLValue
of nkSym:
let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet, skForVar}
@@ -223,6 +223,8 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
result = arLValue
elif isUnsafeAddr and n.sym.kind == skParam:
result = arLValue
elif isUnsafeAddr and n.sym.kind == skConst and dontInlineConstant(n, n.sym.ast):
result = arLValue
elif n.sym.kind in kinds:
if owner != nil and owner == n.sym.owner and
sfGlobal notin n.sym.flags:
@@ -231,7 +233,7 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
result = arLValue
elif n.sym.kind == skType:
let t = n.sym.typ.skipTypes({tyTypeDesc})
if t.kind == tyVar: result = arStrange
if t.kind in {tyVar}: result = arStrange
of nkDotExpr:
let t = skipTypes(n[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
@@ -277,7 +279,7 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
# builtin slice keeps lvalue-ness:
if getMagic(n) in {mArrGet, mSlice}:
result = isAssignable(owner, n[1], isUnsafeAddr)
elif n.typ != nil and n.typ.kind == tyVar:
elif n.typ != nil and n.typ.kind in {tyVar}:
result = arLValue
elif isUnsafeAddr and n.typ != nil and n.typ.kind == tyLent:
result = arLValue

File diff suppressed because it is too large Load Diff

View File

@@ -113,10 +113,8 @@ const
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:
if module.getnimblePkgId == graph.config.mainPackageId:
graph.config.notes = graph.config.mainPackageNotes
else:
if graph.config.mainPackageNotes == {}: graph.config.mainPackageNotes = graph.config.notes
@@ -128,7 +126,7 @@ proc moduleHasChanged*(graph: ModuleGraph; module: PSym): bool {.inline.} =
proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {.discardable.} =
if graph.stopCompile(): return true
var
p: TParsers
p: Parser
a: TPassContextArray
s: PLLStream
fileIdx = module.fileIdx
@@ -166,7 +164,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
else:
s = stream
while true:
openParsers(p, fileIdx, s, graph.cache, graph.config)
openParser(p, fileIdx, s, graph.cache, graph.config)
if module.owner == nil or module.owner.name.s != "stdlib" or module.name.s == "distros":
# XXX what about caching? no processing then? what if I change the
@@ -214,7 +212,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
else:
#echo "----- single\n", n
if not processTopLevelStmt(graph, n, a): break
closeParsers(p)
closeParser(p)
if s.kind != llsStdIn: break
closePasses(graph, a)
# id synchronization point for more consistent code generation:

View File

@@ -99,19 +99,3 @@ when true:
proc addFileExt*(x: RelativeFile; ext: string): RelativeFile {.borrow.}
proc writeFile*(x: AbsoluteFile; content: string) {.borrow.}
when isMainModule:
doAssert AbsoluteDir"/Users/me///" / RelativeFile"z.nim" == AbsoluteFile"/Users/me/z.nim"
doAssert AbsoluteDir"/Users/me" / RelativeFile"../z.nim" == AbsoluteFile"/Users/z.nim"
doAssert AbsoluteDir"/Users/me/" / RelativeFile"../z.nim" == AbsoluteFile"/Users/z.nim"
doAssert relativePath("/foo/bar.nim", "/foo/", '/') == "bar.nim"
doAssert $RelativeDir"foo/bar" == "foo/bar"
doAssert RelativeDir"foo/bar" == RelativeDir"foo/bar"
doAssert RelativeFile"foo/bar".changeFileExt(".txt") == RelativeFile"foo/bar.txt"
doAssert RelativeFile"foo/bar".addFileExt(".txt") == RelativeFile"foo/bar.txt"
doAssert not RelativeDir"foo/bar".isEmpty
doAssert RelativeDir"".isEmpty
when isMainModule and defined(windows):
let nasty = string(AbsoluteDir(r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\linkedPkgs\pkgB-#head\../../simplePkgs/pkgB-#head/") / RelativeFile"pkgA/module.nim")
doAssert nasty.replace('/', '\\') == r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\simplePkgs\pkgB-#head\pkgA\module.nim"

View File

@@ -53,7 +53,7 @@ const
wDeprecated,
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
wInjectStmt, wExperimental, wThis, wUsed, wInvariant, wAssume}
wInjectStmt, wExperimental, wThis, wUsed, wInvariant, wAssume, wAssert}
lambdaPragmas* = {FirstCallConv..LastCallConv,
wNoSideEffect, wSideEffect, wNoreturn, wNosinks, wDynlib, wHeader,
wThread, wAsmNoStackFrame,
@@ -61,18 +61,20 @@ const
wGcSafe, wCodegenDecl, wNoInit}
typePragmas* = declPragmas + {wMagic, wAcyclic,
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wShallow,
wIncompleteStruct, wByCopy, wByRef,
wIncompleteStruct, wCompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow, wGcSafe, wPartial, wExplain, wPackage}
fieldPragmas* = declPragmas + {wGuard, wBitsize, wCursor,
wRequiresInit, wAlign} - {wExportNims, wNodecl} # why exclude these?
wRequiresInit, wNoalias, wAlign} - {wExportNims, wNodecl} # why exclude these?
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
wMagic, wHeader, wCompilerProc, wCore, wDynlib,
wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wCursor, wAlign}
wGensym, wInject, wCodegenDecl,
wGuard, wGoto, wCursor, wNoalias, wAlign}
constPragmas* = declPragmas + {wHeader, wMagic,
wGensym, wInject,
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
paramPragmas* = {wNoalias, wInject, wGensym}
letPragmas* = varPragmas
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
wThread, wRaises, wLocks, wTags, wGcSafe,
@@ -178,7 +180,7 @@ proc processImportCpp(c: PContext; s: PSym, extname: string, info: TLineInfo) =
incl(s.flags, sfImportc)
incl(s.flags, sfInfixCall)
excl(s.flags, sfForward)
if c.config.cmd == cmdCompileToC:
if c.config.backend == backendC:
let m = s.getModule()
incl(m.flags, sfCompileToCpp)
incl c.config.globalOptions, optMixedMode
@@ -237,7 +239,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
var v: string
if n[1].kind == nkIdent: v = n[1].ident.s
else: v = expectStrLit(c, n)
for m in low(TMagic)..high(TMagic):
for m in TMagic:
if substr($m, 1) == v:
s.magic = m
break
@@ -246,7 +248,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
# this assumes that the order of special words and calling conventions is
# the same
result = TCallingConvention(ord(ccDefault) + ord(sw) - ord(wNimcall))
TCallingConvention(ord(ccNimCall) + ord(sw) - ord(wNimcall))
proc isTurnedOn(c: PContext, n: PNode): bool =
if n.kind in nkPragmaCallKinds and n.len == 2:
@@ -256,8 +258,8 @@ proc isTurnedOn(c: PContext, n: PNode): bool =
localError(c.config, n.info, "'on' or 'off' expected")
proc onOff(c: PContext, n: PNode, op: TOptions, resOptions: var TOptions) =
if isTurnedOn(c, n): resOptions = resOptions + op
else: resOptions = resOptions - op
if isTurnedOn(c, n): resOptions.incl op
else: resOptions.excl op
proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
if isTurnedOn(c, n):
@@ -325,35 +327,32 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
# a calling convention that doesn't introduce custom name mangling
# cdecl is the default - the user can override this explicitly
if sym.kind in routineKinds and sym.typ != nil and
sym.typ.callConv == ccDefault:
tfExplicitCallConv notin sym.typ.flags:
sym.typ.callConv = ccCDecl
proc processNote(c: PContext, n: PNode) =
template handleNote(enumVals, notes) =
let x = findStr(enumVals, n[0][1].ident.s, errUnknown)
if x != errUnknown:
nk = TNoteKind(x)
let x = c.semConstBoolExpr(c, n[1])
n[1] = x
if x.kind == nkIntLit and x.intVal != 0: incl(notes, nk)
else: excl(notes, nk)
else:
invalidPragma(c, n)
if n.kind in nkPragmaCallKinds and n.len == 2 and
n[0].kind == nkBracketExpr and
n[0].len == 2 and
n[0][1].kind == nkIdent and n[0][0].kind == nkIdent:
var nk: TNoteKind
case whichKeyword(n[0][0].ident)
of wHint:
var x = findStr(HintsToStr, n[0][1].ident.s)
if x >= 0: nk = TNoteKind(x + ord(hintMin))
else: invalidPragma(c, n); return
of wWarning:
var x = findStr(WarningsToStr, n[0][1].ident.s)
if x >= 0: nk = TNoteKind(x + ord(warnMin))
else: invalidPragma(c, n); return
else:
invalidPragma(c, n)
return
let x = c.semConstBoolExpr(c, n[1])
n[1] = x
if x.kind == nkIntLit and x.intVal != 0: incl(c.config.notes, nk)
else: excl(c.config.notes, nk)
# checkme: honor cmdlineNotes with: c.setNote(nk, x.kind == nkIntLit and x.intVal != 0)
else:
invalidPragma(c, n)
of wHint: handleNote(hintMin .. hintMax, c.config.notes)
of wWarning: handleNote(warnMin .. warnMax, c.config.notes)
of wWarningAsError: handleNote(warnMin .. warnMax, c.config.warningAsErrors)
else: invalidPragma(c, n)
else: invalidPragma(c, n)
proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} =
case w
@@ -363,7 +362,6 @@ proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} =
of wRangeChecks: {optRangeCheck}
of wBoundChecks: {optBoundsCheck}
of wOverflowChecks: {optOverflowCheck}
of wNilChecks: {optNilCheck}
of wFloatChecks: {optNaNCheck, optInfCheck}
of wNanChecks: {optNaNCheck}
of wInfChecks: {optInfCheck}
@@ -472,14 +470,12 @@ proc processPop(c: PContext, n: PNode) =
proc processDefine(c: PContext, n: PNode) =
if (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent):
defineSymbol(c.config.symbols, n[1].ident.s)
message(c.config, n.info, warnDeprecated, "define is deprecated")
else:
invalidPragma(c, n)
proc processUndef(c: PContext, n: PNode) =
if (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent):
undefSymbol(c.config.symbols, n[1].ident.s)
message(c.config, n.info, warnDeprecated, "undef is deprecated")
else:
invalidPragma(c, n)
@@ -548,7 +544,7 @@ proc processLink(c: PContext, n: PNode) =
proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
case n[1].kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
result = newNode(if n.kind == nkAsmStmt: nkAsmStmt else: nkArgList, n.info)
result = newNodeI(if n.kind == nkAsmStmt: nkAsmStmt else: nkArgList, n.info)
var str = n[1].strVal
if str == "":
localError(con.config, n.info, "empty 'asm' statement")
@@ -579,7 +575,7 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
a = c + 1
else:
illFormedAstLocal(n, con.config)
result = newNode(nkAsmStmt, n.info)
result = newNodeI(nkAsmStmt, n.info)
proc pragmaEmit(c: PContext, n: PNode) =
if n.kind notin nkPragmaCallKinds or n.len != 2:
@@ -642,7 +638,7 @@ proc processPragma(c: PContext, n: PNode, i: int) =
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])
userPragma.ast = newTreeI(nkPragma, n.info, n.sons[i+1..^1])
strTableAdd(c.userPragmas, userPragma)
proc pragmaRaisesOrTags(c: PContext, n: PNode) =
@@ -786,6 +782,15 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
if key.kind == nkBracketExpr:
processNote(c, it)
return
elif key.kind == nkCast:
if comesFromPush:
localError(c.config, n.info, "a 'cast' pragma cannot be pushed")
elif not isStatement:
localError(c.config, n.info, "'cast' pragma only allowed in a statement context")
case whichPragma(key[1])
of wRaises, wTags: pragmaRaisesOrTags(c, key[1])
else: discard
return
elif key.kind notin nkIdentKinds:
n[i] = semCustomPragma(c, it)
return
@@ -813,8 +818,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
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)
if c.config.backend != backendCpp:
localError(c.config, it.info, "exportcpp requires `cpp` backend, got " & $c.config.backend)
else:
incl(sym.flags, sfMangleCpp)
incl(sym.flags, sfUsed) # avoid wrong hints
@@ -835,7 +840,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wImportCpp:
processImportCpp(c, sym, getOptionalStr(c, it, "$1"), it.info)
of wImportJs:
if c.config.cmd != cmdCompileToJS:
if c.config.backend != backendJs:
localError(c.config, it.info, "`importjs` pragma requires the JavaScript target")
let name = getOptionalStr(c, it, "$1")
incl(sym.flags, sfImportc)
@@ -880,6 +885,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wRegister:
noVal(c, it)
incl(sym.flags, sfRegister)
of wNoalias:
noVal(c, it)
incl(sym.flags, sfNoalias)
of wThreadVar:
noVal(c, it)
incl(sym.flags, {sfThread, sfGlobal})
@@ -889,7 +897,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wMagic: processMagic(c, it, sym)
of wCompileTime:
noVal(c, it)
incl(sym.flags, sfCompileTime)
if comesFromPush:
if sym.kind in {skProc, skFunc}:
incl(sym.flags, sfCompileTime)
else:
incl(sym.flags, sfCompileTime)
#incl(sym.loc.flags, lfNoDecl)
of wGlobal:
noVal(c, it)
@@ -994,7 +1006,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
incl(sym.flags, sfProcvar)
if sym.typ != nil:
incl(sym.typ.flags, tfThread)
if sym.typ.callConv == ccClosure: sym.typ.callConv = ccDefault
if sym.typ.callConv == ccClosure: sym.typ.callConv = ccNimCall
of wGcSafe:
noVal(c, it)
if sym != nil:
@@ -1049,7 +1061,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wPush:
processPush(c, n, i + 1)
result = true
of wPop: processPop(c, it)
of wPop:
processPop(c, it)
result = true
of wPragma:
if not sym.isNil and sym.kind == skTemplate:
sym.flags.incl sfCustomPragma
@@ -1077,7 +1091,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of FirstCallConv..LastCallConv:
assert(sym != nil)
if sym.typ == nil: invalidPragma(c, it)
else: sym.typ.callConv = wordToCallConv(k)
else:
sym.typ.callConv = wordToCallConv(k)
sym.typ.flags.incl tfExplicitCallConv
of wEmit: pragmaEmit(c, it)
of wUnroll: pragmaUnroll(c, it)
of wLinearScanEnd, wComputedGoto: noVal(c, it)
@@ -1088,6 +1104,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
noVal(c, it)
if sym.typ == nil: invalidPragma(c, it)
else: incl(sym.typ.flags, tfIncompleteStruct)
of wCompleteStruct:
noVal(c, it)
if sym.typ == nil: invalidPragma(c, it)
else: incl(sym.typ.flags, tfCompleteStruct)
of wUnchecked:
noVal(c, it)
if sym.typ == nil or sym.typ.kind notin {tyArray, tyUncheckedArray}:
@@ -1095,9 +1115,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
else:
sym.typ.kind = tyUncheckedArray
of wUnion:
noVal(c, it)
if sym.typ == nil: invalidPragma(c, it)
else: incl(sym.typ.flags, tfUnion)
if c.config.backend == backendJs:
localError(c.config, it.info, "`{.union.}` is not implemented for js backend.")
else:
noVal(c, it)
if sym.typ == nil: invalidPragma(c, it)
else: incl(sym.typ.flags, tfUnion)
of wRequiresInit:
noVal(c, it)
if sym.kind == skField:

View File

@@ -54,36 +54,3 @@ proc prefixMatch*(p, s: string): PrefixMatch =
else:
return PrefixMatch.None
return PrefixMatch.None
when isMainModule:
import macros
macro check(val, body: untyped): untyped =
result = newStmtList()
expectKind body, nnkStmtList
for b in body:
expectKind b, nnkPar
expectLen b, 2
let p = b[0]
let s = b[1]
result.add quote do:
echo prefixMatch(`p`, `s`) == `val`
check PrefixMatch.Prefix:
("abc", "abc")
("a", "abc")
("xyz", "X_yzzzZe")
check PrefixMatch.Substr:
("b", "abc")
("abc", "fooabcabc")
("abC", "foo_AB_c")
check PrefixMatch.Abbrev:
("abc", "AxxxBxxxCxxx")
("xyz", "X_yabcZe")
check PrefixMatch.None:
("foobar", "afkslfjd_as")
("xyz", "X_yuuZuuZe")
("ru", "remotes")

View File

@@ -11,7 +11,7 @@
# This is needed for proper handling of forward declarations.
import
ast, astalgo, msgs, semdata, types, trees, strutils
ast, astalgo, msgs, semdata, types, trees, strutils, lookups
proc equalGenericParams(procA, procB: PNode): bool =
if procA.len != procB.len: return false
@@ -28,40 +28,7 @@ proc equalGenericParams(procA, procB: PNode): bool =
if not exprStructuralEquivalent(a.ast, b.ast): return
result = true
proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym =
# 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
result = initIdentIter(it, scope.symbols, fn.name)
if isGenericRoutine(fn):
# we simply check the AST; this is imprecise but nearly the best what
# can be done; this doesn't work either though as type constraints are
# not kept in the AST ..
while result != nil:
if result.kind == fn.kind and isGenericRoutine(result):
let genR = result.ast[genericParamsPos]
let genF = fn.ast[genericParamsPos]
if exprStructuralEquivalent(genR, genF) and
exprStructuralEquivalent(result.ast[paramsPos],
fn.ast[paramsPos]) and
equalGenericParams(genR, genF):
return
result = nextIdentIter(it, scope.symbols)
else:
while result != nil:
if result.kind == fn.kind and not isGenericRoutine(result):
case equalParams(result.typ.n, fn.typ.n)
of paramsEqual:
return
of paramsIncompatible:
localError(c.config, fn.info, "overloaded '$1' leads to ambiguous calls" % fn.name.s)
return
of paramsNotEqual:
discard
result = nextIdentIter(it, scope.symbols)
proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
proc searchForProcAux(c: PContext, scope: PScope, fn: PSym): PSym =
const flags = {ExactGenericParams, ExactTypeDescValues,
ExactConstraints, IgnoreCC}
var it: TIdentIter
@@ -83,15 +50,13 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
discard
result = nextIdentIter(it, scope.symbols)
proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
result = searchForProcNew(c, scope, fn)
when false:
let old = searchForProcOld(c, scope, fn)
if old != result:
echo "Mismatch in searchForProc: ", fn.info
debug fn.typ
debug if result != nil: result.typ else: nil
debug if old != nil: old.typ else: nil
proc searchForProc*(c: PContext, scope: PScope, fn: PSym): tuple[proto: PSym, comesFromShadowScope: bool] =
var scope = scope
result.proto = searchForProcAux(c, scope, fn)
while result.proto == nil and scope.isShadowScope:
scope = scope.parent
result.proto = searchForProcAux(c, scope, fn)
result.comesFromShadowScope = true
when false:
proc paramsFitBorrow(child, parent: PNode): bool =

7
compiler/readme.md Normal file
View File

@@ -0,0 +1,7 @@
## Nim Compiler
- This directory contains the Nim compiler written in Nim.
- Note that this code has been translated from a bootstrapping version written in Pascal.
- So the code is **not** a poster child of good Nim code.
See [Internals of the Nim Compiler](https://nim-lang.org/docs/intern.html) for more information.

View File

@@ -1,5 +0,0 @@
This directory contains the Nim compiler written in Nim. Note that this
code has been translated from a bootstrapping version written in Pascal, so
the code is **not** a poster child of good Nim code.
See https://nim-lang.org/docs/intern.html for more information.

View File

@@ -20,10 +20,11 @@ import
type
TRenderFlag* = enum
renderNone, renderNoBody, renderNoComments, renderDocComments,
renderNoPragmas, renderIds, renderNoProcDefs, renderSyms
renderNoPragmas, renderIds, renderNoProcDefs, renderSyms, renderRunnableExamples,
renderIr
TRenderFlags* = set[TRenderFlag]
TRenderTok* = object
kind*: TTokType
kind*: TokType
length*: int16
sym*: PSym
@@ -48,11 +49,20 @@ type
pendingNewlineCount: int
fid*: FileIndex
config*: ConfigRef
mangler: seq[PSym]
# We render the source code in a two phases: The first
# determines how long the subtree will likely be, the second
# phase appends to a buffer that will be the output.
proc disamb(g: var TSrcGen; s: PSym): int =
# we group by 's.name.s' to compute the stable name ID.
result = 0
for i in 0 ..< g.mangler.len:
if s == g.mangler[i]: return result
if s.name.s == g.mangler[i].name.s: inc result
g.mangler.add s
proc isKeyword*(i: PIdent): bool =
if (i.id >= ord(tokKeywordLow) - ord(tkSymbol)) and
(i.id <= ord(tokKeywordHigh) - ord(tkSymbol)):
@@ -109,7 +119,7 @@ proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags; config: ConfigRef) =
g.inGenericParams = false
g.config = config
proc addTok(g: var TSrcGen, kind: TTokType, s: string; sym: PSym = nil) =
proc addTok(g: var TSrcGen, kind: TokType, s: string; sym: PSym = nil) =
g.tokens.add TRenderTok(kind: kind, length: int16(s.len), sym: sym)
g.buf.add(s)
if kind != tkSpaces:
@@ -150,7 +160,6 @@ proc putNL(g: var TSrcGen) =
proc optNL(g: var TSrcGen, indent: int) =
g.pendingNL = indent
g.lineLen = indent
g.col = g.indent
when defined(nimpretty): g.pendingNewlineCount = 0
proc optNL(g: var TSrcGen) =
@@ -159,7 +168,6 @@ proc optNL(g: var TSrcGen) =
proc optNL(g: var TSrcGen; a, b: PNode) =
g.pendingNL = g.indent
g.lineLen = g.indent
g.col = g.indent
when defined(nimpretty): g.pendingNewlineCount = lineDiff(a, b)
proc indentNL(g: var TSrcGen) =
@@ -174,7 +182,7 @@ proc dedent(g: var TSrcGen) =
dec(g.pendingNL, IndentWidth)
dec(g.lineLen, IndentWidth)
proc put(g: var TSrcGen, kind: TTokType, s: string; sym: PSym = nil) =
proc put(g: var TSrcGen, kind: TokType, s: string; sym: PSym = nil) =
if kind != tkSpaces:
addPendingNL(g)
if s.len > 0:
@@ -247,7 +255,7 @@ proc maxLineLength(s: string): int =
inc(lineLen)
inc(i)
proc putRawStr(g: var TSrcGen, kind: TTokType, s: string) =
proc putRawStr(g: var TSrcGen, kind: TokType, s: string) =
var i = 0
let hi = s.len - 1
var str = ""
@@ -319,8 +327,8 @@ proc lsub(g: TSrcGen; n: PNode): int
proc litAux(g: TSrcGen; n: PNode, x: BiggestInt, size: int): string =
proc skip(t: PType): PType =
result = t
while result != nil and result.kind in {tyGenericInst, tyRange, tyVar, tyLent, tyDistinct,
tyOrdinal, tyAlias, tySink}:
while result != nil and result.kind in {tyGenericInst, tyRange, tyVar,
tyLent, tyDistinct, tyOrdinal, tyAlias, tySink}:
result = lastSon(result)
let typ = n.typ.skip
@@ -336,7 +344,7 @@ proc litAux(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:
var y = if size < sizeof(BiggestInt): x and ((1 shl (size*8)) - 1)
var y = if size < sizeof(BiggestInt): x and ((1.BiggestInt shl (size*8)) - 1)
else: x
result = "0o" & toOct(y, size * 3)
elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2)
@@ -459,8 +467,8 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkDo: result = lsons(g, n) + len("do__:_")
of nkConstDef, nkIdentDefs:
result = lcomma(g, n, 0, - 3)
if n[^2].kind != nkEmpty: result = result + lsub(g, n[^2]) + 2
if n[^1].kind != nkEmpty: result = result + lsub(g, n[^1]) + 3
if n[^2].kind != nkEmpty: result += lsub(g, n[^2]) + 2
if n[^1].kind != nkEmpty: result += lsub(g, n[^1]) + 3
of nkVarTuple:
if n[^1].kind == nkEmpty:
result = lcomma(g, n, 0, - 2) + len("()")
@@ -471,8 +479,8 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkChckRange: result = len("chckRange") + 2 + lcomma(g, n)
of nkObjDownConv, nkObjUpConv:
result = 2
if n.len >= 1: result = result + lsub(g, n[0])
result = result + lcomma(g, n, 1)
if n.len >= 1: result += lsub(g, n[0])
result += lcomma(g, n, 1)
of nkExprColonExpr: result = lsons(g, n) + 2
of nkInfix: result = lsons(g, n) + 2
of nkPrefix:
@@ -536,7 +544,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkGenericParams: result = lcomma(g, n) + 2
of nkFormalParams:
result = lcomma(g, n, 1) + 2
if n[0].kind != nkEmpty: result = result + lsub(g, n[0]) + 2
if n[0].kind != nkEmpty: result += lsub(g, n[0]) + 2
of nkExceptBranch:
result = lcomma(g, n, 0, -2) + lsub(g, lastSon(n)) + len("except_:_")
of nkObjectTy:
@@ -575,7 +583,7 @@ proc hasCom(n: PNode): bool =
for i in 0..<n.len:
if hasCom(n[i]): return true
proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) =
proc putWithSpace(g: var TSrcGen, kind: TokType, s: string) =
put(g, kind, s)
put(g, tkSpaces, Space)
@@ -589,7 +597,7 @@ proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0,
gsub(g, n[i])
if c:
if g.tokens.len > oldLen:
putWithSpace(g, separator, TokTypeToStr[separator])
putWithSpace(g, separator, $separator)
if hasCom(n[i]):
gcoms(g)
optNL(g, ind)
@@ -618,7 +626,7 @@ proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
theEnd: int = - 1) =
for i in start..n.len + theEnd: gsub(g, n[i], c)
proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TTokType,
proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TokType,
k: string) =
if n.len == 0: return # empty var sections are possible
putWithSpace(g, kind, k)
@@ -847,7 +855,7 @@ proc gident(g: var TSrcGen, n: PNode) =
if sfAnon in n.sym.flags or
(n.typ != nil and tfImplicitTypeParam in n.typ.flags): return
var t: TTokType
var t: TokType
var s = atom(g, n)
if s.len > 0 and s[0] in lexer.SymChars:
if n.kind == nkIdent:
@@ -855,12 +863,19 @@ proc gident(g: var TSrcGen, n: PNode) =
(n.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)):
t = tkSymbol
else:
t = TTokType(n.ident.id + ord(tkSymbol))
t = TokType(n.ident.id + ord(tkSymbol))
else:
t = tkSymbol
else:
t = tkOpr
if n.kind == nkSym and (renderIds in g.flags or sfGenSym in n.sym.flags or n.sym.kind == skTemp):
if renderIr in g.flags and n.kind == nkSym:
let localId = disamb(g, n.sym)
if localId != 0 and n.sym.magic == mNone:
s.add '_'
s.addInt localId
if sfCursor in n.sym.flags:
s.add "_cursor"
elif n.kind == nkSym and (renderIds in g.flags or sfGenSym in n.sym.flags or n.sym.kind == skTemp):
s.add '_'
s.addInt n.sym.id
when defined(debugMagics):
@@ -884,12 +899,23 @@ proc gsub(g: var TSrcGen; n: PNode; i: int) =
else:
put(g, tkOpr, "<<" & $i & "th child missing for " & $n.kind & " >>")
proc isBracket*(n: PNode): bool =
case n.kind
of nkClosedSymChoice, nkOpenSymChoice:
if n.len > 0: result = isBracket(n[0])
of nkSym: result = n.sym.name.s == "[]"
else: result = false
type
BracketKind = enum
bkNone, bkBracket, bkBracketAsgn, bkCurly, bkCurlyAsgn
proc bracketKind*(g: TSrcGen, n: PNode): BracketKind =
if renderIds notin g.flags:
case n.kind
of nkClosedSymChoice, nkOpenSymChoice:
if n.len > 0: result = bracketKind(g, n[0])
of nkSym:
result = case n.sym.name.s
of "[]": bkBracket
of "[]=": bkBracketAsgn
of "{}": bkCurly
of "{}=": bkCurlyAsgn
else: bkNone
else: result = bkNone
proc skipHiddenNodes(n: PNode): PNode =
result = n
@@ -902,10 +928,11 @@ proc skipHiddenNodes(n: PNode): PNode =
else: break
proc accentedName(g: var TSrcGen, n: PNode) =
const backticksNeeded = OpChars + {'[', '{'}
if n == nil: return
let isOperator =
if n.kind == nkIdent and n.ident.s.len > 0 and n.ident.s[0] in OpChars: true
elif n.kind == nkSym and n.sym.name.s.len > 0 and n.sym.name.s[0] in OpChars: true
if n.kind == nkIdent and n.ident.s.len > 0 and n.ident.s[0] in backticksNeeded: true
elif n.kind == nkSym and n.sym.name.s.len > 0 and n.sym.name.s[0] in backticksNeeded: true
else: false
if isOperator:
@@ -964,12 +991,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
of nkCharLit: put(g, tkCharLit, atom(g, n))
of nkNilLit: put(g, tkNil, atom(g, n)) # complex expressions
of nkCall, nkConv, nkDotCall, nkPattern, nkObjConstr:
if renderIds notin g.flags and n.len > 0 and isBracket(n[0]):
gsub(g, n, 1)
put(g, tkBracketLe, "[")
gcomma(g, n, 2)
put(g, tkBracketRi, "]")
elif n.len > 1 and n.lastSon.kind == nkStmtList:
if n.len > 1 and n.lastSon.kind in {nkStmtList, nkStmtListExpr}:
accentedName(g, n[0])
if n.len > 2:
put(g, tkParLe, "(")
@@ -977,10 +999,41 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
put(g, tkParRi, ")")
put(g, tkColon, ":")
gsub(g, n, n.len-1)
elif n.len >= 1:
case bracketKind(g, n[0])
of bkBracket:
gsub(g, n, 1)
put(g, tkBracketLe, "[")
gcomma(g, n, 2)
put(g, tkBracketRi, "]")
of bkBracketAsgn:
gsub(g, n, 1)
put(g, tkBracketLe, "[")
gcomma(g, n, 2, -2)
put(g, tkBracketRi, "]")
put(g, tkSpaces, Space)
putWithSpace(g, tkEquals, "=")
gsub(g, n, n.len - 1)
of bkCurly:
gsub(g, n, 1)
put(g, tkCurlyLe, "{")
gcomma(g, n, 2)
put(g, tkCurlyRi, "}")
of bkCurlyAsgn:
gsub(g, n, 1)
put(g, tkCurlyLe, "{")
gcomma(g, n, 2, -2)
put(g, tkCurlyRi, "}")
put(g, tkSpaces, Space)
putWithSpace(g, tkEquals, "=")
gsub(g, n, n.len - 1)
of bkNone:
accentedName(g, n[0])
put(g, tkParLe, "(")
gcomma(g, n, 1)
put(g, tkParRi, ")")
else:
if n.len >= 1: accentedName(g, n[0])
put(g, tkParLe, "(")
gcomma(g, n, 1)
put(g, tkParRi, ")")
of nkCallStrLit:
if n.len > 0: accentedName(g, n[0])
@@ -988,16 +1041,34 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
put(g, tkRStrLit, '\"' & replace(n[1].strVal, "\"", "\"\"") & '\"')
else:
gsub(g, n, 1)
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv:
of nkHiddenStdConv, nkHiddenSubConv:
if n.len >= 2:
when false:
# if {renderIds, renderIr} * g.flags != {}:
put(g, tkSymbol, "(conv)")
put(g, tkParLe, "(")
gsub(g, n[1])
put(g, tkParRi, ")")
else:
gsub(g, n[1])
else:
put(g, tkSymbol, "(wrong conv)")
of nkHiddenCallConv:
if {renderIds, renderIr} * g.flags != {}:
accentedName(g, n[0])
put(g, tkParLe, "(")
gcomma(g, n, 1)
put(g, tkParRi, ")")
elif n.len >= 2:
gsub(g, n[1])
else:
put(g, tkSymbol, "(wrong conv)")
of nkCast:
put(g, tkCast, "cast")
put(g, tkBracketLe, "[")
gsub(g, n, 0)
put(g, tkBracketRi, "]")
if n.len > 0 and n[0].kind != nkEmpty:
put(g, tkBracketLe, "[")
gsub(g, n, 0)
put(g, tkBracketRi, "]")
put(g, tkParLe, "(")
gsub(g, n, 1)
put(g, tkParRi, ")")
@@ -1155,7 +1226,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
infixArgument(g, n, 1)
put(g, tkSpaces, Space)
gsub(g, n, 0) # binary operator
# eg: `n1 == n2` decompses as following sum:
# e.g.: `n1 == n2` decompses as following sum:
if n.len == 3 and not fits(g, oldLineLen + lsub(g, n[1]) + lsub(g, n[2]) + lsub(g, n[0]) + len(" ")):
optNL(g, g.indent + longIndentWid)
else:
@@ -1589,7 +1660,7 @@ proc initTokRender*(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) =
initSrcGen(r, renderFlags, newPartialConfigRef())
gsub(r, n)
proc getNextTok*(r: var TSrcGen, kind: var TTokType, literal: var string) =
proc getNextTok*(r: var TSrcGen, kind: var TokType, literal: var string) =
if r.idx < r.tokens.len:
kind = r.tokens[r.idx].kind
let length = r.tokens[r.idx].length.int
@@ -1609,9 +1680,9 @@ proc quoteExpr*(a: string): string {.inline.} =
## can be used for quoting expressions in error msgs.
"'" & a & "'"
proc genFieldError*(field: PSym, disc: PSym): string =
proc genFieldDefect*(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
## provide this error msg FieldDefect; 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 " &

152
compiler/renderverbatim.nim Normal file
View File

@@ -0,0 +1,152 @@
import strutils
from xmltree import addEscaped
import ast, options, msgs
import packages/docutils/highlite
const isDebug = false
when isDebug:
import renderer
import astalgo
proc lastNodeRec(n: PNode): PNode =
result = n
while result.safeLen > 0: result = result[^1]
proc isInIndentationBlock(src: string, indent: int): bool =
#[
we stop at the first de-indentation; there's an inherent ambiguity with non
doc comments since they can have arbitrary indentation, so we just take the
practical route and require a runnableExamples to keep its code (including non
doc comments) to its indentation level.
]#
for j in 0..<indent:
if src.len <= j: return true
if src[j] != ' ': return false
return true
type LineData = object
## keep track of which lines are starting inside a multiline doc comment.
## We purposefully avoid re-doing parsing which is already done (we get a PNode)
## so we don't worry about whether we're inside (nested) doc comments etc.
## But we sill need some logic to disambiguate different multiline styles.
conf: ConfigRef
lineFirst: int
lines: seq[bool]
## lines[index] is true if line `lineFirst+index` starts inside a multiline string
## Using a HashSet (extra dependency) would simplify but not by much.
proc tripleStrLitStartsAtNextLine(conf: ConfigRef, n: PNode): bool =
# enabling TLineInfo.offsetA,offsetB would probably make this easier
const tripleQuote = "\"\"\""
let src = sourceLine(conf, n.info)
let col = n.info.col
doAssert src.continuesWith(tripleQuote, col) # sanity check
var i = col + 3
var onlySpace = true
while true:
if src.len <= i:
doAssert src.len == i
return onlySpace
elif src.continuesWith(tripleQuote, i) and (src.len == i+3 or src[i+3] != '\"'):
return false # triple lit is in 1 line
elif src[i] != ' ': onlySpace = false
i.inc
proc visitMultilineStrings(ldata: var LineData, n: PNode) =
var cline = ldata.lineFirst
template setLine() =
let index = cline - ldata.lineFirst
if ldata.lines.len < index+1: ldata.lines.setLen index+1
ldata.lines[index] = true
case n.kind
of nkTripleStrLit:
# same logic should be applied for any multiline token
# we could also consider nkCommentStmt but right now we just assume doc comments,
# unlike triple string litterals, don't de-indent from runnableExamples.
cline = n.info.line.int
if tripleStrLitStartsAtNextLine(ldata.conf, n):
cline.inc
setLine()
for ai in n.strVal:
case ai
of '\n':
cline.inc
setLine()
else: discard
else:
for i in 0..<n.safeLen:
visitMultilineStrings(ldata, n[i])
proc startOfLineInsideTriple(ldata: LineData, line: int): bool =
let index = line - ldata.lineFirst
if index >= ldata.lines.len: false
else: ldata.lines[index]
proc extractRunnableExamplesSource*(conf: ConfigRef; n: PNode): string =
## TLineInfo.offsetA,offsetB would be cleaner but it's only enabled for nimpretty,
## we'd need to check performance impact to enable it for nimdoc.
var first = n.lastSon.info
if first.line == n[0].info.line:
#[
runnableExamples: assert true
]#
discard
else:
#[
runnableExamples:
# non-doc comment that we want to capture even though `first` points to `assert true`
assert true
]#
first.line = n[0].info.line + 1
let last = n.lastNodeRec.info
var info = first
var indent = info.col
let numLines = numLines(conf, info.fileIndex).uint16
var lastNonemptyPos = 0
var ldata = LineData(lineFirst: first.line.int, conf: conf)
visitMultilineStrings(ldata, n[^1])
when isDebug:
debug(n)
for i in 0..<ldata.lines.len:
echo (i+ldata.lineFirst, ldata.lines[i])
result = ""
for line in first.line..numLines: # bugfix, see `testNimDocTrailingExample`
info.line = line
let src = sourceLine(conf, info)
let special = startOfLineInsideTriple(ldata, line.int)
if line > last.line and not special and not isInIndentationBlock(src, indent):
break
if line > first.line: result.add "\n"
if special:
result.add src
lastNonemptyPos = result.len
elif src.len > indent:
result.add src[indent..^1]
lastNonemptyPos = result.len
result.setLen lastNonemptyPos
proc renderNimCode*(result: var string, code: string, isLatex = false) =
var toknizr: GeneralTokenizer
initGeneralTokenizer(toknizr, code)
var buf = ""
template append(kind, val) =
buf.setLen 0
buf.addEscaped(val)
let class = tokenClassToStr[kind]
if isLatex:
result.addf "\\span$1{$2}", [class, buf]
else:
result.addf "<span class=\"$1\">$2</span>", [class, buf]
while true:
getNextToken(toknizr, langNim)
case toknizr.kind
of gtEof: break # End Of File (or string)
else:
# TODO: avoid alloc; maybe toOpenArray
append(toknizr.kind, substr(code, toknizr.start, toknizr.length + toknizr.start - 1))

View File

@@ -1,6 +1,6 @@
import
intsets, ast, idents, algorithm, renderer, os, strutils,
intsets, ast, idents, algorithm, renderer, strutils,
msgs, modulegraphs, syntaxes, options, modulepaths,
lineinfos
@@ -100,38 +100,15 @@ proc computeDeps(cache: IdentCache; n: PNode, declares, uses: var IntSet; topLev
for i in 0..<n.len: computeDeps(cache, n[i], declares, uses, topLevel)
of nkPragma:
let a = n[0]
if a.kind == nkExprColonExpr and a[0].kind == nkIdent and
a[0].ident.s == "pragma":
# user defined pragma
decl(a[1])
if a.kind == nkExprColonExpr and a[0].kind == nkIdent and a[0].ident.s == "pragma":
# user defined pragma
decl(a[1])
else:
for i in 0..<n.safeLen: deps(n[i])
of nkMixinStmt, nkBindStmt: discard
else:
for i in 0..<n.safeLen: deps(n[i])
proc cleanPath(s: string): string =
# Here paths may have the form A / B or "A/B"
result = ""
for c in s:
if c != ' ' and c != '\"':
result.add c
proc joinPath(parts: seq[string]): string =
let nb = parts.len
assert nb > 0
if nb == 1:
return parts[0]
result = parts[0] / parts[1]
for i in 2..<parts.len:
result = result / parts[i]
proc getIncludePath(n: PNode, modulePath: string): string =
let istr = n.renderTree.cleanPath
let (pdir, _) = modulePath.splitPath
let p = istr.split('/').joinPath.addFileExt("nim")
result = pdir / p
proc hasIncludes(n:PNode): bool =
for a in n:
if a.kind == nkIncludeStmt:
@@ -210,42 +187,42 @@ proc mergeSections(conf: ConfigRef; comps: seq[seq[DepN]], res: PNode) =
sn.add dn.pnode[0]
res.add sn
else:
# Problematic circular dependency, we arrange the nodes into
# their original relative order and make sure to re-merge
# consecutive type and const sections
var wmsg = "Circular dependency detected. `codeReordering` pragma may not be able to" &
" reorder some nodes properely"
when defined(debugReorder):
wmsg &= ":\n"
for i in 0..<cs.len-1:
for j in i..<cs.len:
for ci in 0..<cs[i].kids.len:
if cs[i].kids[ci].id == cs[j].id:
wmsg &= "line " & $cs[i].pnode.info.line &
" depends on line " & $cs[j].pnode.info.line &
": " & cs[i].expls[ci] & "\n"
for j in 0..<cs.len-1:
for ci in 0..<cs[^1].kids.len:
if cs[^1].kids[ci].id == cs[j].id:
wmsg &= "line " & $cs[^1].pnode.info.line &
" depends on line " & $cs[j].pnode.info.line &
": " & cs[^1].expls[ci] & "\n"
message(conf, cs[0].pnode.info, warnUser, wmsg)
# Problematic circular dependency, we arrange the nodes into
# their original relative order and make sure to re-merge
# consecutive type and const sections
var wmsg = "Circular dependency detected. `codeReordering` pragma may not be able to" &
" reorder some nodes properely"
when defined(debugReorder):
wmsg &= ":\n"
for i in 0..<cs.len-1:
for j in i..<cs.len:
for ci in 0..<cs[i].kids.len:
if cs[i].kids[ci].id == cs[j].id:
wmsg &= "line " & $cs[i].pnode.info.line &
" depends on line " & $cs[j].pnode.info.line &
": " & cs[i].expls[ci] & "\n"
for j in 0..<cs.len-1:
for ci in 0..<cs[^1].kids.len:
if cs[^1].kids[ci].id == cs[j].id:
wmsg &= "line " & $cs[^1].pnode.info.line &
" depends on line " & $cs[j].pnode.info.line &
": " & cs[^1].expls[ci] & "\n"
message(conf, cs[0].pnode.info, warnUser, wmsg)
var i = 0
while i < cs.len:
if cs[i].pnode.kind in {nkTypeSection, nkConstSection}:
let ckind = cs[i].pnode.kind
var sn = newNode(ckind)
var i = 0
while i < cs.len:
if cs[i].pnode.kind in {nkTypeSection, nkConstSection}:
let ckind = cs[i].pnode.kind
var sn = newNode(ckind)
sn.add cs[i].pnode[0]
inc i
while i < cs.len and cs[i].pnode.kind == ckind:
sn.add cs[i].pnode[0]
inc i
while i < cs.len and cs[i].pnode.kind == ckind:
sn.add cs[i].pnode[0]
inc i
res.add sn
else:
res.add cs[i].pnode
inc i
res.add sn
else:
res.add cs[i].pnode
inc i
proc hasImportStmt(n: PNode): bool =
# Checks if the node is an import statement or
@@ -292,17 +269,17 @@ proc hasAccQuoted(n: PNode): bool =
if hasAccQuoted(a):
return true
const extandedProcDefs = procDefs + {nkMacroDef, nkTemplateDef}
const extendedProcDefs = procDefs + {nkMacroDef, nkTemplateDef}
proc hasAccQuotedDef(n: PNode): bool =
# Checks if the node is a function, macro, template ...
# with a quoted name or if it contains one
case n.kind
of extandedProcDefs:
of extendedProcDefs:
result = n[0].hasAccQuoted
of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse, nkStaticStmt:
for a in n:
if a.hasAccQuotedDef:
if hasAccQuotedDef(a):
return true
else:
result = false
@@ -318,7 +295,7 @@ proc hasBody(n: PNode): bool =
case n.kind
of nkCommand, nkCall:
result = true
of extandedProcDefs:
of extendedProcDefs:
result = n[^1].kind == nkStmtList
of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse, nkStaticStmt:
for a in n:
@@ -411,8 +388,7 @@ proc strongConnect(v: var DepN, idx: var int, s: var seq[DepN],
proc getStrongComponents(g: var DepG): seq[seq[DepN]] =
## Tarjan's algorithm. Performs a topological sort
## and detects strongly connected components.
result = newSeq[seq[DepN]]()
var s = newSeq[DepN]()
var s: seq[DepN]
var idx = 0
for v in g.mitems:
if v.idx < 0:
@@ -424,7 +400,7 @@ proc hasForbiddenPragma(n: PNode): bool =
for a in n:
if a.kind == nkPragma and a[0].kind == nkIdent and
a[0].ident.s == "push":
return true
return true
proc reorder*(graph: ModuleGraph, n: PNode, module: PSym): PNode =
if n.hasForbiddenPragma:

View File

@@ -917,6 +917,8 @@ proc loadNode*(g: ModuleGraph; module: PSym): PNode =
replay(g, module, result)
proc setupModuleCache*(g: ModuleGraph) =
# historical note: there used to be a `rodfiles` dir with special tests
# for incremental compilation via symbol files. This was likely replaced by ic.
if g.config.symbolFiles == disabledSf: return
g.recordStmt = recordStmt
let dbfile = getNimcacheDir(g.config) / RelativeFile"rodfiles.db"

View File

@@ -80,16 +80,14 @@ proc decodeStr*(s: cstring, pos: var int): string =
else: break
pos = i
const
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
{.push overflowChecks: off.}
# since negative numbers require a leading '-' they use up 1 byte. Thus we
# subtract/add `vintDelta` here to save space for small negative numbers
# which are common in ROD files:
const
vintDelta = 5
const vintDelta = 5
template encodeIntImpl(self) =
var d: char

View File

@@ -15,33 +15,33 @@ proc `|+|`*(a, b: BiggestInt): BiggestInt =
if (result xor a) >= 0'i64 or (result xor b) >= 0'i64:
return result
if a < 0 or b < 0:
result = low(result)
result = low(typeof(result))
else:
result = high(result)
result = high(typeof(result))
proc `|-|`*(a, b: BiggestInt): BiggestInt =
result = a -% b
if (result xor a) >= 0'i64 or (result xor not b) >= 0'i64:
return result
if b > 0:
result = low(result)
result = low(typeof(result))
else:
result = high(result)
result = high(typeof(result))
proc `|abs|`*(a: BiggestInt): BiggestInt =
if a != low(a):
if a != low(typeof(a)):
if a >= 0: result = a
else: result = -a
else:
result = low(a)
result = low(typeof(a))
proc `|div|`*(a, b: BiggestInt): BiggestInt =
# (0..5) div (0..4) == (0..5) div (1..4) == (0 div 4)..(5 div 1)
if b == 0'i64:
# make the same as ``div 1``:
result = a
elif a == low(a) and b == -1'i64:
result = high(result)
elif a == low(typeof(a)) and b == -1'i64:
result = high(typeof(result))
else:
result = a div b
@@ -74,6 +74,6 @@ proc `|*|`*(a, b: BiggestInt): BiggestInt =
return result
if floatProd >= 0.0:
result = high(result)
result = high(typeof(result))
else:
result = low(result)
result = low(typeof(result))

View File

@@ -228,11 +228,14 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
# watch out, "newruntime" can be set within NimScript itself and then we need
# to remember this:
if conf.selectedGC == gcUnselected:
conf.selectedGC = oldSelectedGC
if optOwnedRefs in oldGlobalOptions:
conf.globalOptions.incl {optTinyRtti, optOwnedRefs, optSeqDestructors}
defineSymbol(conf.symbols, "nimv2")
if conf.selectedGC == gcUnselected:
conf.selectedGC = oldSelectedGC
if conf.selectedGC in {gcArc, gcOrc}:
conf.globalOptions.incl {optTinyRtti, optSeqDestructors}
defineSymbol(conf.symbols, "nimv2")
# ensure we load 'system.nim' again for the real non-config stuff!
resetSystemArtifacts(graph)

View File

@@ -16,7 +16,8 @@ import
procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch,
intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
lowerings, plugins/active, rod, lineinfos, strtabs, int128
lowerings, plugins/active, rod, lineinfos, strtabs, int128,
isolation_check, typeallowed
from modulegraphs import ModuleGraph, PPassContext, onUse, onDef, onDefResolveForward
@@ -197,15 +198,13 @@ proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
suggestDecl(c, n, result)
proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLowerAscii
# like newSymS, but considers gensym'ed symbols
if n.kind == nkSym:
# and sfGenSym in n.sym.flags:
result = n.sym
if result.kind notin {kind, skTemp}:
localError(c.config, n.info, "cannot use symbol of kind '" &
$result.kind & "' as a '" & $kind & "'")
localError(c.config, n.info, "cannot use symbol of kind '$1' as a '$2'" %
[result.kind.toHumanStr, kind.toHumanStr])
when false:
if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}:
# declarative context, so produce a fresh gensym:
@@ -229,20 +228,22 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
allowed: TSymFlags): PSym
proc typeAllowedCheck(conf: ConfigRef; info: TLineInfo; typ: PType; kind: TSymKind;
proc typeAllowedCheck(c: PContext; info: TLineInfo; typ: PType; kind: TSymKind;
flags: TTypeAllowedFlags = {}) =
let t = typeAllowed(typ, kind, flags)
let t = typeAllowed(typ, kind, c, flags)
if t != nil:
var err: string
if t == typ:
localError(conf, info, "invalid type: '" & typeToString(typ) &
"' for " & substr($kind, 2).toLowerAscii)
err = "invalid type: '$1' for $2" % [typeToString(typ), toHumanStr(kind)]
if kind in {skVar, skLet, skConst} and taIsTemplateOrMacro in flags:
err &= ". Did you mean to call the $1 with '()'?" % [toHumanStr(typ.owner.kind)]
else:
localError(conf, info, "invalid type: '" & typeToString(t) &
"' in this context: '" & typeToString(typ) &
"' for " & substr($kind, 2).toLowerAscii)
err = "invalid type: '$1' in this context: '$2' for $3" % [typeToString(t),
typeToString(typ), toHumanStr(kind)]
localError(c.config, info, err)
proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
typeAllowedCheck(c.config, typ.n.info, typ, skProc)
typeAllowedCheck(c, typ.n.info, typ, skProc)
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
@@ -323,7 +324,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
let oldErrorOutputs = c.config.m.errorOutputs
c.config.m.errorOutputs = {}
c.config.errorMax = high(int)
c.config.errorMax = high(int) # `setErrorMaxHighMaybe` not appropriate here
try:
result = evalConstExpr(c.module, c.graph, e)
@@ -377,14 +378,15 @@ proc semExprFlagDispatched(c: PContext, n: PNode, flags: TExprFlags): PNode =
evaluated = evalAtCompileTime(c, result)
if evaluated != nil: return evaluated
when not defined(nimHasSinkInference):
{.pragma: nosinks.}
include hlo, seminst, semcall
when false:
# hopefully not required:
proc resetSemFlag(n: PNode) =
excl n.flags, nfSem
for i in 0..<n.safeLen:
resetSemFlag(n[i])
proc resetSemFlag(n: PNode) =
excl n.flags, nfSem
for i in 0..<n.safeLen:
resetSemFlag(n[i])
proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
s: PSym, flags: TExprFlags): PNode =
@@ -399,8 +401,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
c.friendModules.add(s.owner.getModule)
idSynchronizationPoint(5000)
result = macroResult
excl(result.flags, nfSem)
#resetSemFlag n
resetSemFlag result
if s.typ[0] == nil:
result = semStmt(c, result, flags)
else:
@@ -468,7 +469,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
#if c.evalContext == nil:
# c.evalContext = c.createEvalContext(emStatic)
result = evalMacroCall(c.module, c.graph, n, nOrig, sym)
result = evalMacroCall(c.module, c.graph, c.templInstCounter, n, nOrig, sym)
if efNoSemCheck notin flags:
result = semAfterMacroCall(c, n, result, sym, flags)
if c.config.macrosToExpand.hasKey(sym.name.s):
@@ -481,15 +482,10 @@ proc forceBool(c: PContext, n: PNode): PNode =
if result == nil: result = n
proc semConstBoolExpr(c: PContext, n: PNode): PNode =
let nn = semExprWithType(c, n)
result = fitNode(c, getSysType(c.graph, n.info, tyBool), nn, nn.info)
if result == nil:
result = forceBool(c, semConstExpr(c, n))
if result.kind != nkIntLit:
localError(c.config, n.info, errConstExprExpected)
return nn
result = getConstExpr(c.module, result, c.graph)
if result == nil:
localError(c.config, n.info, errConstExprExpected)
result = nn
proc semGenericStmt(c: PContext, n: PNode): PNode
proc semConceptBody(c: PContext, n: PNode): PNode
@@ -506,7 +502,7 @@ proc addCodeForGenerics(c: PContext, n: PNode) =
n.add prc.ast
c.lastGenericIdx = c.generics.len
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} =
var c = newContext(graph, module)
if c.p != nil: internalError(graph.config, module.info, "sem.myOpen")
c.semConstExpr = semConstExpr
@@ -522,6 +518,7 @@ proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
c.semTypeNode = semTypeNode
c.instTypeBoundOp = sigmatch.instTypeBoundOp
c.hasUnresolvedArgs = hasUnresolvedArgs
c.templInstCounter = new int
pushProcCon(c, module)
pushOwner(c, c.module)
@@ -597,7 +594,7 @@ proc recoverContext(c: PContext) =
while getCurrOwner(c).kind != skModule: popOwner(c)
while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
proc myProcess(context: PPassContext, n: PNode): PNode =
proc myProcess(context: PPassContext, n: PNode): PNode {.nosinks.} =
var c = PContext(context)
# no need for an expensive 'try' if we stop after the first error anyway:
if c.config.errorMax <= 1:

View File

@@ -94,10 +94,6 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
if c.currentScope.symbols.counter == counterInitial or syms.len != 0:
matches(c, n, orig, z)
if z.state == csMatch:
#if sym.name.s == "==" and (n.info ?? "temp3"):
# echo typeToString(sym.typ)
# writeMatches(z)
# little hack so that iterators are preferred over everything else:
if sym.kind == skIterator: inc(z.exactMatches, 200)
case best.state
@@ -234,6 +230,9 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
doAssert err.firstMismatch.formal != nil
candidates.add("\n required type for " & nameParam & ": ")
candidates.add typeToString(wanted)
when false:
if wanted.sym != nil:
candidates.add "(" & (c.config $ wanted.sym.info) & ")"
candidates.add "\n but expression '"
if err.firstMismatch.kind == kVarNeeded:
candidates.add renderNotLValue(nArg)
@@ -243,6 +242,10 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
candidates.add "' is of type: "
var got = nArg.typ
candidates.add typeToString(got)
when false:
if got.sym != nil:
candidates.add "(" & (c.config $ got.sym.info) & ")"
doAssert wanted != nil
if got != nil: effectProblem(wanted, got, candidates, c)
of kUnknown: discard "do not break 'nim check'"
@@ -327,7 +330,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
var typeHint = ""
if sym == nil:
# Perhaps we're in a `compiles(foo.bar)` expression, or
# in a concept, eg:
# in a concept, e.g.:
# ExplainedConcept {.explain.} = concept x
# x.foo is int
# We could use: `(c.config $ n[1].info)` to get more context.
@@ -499,9 +502,14 @@ proc updateDefaultParams(call: PNode) =
proc getCallLineInfo(n: PNode): TLineInfo =
case n.kind
of nkAccQuoted, nkBracketExpr, nkCall, nkCallStrLit, nkCommand:
getCallLineInfo(n[0])
of nkDotExpr: getCallLineInfo(n[1])
else: n.info
if len(n) > 0:
return getCallLineInfo(n[0])
of nkDotExpr:
if len(n) > 1:
return getCallLineInfo(n[1])
else:
discard
result = n.info
proc semResolvedCall(c: PContext, x: TCandidate,
n: PNode, flags: TExprFlags): PNode =
@@ -531,7 +539,10 @@ proc semResolvedCall(c: PContext, x: TCandidate,
for s in instantiateGenericParamList(c, gp, x.bindings):
case s.kind
of skConst:
x.call.add s.ast
if not s.ast.isNil:
x.call.add s.ast
else:
x.call.add c.graph.emptyNode
of skType:
x.call.add newSymNode(s, n.info)
else:
@@ -553,7 +564,7 @@ proc tryDeref(n: PNode): PNode =
result.add n
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
filter: TSymKinds, flags: TExprFlags): PNode =
filter: TSymKinds, flags: TExprFlags): PNode {.nosinks.} =
var errors: CandidateErrors = @[] # if efExplain in flags: @[] else: nil
var r = resolveOverloads(c, n, nOrig, filter, flags, errors, efExplain in flags)
if r.state == csMatch:
@@ -637,7 +648,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
if s.ast[genericParamsPos].safeLen != n.len-1:
let expected = s.ast[genericParamsPos].safeLen
localError(c.config, getCallLineInfo(n), errGenerated, "cannot instantiate: '" & renderTree(n) &
"'; got " & $(n.len-1) & " type(s) but expected " & $expected)
"'; got " & $(n.len-1) & " typeof(s) but expected " & $expected)
return n
result = explicitGenericSym(c, n, s)
if result == nil: result = explicitGenericInstError(c, n)
@@ -677,13 +688,14 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
if t.kind == tyDistinct or param.typ.kind == tyDistinct: hasDistinct = true
var x: PType
if param.typ.kind == tyVar:
x = newTypeS(tyVar, c)
x = newTypeS(param.typ.kind, c)
x.addSonSkipIntLit t.baseOfDistinct
else:
x = t.baseOfDistinct
call.add(newNodeIT(nkEmpty, fn.info, x))
if hasDistinct:
var resolved = semOverloadedCall(c, call, call, {fn.kind}, {})
let filter = if fn.kind in {skProc, skFunc}: {skProc, skFunc} else: {fn.kind}
var resolved = semOverloadedCall(c, call, call, filter, {})
if resolved != nil:
result = resolved[0].sym
if not compareTypes(result.typ[0], fn.typ[0], dcEqIgnoreDistinct):

View File

@@ -21,11 +21,12 @@ type
notes*: TNoteKinds
features*: set[Feature]
otherPragmas*: PNode # every pragma can be pushed
warningAsErrors*: TNoteKinds
POptionEntry* = ref TOptionEntry
PProcCon* = ref TProcCon
TProcCon* = object # procedure context; also used for top-level
# statements
TProcCon* {.acyclic.} = object # procedure context; also used for top-level
# statements
owner*: PSym # the symbol this context belongs to
resultSym*: PSym # the result symbol (if we are in a proc)
selfSym*: PSym # the 'self' symbol (if available)
@@ -34,7 +35,6 @@ type
inTryStmt*: int # whether we are in a try statement; works also
# in standalone ``except`` and ``finally``
next*: PProcCon # used for stacking procedure contexts
wasForwarded*: bool # whether the current proc has a separate header
mappingExists*: bool
mapping*: TIdTable
caseContext*: seq[tuple[n: PNode, idx: int]]
@@ -85,6 +85,7 @@ type
# this is used so that generic instantiations
# can access private object fields
instCounter*: int # to prevent endless instantiations
templInstCounter*: ref int # gives every template instantiation a unique id
ambiguousSymbols*: IntSet # ids of all ambiguous symbols (cannot
# store this info in the syms themselves!)
@@ -143,6 +144,7 @@ type
# would otherwise fail.
unusedImports*: seq[(PSym, TLineInfo)]
exportIndirections*: HashSet[(int, int)]
lastTLineInfo*: TLineInfo
template config*(c: PContext): ConfigRef = c.graph.config
@@ -211,9 +213,10 @@ proc considerGenSyms*(c: PContext; n: PNode) =
proc newOptionEntry*(conf: ConfigRef): POptionEntry =
new(result)
result.options = conf.options
result.defaultCC = ccDefault
result.defaultCC = ccNimCall
result.dynlib = nil
result.notes = conf.notes
result.warningAsErrors = conf.warningAsErrors
proc pushOptionEntry*(c: PContext): POptionEntry =
new(result)
@@ -222,12 +225,14 @@ proc pushOptionEntry*(c: PContext): POptionEntry =
result.defaultCC = prev.defaultCC
result.dynlib = prev.dynlib
result.notes = c.config.notes
result.warningAsErrors = c.config.warningAsErrors
result.features = c.features
c.optionStack.add(result)
proc popOptionEntry*(c: PContext) =
c.config.options = c.optionStack[^1].options
c.config.notes = c.optionStack[^1].notes
c.config.warningAsErrors = c.optionStack[^1].warningAsErrors
c.features = c.optionStack[^1].features
c.optionStack.setLen(c.optionStack.len - 1)
@@ -318,7 +323,8 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
let typedesc = newTypeS(tyTypeDesc, c)
incl typedesc.flags, tfCheckedForDestructor
typedesc.addSonSkipIntLit(assertNotNil(c.config, typ))
internalAssert(c.config, typ != nil)
typedesc.addSonSkipIntLit(typ)
let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info,
c.config.options).linkTo(typedesc)
return newSymNode(sym, info)
@@ -376,8 +382,7 @@ proc makeNotType*(c: PContext, t1: PType): PType =
result.flags.incl tfHasMeta
proc nMinusOne(c: PContext; n: PNode): PNode =
result = newNode(nkCall, n.info, @[
newSymNode(getSysMagic(c.graph, n.info, "pred", mPred)), n])
result = newTreeI(nkCall, n.info, newSymNode(getSysMagic(c.graph, n.info, "pred", mPred)), n)
# Remember to fix the procs below this one when you make changes!
proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
@@ -386,9 +391,8 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
result.sons = @[intType]
if n.typ != nil and n.typ.n == nil:
result.flags.incl tfUnresolved
result.n = newNode(nkRange, n.info, @[
newIntTypeNode(0, intType),
makeStaticExpr(c, nMinusOne(c, n))])
result.n = newTreeI(nkRange, n.info, newIntTypeNode(0, intType),
makeStaticExpr(c, nMinusOne(c, n)))
template rangeHasUnresolvedStatic*(t: PType): bool =
tfUnresolved in t.flags

View File

@@ -33,7 +33,7 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
# 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, c.cache, efFromHlo in flags)
result = evalTemplate(n, s, getCurrOwner(c), c.config, c.cache, c.templInstCounter, efFromHlo in flags)
if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags)
popInfoContext(c.config)
@@ -62,12 +62,18 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
renderTree(result, {renderNoComments}))
result.typ = errorType(c)
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
proc semExprCheck(c: PContext, n: PNode, flags: TExprFlags): PNode =
rejectEmptyNode(n)
result = semExpr(c, n, flags+{efWantValue})
if result.kind == nkEmpty:
# bug #12741, redundant error messages are the lesser evil here:
localError(c.config, n.info, errExprXHasNoType %
renderTree(result, {renderNoComments}))
# do not produce another redundant error message:
result = errorNode(c, n)
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semExprCheck(c, n, flags)
if result.typ == nil or result.typ == c.enforceVoidContext:
localError(c.config, n.info, errExprXHasNoType %
renderTree(result, {renderNoComments}))
@@ -76,11 +82,7 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
rejectEmptyNode(n)
result = semExpr(c, n, flags+{efWantValue})
if result.kind == nkEmpty:
# do not produce another redundant error message:
result = errorNode(c, n)
result = semExprCheck(c, n, flags)
if result.typ == nil:
localError(c.config, n.info, errExprXHasNoType %
renderTree(result, {renderNoComments}))
@@ -176,7 +178,7 @@ proc checkConvertible(c: PContext, targetTyp: PType, src: PNode): TConvStatus =
else:
discard
proc isCastable(conf: ConfigRef; dst, src: PType): bool =
proc isCastable(c: PContext; dst, src: PType): bool =
## Checks whether the source type can be cast to the destination type.
## Casting is very unrestrictive; casts are allowed as long as
## castDest.size >= src.size, and typeAllowed(dst, skParam)
@@ -189,6 +191,14 @@ proc isCastable(conf: ConfigRef; dst, src: PType): bool =
return false
if skipTypes(src, abstractInst-{tyTypeDesc}).kind == tyTypeDesc:
return false
if skipTypes(dst, abstractInst).kind == tyBuiltInTypeClass:
return false
let conf = c.config
if conf.selectedGC in {gcArc, gcOrc}:
let d = skipTypes(dst, abstractInst)
let s = skipTypes(src, abstractInst)
if d.kind == tyRef and s.kind == tyRef and s[0].isFinal != d[0].isFinal:
return false
var dstSize, srcSize: BiggestInt
dstSize = computeSize(conf, dst)
@@ -201,7 +211,7 @@ proc isCastable(conf: ConfigRef; dst, src: PType): bool =
result = false
elif srcSize < 0:
result = false
elif typeAllowed(dst, skParam) != nil:
elif typeAllowed(dst, skParam, c) != nil:
result = false
elif dst.kind == tyProc and dst.callConv == ccClosure:
result = src.kind == tyProc and src.callConv == ccClosure
@@ -329,7 +339,7 @@ proc semCast(c: PContext, n: PNode): PNode =
let castedExpr = semExprWithType(c, n[1])
if tfHasMeta in targetType.flags:
localError(c.config, n[0].info, "cannot cast to a non concrete type: '$1'" % $targetType)
if not isCastable(c.config, targetType, castedExpr.typ):
if not isCastable(c, targetType, castedExpr.typ):
let tar = $targetType
let alt = typeToString(targetType, preferDesc)
let msg = if tar != alt: tar & "=" & alt else: tar
@@ -421,7 +431,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
m.diagnostics = @[]
m.diagnosticsEnabled = true
res = typeRel(m, t2, t1) >= isSubtype # isNone
# `res = sameType(t1, t2)` would be wrong, eg for `int is (int|float)`
# `res = sameType(t1, t2)` would be wrong, e.g. for `int is (int|float)`
result = newIntNode(nkIntLit, ord(res))
result.typ = n.typ
@@ -622,11 +632,12 @@ proc isAssignable(c: PContext, n: PNode; isUnsafeAddr=false): TAssignableResult
result = parampatterns.isAssignable(c.p.owner, n, isUnsafeAddr)
proc isUnresolvedSym(s: PSym): bool =
return s.kind == skGenericParam or
tfInferrableStatic in s.typ.flags or
(s.kind == skParam and s.typ.isMetaType) or
(s.kind == skType and
s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} != {})
result = s.kind == skGenericParam
if not result and s.typ != nil:
result = tfInferrableStatic in s.typ.flags or
(s.kind == skParam and s.typ.isMetaType) or
(s.kind == skType and
s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} != {})
proc hasUnresolvedArgs(c: PContext, n: PNode): bool =
# Checks whether an expression depends on generic parameters that
@@ -652,7 +663,7 @@ proc hasUnresolvedArgs(c: PContext, n: PNode): bool =
return false
proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
if n.kind == nkHiddenDeref and not (c.config.cmd == cmdCompileToCpp or
if n.kind == nkHiddenDeref and not (c.config.backend == backendCpp or
sfCompileToCpp in c.module.flags):
checkSonsLen(n, 1, c.config)
result = n[0]
@@ -704,7 +715,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
# note sometimes this is eval'ed twice so we check for nkHiddenAddr here:
for i in 1..<n.len:
if i < t.len and t[i] != nil and
skipTypes(t[i], abstractInst-{tyTypeDesc}).kind == tyVar:
skipTypes(t[i], abstractInst-{tyTypeDesc}).kind in {tyVar}:
let it = n[i]
if isAssignable(c, it) notin {arLValue, arLocalLValue}:
if it.kind != nkHiddenAddr:
@@ -725,7 +736,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
# calls and then they wouldn't be analysed otherwise
analyseIfAddressTakenInCall(c, n[i])
if i < t.len and
skipTypes(t[i], abstractInst-{tyTypeDesc}).kind == tyVar:
skipTypes(t[i], abstractInst-{tyTypeDesc}).kind in {tyVar}:
if n[i].kind != nkHiddenAddr:
n[i] = analyseIfAddressTaken(c, n[i])
@@ -784,7 +795,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
if callee.kind notin {skProc, skFunc, skConverter, skConst} or callee.isGenericRoutine:
return
if n.typ != nil and typeAllowed(n.typ, skConst) != nil: return
if n.typ != nil and typeAllowed(n.typ, skConst, c) != nil: return
var call = newNodeIT(nkCall, n.info, n.typ)
call.add(n[0])
@@ -945,8 +956,17 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
hasErrorType = true
break
if not hasErrorType:
let typ = n[0].typ
msg.add(">\nbut expected one of: \n" &
typeToString(n[0].typ))
typeToString(typ))
# prefer notin preferToResolveSymbols
# t.sym != nil
# sfAnon notin t.sym.flags
# t.kind != tySequence(It is tyProc)
if typ.sym != nil and sfAnon notin typ.sym.flags and
typ.kind == tyProc:
msg.add(" = " &
typeToString(typ, preferDesc))
localError(c.config, n.info, msg)
return errorNode(c, n)
result = nil
@@ -1184,17 +1204,6 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
elif sfGenSym in s.flags:
# the owner should have been set by now by addParamOrResult
internalAssert c.config, s.owner != nil
if c.p.wasForwarded:
# gensym'ed parameters that nevertheless have been forward declared
# need a special fixup:
let realParam = c.p.owner.typ.n[s.position+1]
internalAssert c.config, realParam.kind == nkSym and realParam.sym.kind == skParam
return newSymNode(c.p.owner.typ.n[s.position+1].sym, n.info)
elif c.p.owner.kind == skMacro:
# gensym'ed macro parameters need a similar hack (see bug #1944):
var u = searchInScopes(c, s.name)
internalAssert c.config, u != nil and u.kind == skParam and u.owner == s.owner
return newSymNode(u, n.info)
result = newSymNode(s, n.info)
of skVar, skLet, skResult, skForVar:
if s.magic == mNimvm:
@@ -1266,6 +1275,54 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
onUse(info, s)
result = newSymNode(s, info)
proc tryReadingGenericParam(c: PContext, n: PNode, i: PIdent, t: PType): PNode =
case t.kind
of tyTypeParamsHolders:
result = readTypeParameter(c, t, i, n.info)
if result == c.graph.emptyNode:
result = n
n.typ = makeTypeFromExpr(c, n.copyTree)
of tyUserTypeClasses:
if t.isResolvedUserTypeClass:
result = readTypeParameter(c, t, i, n.info)
else:
n.typ = makeTypeFromExpr(c, copyTree(n))
result = n
of tyGenericParam, tyAnything:
n.typ = makeTypeFromExpr(c, copyTree(n))
result = n
else:
discard
proc tryReadingTypeField(c: PContext, n: PNode, i: PIdent, ty: PType): PNode =
var ty = ty.skipTypes(tyDotOpTransparent)
case ty.kind
of tyEnum:
# look up if the identifier belongs to the enum:
var f = PSym(nil)
while ty != nil:
f = getSymFromList(ty.n, i)
if f != nil: break
ty = ty.sons[0] # enum inheritance
if f != nil:
result = newSymNode(f)
result.info = n.info
result.typ = ty
markUsed(c, n.info, f)
onUse(n.info, f)
of tyObject, tyTuple:
if ty.n != nil and ty.n.kind == nkRecList:
let field = lookupInRecord(ty.n, i)
if field != nil:
n.typ = makeTypeDesc(c, field.typ)
result = n
of tyGenericInst:
result = tryReadingTypeField(c, n, i, ty.lastSon)
if result == nil:
result = tryReadingGenericParam(c, n, i, ty)
else:
result = tryReadingGenericParam(c, n, i, ty)
proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
## returns nil if it's not a built-in field access
checkSonsLen(n, 2, c.config)
@@ -1296,28 +1353,6 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
var f: PSym = nil
result = nil
template tryReadingGenericParam(t: PType) =
case t.kind
of tyTypeParamsHolders:
result = readTypeParameter(c, t, i, n.info)
if result == c.graph.emptyNode:
result = n
n.typ = makeTypeFromExpr(c, n.copyTree)
return
of tyUserTypeClasses:
if t.isResolvedUserTypeClass:
return readTypeParameter(c, t, i, n.info)
else:
n.typ = makeTypeFromExpr(c, copyTree(n))
return n
of tyGenericParam, tyAnything:
n.typ = makeTypeFromExpr(c, copyTree(n))
return n
else:
discard
var argIsType = false
if ty.kind == tyTypeDesc:
if ty.base.kind == tyNone:
# This is a still unresolved typedesc parameter.
@@ -1330,40 +1365,10 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
else:
return nil
else:
ty = ty.base
argIsType = true
else:
argIsType = isTypeExpr(n[0])
return tryReadingTypeField(c, n, i, ty.base)
elif isTypeExpr(n.sons[0]):
return tryReadingTypeField(c, n, i, ty)
if argIsType:
ty = ty.skipTypes(tyDotOpTransparent)
case ty.kind
of tyEnum:
# look up if the identifier belongs to the enum:
while ty != nil:
f = getSymFromList(ty.n, i)
if f != nil: break
ty = ty[0] # enum inheritance
if f != nil:
result = newSymNode(f)
result.info = n.info
result.typ = ty
markUsed(c, n.info, f)
onUse(n.info, f)
return
of tyObject, tyTuple:
if ty.n != nil and ty.n.kind == nkRecList:
let field = lookupInRecord(ty.n, i)
if field != nil:
n.typ = makeTypeDesc(c, field.typ)
return n
else:
tryReadingGenericParam(ty)
return
# XXX: This is probably not relevant any more
# reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
ty = n[0].typ
return nil
if ty.kind in tyUserTypeClasses and ty.isResolvedUserTypeClass:
ty = ty.lastSon
ty = skipTypes(ty, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, tyOwned, tyAlias, tySink})
@@ -1407,7 +1412,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
# we didn't find any field, let's look for a generic param
if result == nil:
let t = n[0].typ.skipTypes(tyDotOpTransparent)
tryReadingGenericParam(t)
result = tryReadingGenericParam(c, n, i, t)
proc dotTransformation(c: PContext, n: PNode): PNode =
if isSymChoice(n[1]):
@@ -1555,10 +1560,9 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
# this is ugly. XXX Semantic checking should use the ``nfSem`` flag for
# nodes?
let aOrig = nOrig[0]
result = newNode(nkCall, n.info, sons = @[setterId, a[0],
semExprWithType(c, n[1])])
result = newTreeI(nkCall, n.info, setterId, a[0], semExprWithType(c, n[1]))
result.flags.incl nfDotSetter
let orig = newNode(nkCall, n.info, sons = @[setterId, aOrig[0], nOrig[1]])
let orig = newTreeI(nkCall, n.info, setterId, aOrig[0], nOrig[1])
result = semOverloadedCallAnalyseEffects(c, result, orig, {})
if result != nil:
@@ -1571,17 +1575,22 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
# return a view into the first argument (if there is one):
let root = exprRoot(n)
if root != nil and root.owner == c.p.owner:
template url: string = "var_t_return.html".createDocLink
if root.kind in {skLet, skVar, skTemp} and sfGlobal notin root.flags:
localError(c.config, n.info, "'$1' escapes its stack frame; context: '$2'; see $3/var_t_return.html" % [
root.name.s, renderTree(n, {renderNoComments}), explanationsBaseUrl])
localError(c.config, n.info, "'$1' escapes its stack frame; context: '$2'; see $3" % [
root.name.s, renderTree(n, {renderNoComments}), url])
elif root.kind == skParam and root.position != 0:
localError(c.config, n.info, "'$1' is not the first parameter; context: '$2'; see $3/var_t_return.html" % [
root.name.s, renderTree(n, {renderNoComments}), explanationsBaseUrl])
localError(c.config, n.info, "'$1' is not the first parameter; context: '$2'; see $3" % [
root.name.s, renderTree(n, {renderNoComments}), url])
case n.kind
of nkHiddenAddr, nkAddr: return n
of nkHiddenDeref, nkDerefExpr: return n[0]
of nkDerefExpr: return n[0]
of nkBracketExpr:
if n.len == 1: return n[0]
of nkHiddenDeref:
# issue #13848
# `proc fun(a: var int): var int = a`
discard
else: discard
let valid = isAssignable(c, n, isLent)
if valid != arLValue:
@@ -1595,7 +1604,7 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
if le.kind == nkHiddenDeref:
var x = le[0]
if x.typ.kind in {tyVar, tyLent} and x.kind == nkSym and x.sym.kind == skResult:
if (x.typ.kind in {tyVar, tyLent} or classifyViewType(x.typ) != noView) and x.kind == nkSym and x.sym.kind == skResult:
n[0] = x # 'result[]' --> 'result'
n[1] = takeImplicitAddr(c, ri, x.typ.kind == tyLent)
x.typ.flags.incl tfVarIsPtr
@@ -1705,9 +1714,9 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
var le = a.typ
if le == nil:
localError(c.config, a.info, "expression has no type")
elif (skipTypes(le, {tyGenericInst, tyAlias, tySink}).kind != tyVar and
isAssignable(c, a) in {arNone, arLentValue}) or
skipTypes(le, abstractVar).kind in {tyOpenArray, tyVarargs}:
elif (skipTypes(le, {tyGenericInst, tyAlias, tySink}).kind notin {tyVar} and
isAssignable(c, a) in {arNone, arLentValue}) or (
skipTypes(le, abstractVar).kind in {tyOpenArray, tyVarargs} and views notin c.features):
# Direct assignment to a discriminant is allowed!
localError(c.config, a.info, errXCannotBeAssignedTo %
renderTree(a, {renderNoComments}))
@@ -1727,7 +1736,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
if cmpTypes(c, lhs.typ, rhsTyp) in {isGeneric, isEqual}:
internalAssert c.config, c.p.resultSym != nil
# Make sure the type is valid for the result variable
typeAllowedCheck(c.config, n.info, rhsTyp, skResult)
typeAllowedCheck(c, n.info, rhsTyp, skResult)
lhs.typ = rhsTyp
c.p.resultSym.typ = rhsTyp
c.p.owner.typ[0] = rhsTyp
@@ -1748,17 +1757,21 @@ proc semReturn(c: PContext, n: PNode): PNode =
if c.p.owner.kind in {skConverter, skMethod, skProc, skFunc, skMacro} or
(not c.p.owner.typ.isNil and isClosureIterator(c.p.owner.typ)):
if n[0].kind != nkEmpty:
# transform ``return expr`` to ``result = expr; return``
if c.p.resultSym != nil:
if n[0].kind == nkAsgn and n[0][0].kind == nkSym and c.p.resultSym == n[0][0].sym:
discard "return is already transformed"
elif c.p.resultSym != nil:
# transform ``return expr`` to ``result = expr; return``
var a = newNodeI(nkAsgn, n[0].info)
a.add newSymNode(c.p.resultSym)
a.add n[0]
n[0] = semAsgn(c, a)
# optimize away ``result = result``:
if n[0][1].kind == nkSym and n[0][1].sym == c.p.resultSym:
n[0] = c.graph.emptyNode
n[0] = a
else:
localError(c.config, n.info, errNoReturnTypeDeclared)
return
result[0] = semAsgn(c, n[0])
# optimize away ``result = result``:
if result[0][1].kind == nkSym and result[0][1].sym == c.p.resultSym:
result[0] = c.graph.emptyNode
else:
localError(c.config, n.info, "'return' not allowed here")
@@ -1820,7 +1833,11 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
tupleConstr[i] = takeImplicitAddr(c, tupleConstr[i], e.kind == tyLent)
else:
localError(c.config, n[0].info, errXExpected, "tuple constructor")
else: discard
else:
when false:
# XXX investigate what we really need here.
if isViewType(t):
n[0] = takeImplicitAddr(c, n[0], false)
proc semYield(c: PContext, n: PNode): PNode =
result = n
@@ -1848,29 +1865,32 @@ proc semYield(c: PContext, n: PNode): PNode =
elif c.p.owner.typ[0] != nil:
localError(c.config, n.info, errGenerated, "yield statement must yield a value")
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
if onlyCurrentScope:
result = localSearchInScope(c, i)
else:
result = searchInScopes(c, i) # no need for stub loading
proc semDefined(c: PContext, n: PNode): PNode =
checkSonsLen(n, 2, c.config)
# we replace this node by a 'true' or 'false' node:
result = newIntNode(nkIntLit, 0)
result.intVal = ord isDefined(c.config, considerQuotedIdent(c, n[1], n).s)
result.info = n.info
result.typ = getSysType(c.graph, n.info, tyBool)
proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
proc lookUpForDeclared(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
case n.kind
of nkIdent:
result = lookUpForDefined(c, n.ident, onlyCurrentScope)
of nkIdent, nkAccQuoted:
result = if onlyCurrentScope:
localSearchInScope(c, considerQuotedIdent(c, n))
else:
searchInScopes(c, considerQuotedIdent(c, n))
of nkDotExpr:
result = nil
if onlyCurrentScope: return
checkSonsLen(n, 2, c.config)
var m = lookUpForDefined(c, n[0], onlyCurrentScope)
var m = lookUpForDeclared(c, n[0], onlyCurrentScope)
if m != nil and m.kind == skModule:
let ident = considerQuotedIdent(c, n[1], n)
if m == c.module:
result = strTableGet(c.topLevelScope.symbols, ident)
else:
result = strTableGet(m.tab, ident)
of nkAccQuoted:
result = lookUpForDefined(c, considerQuotedIdent(c, n), onlyCurrentScope)
of nkSym:
result = n.sym
of nkOpenSymChoice, nkClosedSymChoice:
@@ -1879,15 +1899,11 @@ proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
localError(c.config, n.info, "identifier expected, but got: " & renderTree(n))
result = nil
proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
proc semDeclared(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
checkSonsLen(n, 2, c.config)
# we replace this node by a 'true' or 'false' node:
result = newIntNode(nkIntLit, 0)
if not onlyCurrentScope and considerQuotedIdent(c, n[0], n).s == "defined":
let d = considerQuotedIdent(c, n[1], n)
result.intVal = ord isDefined(c.config, d.s)
elif lookUpForDefined(c, n[1], onlyCurrentScope) != nil:
result.intVal = 1
result.intVal = ord lookUpForDeclared(c, n[1], onlyCurrentScope) != nil
result.info = n.info
result.typ = getSysType(c.graph, n.info, tyBool)
@@ -2036,7 +2052,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
dummyTemplate[paramsPos].add getSysSym(c.graph, n.info, "untyped").newSymNode # return type
ids.add getSysSym(c.graph, n.info, "untyped").newSymNode # params type
ids.add c.graph.emptyNode # no default value
dummyTemplate[paramsPos].add newNode(nkIdentDefs, n.info, ids)
dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids)
var tmpl = semTemplateDef(c, dummyTemplate)
quotes[0] = tmpl[namePos]
@@ -2048,14 +2064,18 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
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, @[
quotes[1] = newTreeI(nkCall, n.info, identNode, newStrNode(nkStrLit, "result"))
result = newTreeI(nkCall, n.info,
createMagic(c.graph, "getAst", mExpandToAst).newSymNode,
newNode(nkCall, n.info, quotes)])
newTreeI(nkCall, n.info, quotes))
result = semExpandToAst(c, result)
proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# watch out, hacks ahead:
when defined(nimsuggest):
# Remove the error hook so nimsuggest doesn't report errors there
let tempHook = c.graph.config.structuredErrorHook
c.graph.config.structuredErrorHook = nil
let oldErrorCount = c.config.errorCounter
let oldErrorMax = c.config.errorMax
let oldCompilesId = c.compilesContextId
@@ -2064,8 +2084,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
if c.compilesContextId == 0:
inc c.compilesContextIdGenerator
c.compilesContextId = c.compilesContextIdGenerator
# do not halt after first error:
c.config.errorMax = high(int)
c.config.errorMax = high(int) # `setErrorMaxHighMaybe` not appropriate here
# open a scope for temporary symbol inclusions:
let oldScope = c.currentScope
@@ -2105,6 +2124,9 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
c.config.m.errorOutputs = oldErrorOutputs
c.config.errorCounter = oldErrorCount
c.config.errorMax = oldErrorMax
when defined(nimsuggest):
# Restore the error hook
c.graph.config.structuredErrorHook = tempHook
proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
# we replace this node by a 'true' or 'false' node:
@@ -2143,7 +2165,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.excl {sfCompilerProc, sfExportc, sfImportc}
result.loc.r = nil
proc setMs(n: PNode, s: PSym): PNode =
@@ -2175,10 +2197,13 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result = semTypeOf(c, n)
of mDefined:
markUsed(c, n.info, s)
result = semDefined(c, setMs(n, s), false)
of mDefinedInScope:
result = semDefined(c, setMs(n, s))
of mDeclared:
markUsed(c, n.info, s)
result = semDefined(c, setMs(n, s), true)
result = semDeclared(c, setMs(n, s), false)
of mDeclaredInScope:
markUsed(c, n.info, s)
result = semDeclared(c, setMs(n, s), true)
of mCompiles:
markUsed(c, n.info, s)
result = semCompiles(c, setMs(n, s), flags)
@@ -2565,6 +2590,43 @@ proc shouldBeBracketExpr(n: PNode): bool =
n[0] = be
return true
proc hoistParamsUsedInDefault(c: PContext, call, letSection, defExpr: var PNode) =
# This takes care of complicated signatures such as:
# proc foo(a: int, b = a)
# proc bar(a: int, b: int, c = a + b)
#
# The recursion may confuse you. It performs two duties:
#
# 1) extracting all referenced params from default expressions
# into a let section preceding the call
#
# 2) replacing the "references" within the default expression
# with these extracted skLet symbols.
#
# The first duty is carried out directly in the code here, while the second
# duty is activated by returning a non-nil value. The caller is responsible
# for replacing the input to the function with the returned non-nil value.
# (which is the hoisted symbol)
if defExpr.kind == nkSym and defExpr.sym.kind == skParam and defExpr.sym.owner == call[0].sym:
let paramPos = defExpr.sym.position + 1
if call[paramPos].kind != nkSym:
let hoistedVarSym = newSym(skLet, getIdent(c.graph.cache, genPrefix), c.p.owner, letSection.info, c.p.owner.options)
hoistedVarSym.typ = call[paramPos].typ
letSection.add newTreeI(nkIdentDefs, letSection.info,
newSymNode(hoistedVarSym),
newNodeI(nkEmpty, letSection.info),
call[paramPos])
call[paramPos] = newSymNode(hoistedVarSym) # Refer the original arg to its hoisted sym
# arg we refer to is a sym, wether introduced by hoisting or not doesn't matter, we simply reuse it
defExpr = call[paramPos]
else:
for i in 0..<defExpr.safeLen:
hoistParamsUsedInDefault(c, call, letSection, defExpr[i])
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
when defined(nimCompilerStackraceHints):
setFrameMsg c.config$n.info & " " & $n.kind
@@ -2693,6 +2755,15 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semDirectOp(c, n, flags)
else:
result = semIndirectOp(c, n, flags)
if nfDefaultRefsParam in result.flags:
result = result.copyTree #XXX: Figure out what causes default param nodes to be shared.. (sigmatch bug?)
# We've found a default value that references another param.
# See the notes in `hoistParamsUsedInDefault` for more details.
var hoistedParams = newNodeI(nkLetSection, result.info)
for i in 1..<result.len:
hoistParamsUsedInDefault(c, result, hoistedParams, result[i])
result = newTreeIT(nkStmtListExpr, result.info, result.typ, hoistedParams, result)
of nkWhen:
if efWantStmt in flags:
result = semWhen(c, n, true)

View File

@@ -475,15 +475,13 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
else:
localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
of nkBracket:
idx = idx - toInt64(firstOrd(g.config, x.typ))
idx -= toInt64(firstOrd(g.config, x.typ))
if idx >= 0 and idx < x.len: result = x[int(idx)]
else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
of nkStrLit..nkTripleStrLit:
result = newNodeIT(nkCharLit, x.info, n.typ)
if idx >= 0 and idx < x.strVal.len:
result.intVal = ord(x.strVal[int(idx)])
elif idx == x.strVal.len and optLaxStrings in g.config.options:
discard
else:
localError(g.config, n.info, formatErrorIndexBound(idx, x.strVal.len-1) & $n)
else: discard
@@ -549,9 +547,13 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
localError(g.config, s.info,
"{.intdefine.} const was set to an invalid integer: '" &
g.config.symbols[s.name.s] & "'")
else:
result = copyTree(s.ast)
of mStrDefine:
if isDefined(g.config, s.name.s):
result = newStrNodeT(g.config.symbols[s.name.s], n, g)
else:
result = copyTree(s.ast)
of mBoolDefine:
if isDefined(g.config, s.name.s):
try:
@@ -560,6 +562,8 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
localError(g.config, s.info,
"{.booldefine.} const was set to an invalid bool: '" &
g.config.symbols[s.name.s] & "'")
else:
result = copyTree(s.ast)
else:
result = copyTree(s.ast)
of skProc, skFunc, skMethod:
@@ -639,9 +643,9 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
discard
else:
result = magicCall(m, n, g)
except OverflowError:
except OverflowDefect:
localError(g.config, n.info, "over- or underflow")
except DivByZeroError:
except DivByZeroDefect:
localError(g.config, n.info, "division by zero")
of nkAddr:
var a = getConstExpr(m, n[0], g)

View File

@@ -28,7 +28,7 @@ proc getIdentNode(c: PContext; n: PNode): PNode =
type
GenericCtx = object
toMixin: IntSet
toMixin, toBind: IntSet
cursorInBody: bool # only for nimsuggest
bracketExpr: PNode
@@ -124,7 +124,7 @@ proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
if ident.id notin ctx.toMixin and withinMixin notin flags:
errorUndeclaredIdentifier(c, n.info, ident.s)
else:
if withinBind in flags:
if withinBind in flags or s.id in ctx.toBind:
result = symChoice(c, n, s, scClosed)
elif s.isMixedIn:
result = symChoice(c, n, s, scForceOpen)
@@ -155,7 +155,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
var s = searchInScopes(c, ident, routineKinds).skipAlias(n, c.config)
if s != nil:
isMacro = s.kind in {skTemplate, skMacro}
if withinBind in flags:
if withinBind in flags or s.id in ctx.toBind:
result = newDot(result, symChoice(c, n, s, scClosed))
elif s.isMixedIn:
result = newDot(result, symChoice(c, n, s, scForceOpen))
@@ -211,6 +211,8 @@ proc semGenericStmt(c: PContext, n: PNode,
result = semGenericStmt(c, n[0], flags+{withinBind}, ctx)
of nkMixinStmt:
result = semMixinStmt(c, n, ctx.toMixin)
of nkBindStmt:
result = semBindStmt(c, n, ctx.toBind)
of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit:
# check if it is an expression macro:
checkMinSonsLen(n, 1, c.config)
@@ -226,8 +228,11 @@ proc semGenericStmt(c: PContext, n: PNode,
var mixinContext = false
if s != nil:
incl(s.flags, sfUsed)
mixinContext = s.magic in {mDefined, mDefinedInScope, mCompiles, mAstToStr}
let sc = symChoice(c, fn, s, if s.isMixedIn: scForceOpen else: scOpen)
mixinContext = s.magic in {mDefined, mDeclared, mDeclaredInScope, mCompiles, mAstToStr}
let whichChoice = if s.id in ctx.toBind: scClosed
elif s.isMixedIn: scForceOpen
else: scOpen
let sc = symChoice(c, fn, s, whichChoice)
case s.kind
of skMacro:
if macroToExpand(s) and sc.safeLen <= 1:
@@ -260,7 +265,7 @@ proc semGenericStmt(c: PContext, n: PNode,
# We're not interested in the example code during this pass so let's
# skip it
if s.magic == mRunnableExamples:
inc first
first = result.safeLen # see trunnableexamples.fun3
of skGenericParam:
result[0] = newSymNodeTypeDesc(s, fn.info)
onUse(fn.info, s)
@@ -492,12 +497,14 @@ proc semGenericStmt(c: PContext, n: PNode,
proc semGenericStmt(c: PContext, n: PNode): PNode =
var ctx: GenericCtx
ctx.toMixin = initIntSet()
ctx.toBind = initIntSet()
result = semGenericStmt(c, n, {}, ctx)
semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody)
proc semConceptBody(c: PContext, n: PNode): PNode =
var ctx: GenericCtx
ctx.toMixin = initIntSet()
ctx.toBind = initIntSet()
result = semGenericStmt(c, n, {withinConcept}, ctx)
semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody)

View File

@@ -66,7 +66,7 @@ iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym
continue
let symKind = if q.typ.kind == tyStatic: skConst else: skType
var s = newSym(symKind, q.name, getCurrOwner(c), q.info)
s.flags = s.flags + {sfUsed, sfFromGeneric}
s.flags.incl {sfUsed, sfFromGeneric}
var t = PType(idTableGet(pt, q.typ))
if t == nil:
if tfRetType in q.typ.flags:
@@ -178,13 +178,13 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
internalAssert c.config, header.kind == tyGenericInvocation
var
typeMap: LayeredIdTable
cl: TReplTypeVars
initIdTable(cl.symMap)
initIdTable(cl.localCache)
initIdTable(typeMap.topLayer)
cl.typeMap = addr(typeMap)
cl.typeMap = LayeredIdTable()
initIdTable(cl.typeMap.topLayer)
cl.info = info
cl.c = c
cl.allowMetaTypes = allowMetaTypes
@@ -244,7 +244,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
#addDecl(c, prc)
pushInfoContext(c.config, info)
var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(c, addr(typeMap), info, nil)
var cl = initTypeVars(c, typeMap, info, nil)
var result = instCopyType(cl, prc.typ)
let originalParams = result.n
result.n = originalParams.shallowCopy
@@ -328,7 +328,7 @@ proc fillMixinScope(c: PContext) =
p = p.next
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym =
info: TLineInfo): PSym {.nosinks.} =
## Generates a new instance of a generic procedure.
## The `pt` parameter is a type-unsafe mapping table used to link generic
## parameters to their concrete types within the generic instance.

View File

@@ -42,9 +42,6 @@ type
proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode
proc skipAddr(n: PNode): PNode {.inline.} =
(if n.kind == nkHiddenAddr: n[0] else: n)
proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
result = newNodeI(nkBracketExpr, n.info)
for i in 1..<n.len: result.add(n[i])
@@ -402,14 +399,18 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym
# Replace nkDerefExpr by nkHiddenDeref
# nkDeref is for 'ref T': x[].field
# nkHiddenDeref is for 'var T': x<hidden deref [] here>.field
proc transform(n: PNode; old, fresh: PType; oldParam, newParam: PSym): PNode =
proc transform(procSym: PSym; n: PNode; old, fresh: PType; oldParam, newParam: PSym): PNode =
result = shallowCopy(n)
if sameTypeOrNil(n.typ, old):
result.typ = fresh
if n.kind == nkSym and n.sym == oldParam:
result.sym = newParam
if n.kind == nkSym:
if n.sym == oldParam:
result.sym = newParam
elif n.sym.owner == orig:
result.sym = copySym(n.sym)
result.sym.owner = procSym
for i in 0 ..< safeLen(n):
result[i] = transform(n[i], old, fresh, oldParam, newParam)
result[i] = transform(procSym, n[i], old, fresh, oldParam, newParam)
#if n.kind == nkDerefExpr and sameType(n[0].typ, old):
# result =
@@ -423,21 +424,35 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym
let newParam = newSym(skParam, oldParam.name, result, result.info)
newParam.typ = newParamType
# proc body:
result.ast = transform(orig.ast, origParamType, newParamType, oldParam, newParam)
result.ast = transform(result, orig.ast, origParamType, newParamType, oldParam, newParam)
# proc signature:
result.typ = newProcType(result.info, result)
result.typ.addParam newParam
proc semQuantifier(c: PContext; n: PNode): PNode =
checkMinSonsLen(n, 2, c.config)
checkSonsLen(n, 2, c.config)
openScope(c)
for i in 0..n.len-2:
let v = newSymS(skForVar, n[i], c)
styleCheckDef(c.config, v)
onDef(n.info, v)
n[i] = newSymNode(v)
addDecl(c, v)
n[^1] = forceBool(c, semExprWithType(c, n[^1]))
result = newNodeIT(n.kind, n.info, n.typ)
result.add n[0]
let args = n[1]
assert args.kind == nkArgList
for i in 0..args.len-2:
let it = args[i]
var valid = false
if it.kind == nkInfix:
let op = considerQuotedIdent(c, it[0])
if op.id == ord(wIn):
let v = newSymS(skForVar, it[1], c)
styleCheckDef(c.config, v)
onDef(it[1].info, v)
let domain = semExprWithType(c, it[2], {efWantIterator})
v.typ = domain.typ
valid = true
addDecl(c, v)
result.add newTree(nkInfix, it[0], newSymNode(v), domain)
if not valid:
localError(c.config, n.info, "<quantifier> 'in' <range> expected")
result.add forceBool(c, semExprWithType(c, args[^1]))
closeScope(c)
proc semOld(c: PContext; n: PNode): PNode =
@@ -512,14 +527,24 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
if n[^1].kind == nkSym and n[^1].sym.kind notin {skProc, skFunc}:
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
elif optTinyRtti in c.config.globalOptions:
let fin = if n[^1].kind == nkLambda: n[^1][namePos].sym
else: n[^1].sym
# check if we converted this finalizer into a destructor already:
let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef}))
if t != nil and t.attachedOps[attachedDestructor] != nil and t.attachedOps[attachedDestructor].owner == fin:
discard "already turned this one into a finalizer"
else:
bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor)
let nfin = skipConvCastAndClosure(n[^1])
let fin = case nfin.kind
of nkSym: nfin.sym
of nkLambda, nkDo: nfin[namePos].sym
else:
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
nil
if fin != nil:
if fin.kind notin {skProc, skFunc}:
# calling convention is checked in codegen
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
# check if we converted this finalizer into a destructor already:
let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef}))
if t != nil and t.attachedOps[attachedDestructor] != nil and t.attachedOps[attachedDestructor].owner == fin:
discard "already turned this one into a finalizer"
else:
bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor)
result = n
of mDestroy:
result = n
@@ -545,10 +570,13 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
let constructed = result[1].typ.base
if constructed.requiresInit:
message(c.config, n.info, warnUnsafeDefault, typeToString(constructed))
of mIsolate:
if not checkIsolate(n[1]):
localError(c.config, n.info, "expression cannot be isolated: " & $n[1])
result = n
of mPred:
if n[1].typ.skipTypes(abstractInst).kind in {tyUInt..tyUInt64}:
n[0].sym.magic = mSubU
result = n
else:
result = n

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