Compare commits

...

125 Commits

Author SHA1 Message Date
narimiran
5a598a4945 update makefile.nimf 2026-05-22 09:57:47 +02:00
narimiran
5360d076f3 update actions' versions 2026-05-22 09:31:47 +02:00
Andreas Rumpf
71467ecd86 fixes DOS via malformed HTTP protocol (#25793)
refs https://github.com/nim-lang/Nim/pull/25568

(cherry picked from commit f0077a12b2)
2026-05-22 08:56:00 +02:00
narimiran
ec324ad073 disable failing pacakge 2024-07-09 13:45:16 +02:00
narimiran
9ce81868a8 Revert "fixes #9940; genericAssign does not take care of the importC variables in refc [backport] (#23761)"
This reverts commit fda43d1f0a.
2024-07-09 13:02:30 +02:00
narimiran
d993aff496 Revert "try to fix broken tests"
This reverts commit 786bbff1ae.
2024-07-09 13:02:19 +02:00
narimiran
786bbff1ae try to fix broken tests 2024-06-28 08:31:43 +02:00
ringabout
fda43d1f0a fixes #9940; genericAssign does not take care of the importC variables in refc [backport] (#23761)
fixes #9940

(cherry picked from commit 828cd58d8a)
2024-06-27 14:09:14 +02:00
ringabout
6789859503 Update nimsuggest.nim 2024-06-18 22:46:59 +08:00
Juan M Gómez
d9b1477b81 [Backport 1.6] Nimsuggest handle unknown file (#23702) 2024-06-10 17:14:08 +02:00
Giuliano Mega
3864066408 [Backport 1.6] Fix reset code gen for range types (#22462, #23214) (#23215) (#23638)
This is a backport of https://github.com/nim-lang/Nim/pull/23215. I
thought I'd put a PR instead of [just asking for
it](https://github.com/nim-lang/Nim/pull/23215#issuecomment-2125829028).
🙂
2024-05-23 11:30:15 +02:00
Juan M Gómez
53424c0036 [Backport 1.6] Skips generic owner when mangling instances (#23599) 2024-05-14 11:25:33 +02:00
Nikolay Nikolov
6a63df181f [backport v1.6.x] fixes the discVal register is used after free in vmgen (#22688) (#23553)
follow up https://github.com/nim-lang/Nim/pull/11955

(cherry picked from commit b1a8d6976f)

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2024-05-01 22:56:16 +02:00
bptato
b7b3f87719 Fix std/base64.decode out of bounds read (#23526)
inputLen may end up as 0 in the loop if the input string only includes
trailing characters. e.g. without the patch, decode(" ") would panic.

(cherry picked from commit 30cf570af9)
2024-04-23 06:58:18 +02:00
narimiran
8ebb4dc30a bump NimVersion to 1.6.21 2024-04-16 15:49:03 +02:00
Nikolay Nikolov
19fdbfc173 Converted the 'invalid kind for firstOrd/lastOrd(XXX)' messages from internal errors to fatal errors. (#23443) (#23447)
This fixes a nimsuggest crash when opening:
    beacon_chain/consensus_object_pools/blockchain_dag.nim
from the nimbus-eth2 project and many other .nim files (44 files, to be
precise) in the same project.

Replaces: https://github.com/nim-lang/Nim/pull/23402 (cherry picked from
commit c934d5986d)
2024-04-06 14:33:03 +02:00
narimiran
8f9fde0615 bump NimVersion to 1.6.20 2024-03-19 16:37:43 +01:00
Nikolay Nikolov
e6ee956845 fixes #22753; Nimsuggest segfault with invalid assignment to table (#22781) (#23314)
fixes #22753

## Future work
We should turn all the error nodes into nodes of a nkError kind, which
could be a industrious task. But perhaps we can add a special treatment
for error nodes to make the transition smooth.

(cherry picked from commit 642ac0c1c3)

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2024-03-14 18:35:25 +01:00
Juan M Gómez
afced7d9ab [Backport 1.6] When NimScript errors prevents NimSuggest from Init (#23348) 2024-03-03 17:36:34 +01:00
Nikolay Nikolov
51c86fdae7 * fixed nimsuggest crash when opening a .nim file, that contain a {.fatal: "msg".} pragma. (#23325) (#23329)
(cherry picked from commit 773c066634)
2024-02-24 07:40:47 +01:00
Juan M Gómez
d08bba579d [Backport 1.6] Itanium mangling scheme #23301 (#23302) 2024-02-13 08:08:46 +01:00
ringabout
ac1dc03258 fixes regression #23280; Operations on inline toOpenArray len return a wrong result (#23285)
fixes #23280

(cherry picked from commit 4b67cccf50)
2024-02-07 20:26:27 +01:00
Nikolay Nikolov
e8fe9275b5 + show the inferred exception list (as part of the type) for functions that don't have an explicit .raises pragma (#23193) (#23213)
(cherry picked from commit 18b5fb256d)
2024-01-16 15:36:36 +08:00
Juan M Gómez
0f97dd6fb3 backport nimsuggest info:capabilities (#23190) 2024-01-09 22:48:24 +08:00
Juan M Gómez
e3bcbf5f15 makes nimsuggest con work under v3 [Backport_1.6.18] (#23158)
Co-authored-by: Jake Leahy <jake@leahy.dev>
2024-01-08 20:30:46 +01:00
narimiran
d84e2d3f63 update macOS to 12, remove one package from testing 2024-01-08 13:35:26 +01:00
ringabout
7912685905 fixes #23148; restricts infix path concatenation to what starts with / (#23150)
fixes #23148

(cherry picked from commit c7d742e484)
2024-01-03 10:56:47 +01:00
narimiran
2cc4da8fd4 bump NimVersion to 1.6.19 2024-01-03 10:56:24 +01:00
narimiran
a749a8b742 bump NimVersion to 1.6.18 2023-12-14 17:52:25 +01:00
Nikolay Nikolov
9a87057f0b Skip trailing asterisk when placing inlay type hints. Fixes #23067 (backport of #23068) (#23071)
(cherry picked from commit a3739751a8)
2023-12-14 09:26:12 +08:00
Nikolay Nikolov
efd5ed7328 backport to version 1.6: Also show the raises pragma when converting proc types to string (#23026) (#23029)
This affects also nimsuggest hints (e.g. on mouse hover), as well as
compiler messages.

(cherry picked from commit 618ccb6b6a)
2023-12-12 10:36:58 +01:00
Jake Leahy
2e87171e14 Register declaration of enum field has a use (#22990)
Currently when using `use` with nimsuggest on an enum field, it doesn't
return the definition of the field.

Breaks renaming in IDEs since it will replace all the usages, but not
the declaration

(cherry picked from commit c31bbb07fb)
2023-11-28 08:25:42 +01:00
tersec
9cbd8695e7 remove unnecessary side-effects from base64.encode(mime) (#22986)
Fixes https://github.com/nim-lang/Nim/issues/22985

(cherry picked from commit 26f2ea149c)
2023-11-26 07:15:57 +01:00
Nikolay Nikolov
6f0cad6843 backport to v 1.6: nimsuggest: Added optional command line option '--clientProcessId:XXX' (#22969) (#22982)
When it is specified, the nimsuggest instance monitors whether this
process is still alive. In case it's found to be dead, nimsuggest shuts
itself down. Currently only implemented on POSIX and Windows platforms.
The switch is silently ignored on other platforms. Note that the Nim
language server should still try to shut down its child nimsuggest
processes. This switch just adds extra protection against crashing Nim
language server and gets rid of the remaining nimsuggest processes,
which consume memory and system resources.

(cherry picked from commit 502a4486ae)
2023-11-25 11:50:37 +01:00
Nikolay Nikolov
ef10224e61 Backport to 1.6: Introduced version 4 of the NimSuggest protocol. The InlayHints feature made V4 or later only. (#22953) (#22962)
Since nimsuggest now has a protocol version support detection via
`--info:protocolVer`, the InlayHints feature can be moved to protocol
V4. This way, the Nim language server can detect the nimsuggest version
and avoid sending unsupported `InlayHints` commands to older nimsuggest
versions. Related nim language server PR:
https://github.com/nim-lang/langserver/pull/60

(cherry picked from commit 4fc0027b57)
2023-11-20 09:13:38 +08:00
Nikolay Nikolov
f3382743dd backport to version 1.6: nimsuggest: Instead of checking for protocol version 3 exactly, check for version 3 or later. (#22945) (#22956)
Refactored the way nimsuggest checks for protocol version 3. Instead of
checking for version 3 exactly, it now checks for version 3 or later.
This way, once a version 4 is introduced, it will use version 3 as a
base line, and then extra changes to the protocol can be added on top.
No functional changes are introduced in this commit.

(cherry picked from commit 3680200df4)
2023-11-18 09:52:15 +08:00
Nikolay Nikolov
1dab585a26 Added new command line option --info:X to nimsuggest for obtaining … (#22942)
…information. (#22940)

`--info:protocolVer` returns the highest nimsuggest protocol version
that is supported (currently, it's version 3).
`--info:nimVer` returns the Nim compiler version that nimsuggest uses
internally.

Note that you can obtain the Nim compiler version via `nimsuggest -v`,
but that requires parsing the output, which looks like this:

```
Nim Compiler Version 2.1.1 [Linux: amd64]
Compiled at 2023-11-14
Copyright (c) 2006-2023 by Andreas Rumpf

git hash: 47ddfeca5247dce992becd734d1ae44e621207b8
active boot switches: -d:release -d:danger --gc:markAndSweep
```

`--info:nimVer` will return just:

```
2.1.1
```

(cherry picked from commit d0cc02dfc4)
2023-11-17 17:29:14 +08:00
Nikolay Nikolov
a77ca1a4bf Inlay hints backport to Nim v1.6.x (#22920) 2023-11-08 00:22:40 +01:00
narimiran
0779a5e11b bump NimVersion to 1.6.17 2023-11-01 19:43:25 +01:00
ringabout
a17c077f78 fixes chronicles (#22899) 2023-11-01 17:03:19 +08:00
ringabout
47010a3919 fixes #22874; backport #22088 to version-1-6 2023-11-01 00:51:48 +00:00
ringabout
3c9b68dc15 fixes CI; disable SSL tests on osx for now (#22304)
* test CI

* disable osx

(cherry picked from commit 993fcf5bda)
2023-10-10 08:55:48 +02:00
narimiran
ec72abc7b7 fixes stint CI 2023-10-10 08:53:45 +02:00
narimiran
a08f56f9ba bump NimVersion to 1.6.16 2023-10-09 19:07:36 +02:00
SirOlaf
246267aa52 Exclude block from endsInNoReturn, fix regression (#22632)
Co-authored-by: SirOlaf <>
(cherry picked from commit d2f36c071b)
2023-09-15 19:49:57 +02:00
SirOlaf
ce8d9dd1cb Fix #22604: Make endsInNoReturn traverse the tree (#22612)
* Rewrite endsInNoReturn

* Handle `try` stmt again and add tests

* Fix unreachable code warning

* Remove unreachable code in semexprs again

* Check `it.len` before skip

* Move import of assertions

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit 3b206ed988)
2023-09-15 12:58:20 +02:00
ringabout
4fc535fbd6 fixes #17197; fixes #22560; fixes the dest of newSeqOfCap in refc (#22594)
(cherry picked from commit 5bd1afc3f9)
2023-09-15 12:58:20 +02:00
ringabout
2d529edf3e fixes #22541; peg matchLen can raise an unlisted exception: Exception (#22545)
The `mopProc` is a recursive function.

(cherry picked from commit c56a712e7d)
2023-09-15 09:10:56 +02:00
metagn
d37901fe06 fix getNullValue for cstring in VM, make other VM code aware of nil cstring (#22527)
* fix getNullValue for cstring in VM

fixes #22524

* very ugly fixes, but fix #15730

* nil cstring len works, more test lines

* fix high

(cherry picked from commit 942f846f04)
2023-09-15 09:10:56 +02:00
ringabout
dc59e67a12 fixes bareExcept warnings; catch specific exceptions (#21119)
* fixes bareExcept warnings; catch specific exceptions

* Update lib/pure/coro.nim

(cherry picked from commit 9207d77848)
2023-09-15 08:39:22 +02:00
ringabout
09f7be13b6 fixes #22262; fixes -d:useMalloc broken with --mm:none and --threads on (#22355)
* fixes #22262; -d:useMalloc broken with --mm:none and threads on

* fixes

(cherry picked from commit a23e53b490)
2023-09-15 08:37:31 +02:00
Andreas Rumpf
d80397c7d7 fixes #22138 (#22221)
(cherry picked from commit 86ff37fab8)
2023-09-14 17:02:49 +02:00
Juan M Gómez
efa3479e4e reset macrocache after each script evaluation (#22195)
(cherry picked from commit 2f109595e9)
2023-09-14 16:59:13 +02:00
ringabout
e8ec3efd3d allow addressing elements of openArray[char] in VM (#22045)
allow addressing elements of openArray[char]

(cherry picked from commit a8d0dda833)
2023-09-14 14:07:08 +02:00
metagn
8f102f9e62 retain forced open undeclared ident information (#22019)
(cherry picked from commit ce72b564bc)
2023-09-14 14:04:43 +02:00
ringabout
876f6d69a8 fixes #21974; fixes sameConstant fieldDefect (#21981)
* fixes #21974; fixes sameConstant fieldDefect

* add a test case

(cherry picked from commit 8e35b3d577)
2023-09-14 14:04:43 +02:00
heterodoxic
50173ec7ec prevent spamming of thread local forward declarations in C/C++ output (#21955)
(cherry picked from commit f47b27d532)
2023-09-14 14:03:47 +02:00
metagn
ecab260330 underscore as special word (#21766)
* underscore as special word

* fix really hard to notice error

(cherry picked from commit ca82b4ea16)
2023-09-14 13:09:43 +02:00
ringabout
43ce0558b4 handle quoted routine symbols and non symbols expressions as before (#21740)
(cherry picked from commit 560fa9a1fe)
2023-09-14 12:00:47 +02:00
narimiran
19b3f8c0ea Revert "fixes #16790; fixes #19075; put big arrays on the constant seqs; don't inline them in the VM; big performance boost (#21318)"
This reverts commit 7ad8c44e28.
2023-09-14 06:03:34 +02:00
SirOlaf
5ad4b72ac7 Fix #17509: Continue instead of return with unfinished generics (#22563)
Close #17509

Current knowledge:
- delaying cache fixes the issue
- changing return of `if inst.len < key.len:` in `searchInstTypes` to
`continue` fixes the issue. With return the broken types are also cached
over and over

Related issues are completely unaffected as of now, so there must be
something deeper.

I am also still trying to find the true cause, so feel free to ignore
for now

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit ee4a219012)
2023-09-12 09:24:33 +02:00
Amjad Ben Hedhili
d7dfbf026b Remove some unnecessary initialization in string operations (#22579)
* `prepareAdd`
* `toNimStr`
* `setLengthStrV2`
* `NimAsgnStrV2`
* `prepareMutation`
* Some cleanups

(cherry picked from commit a4df44d9fb)
2023-09-12 09:24:33 +02:00
metagn
79a1990774 use dummy dest for void branches to fix noreturn in VM (#22617)
fixes #22216

(cherry picked from commit 2542dc09c8)
2023-09-12 09:24:33 +02:00
metagn
106cde1ff8 unify explicit generic param semchecking in calls (#22618)
fixes #9040

(cherry picked from commit 6738f44af3)
2023-09-12 09:24:33 +02:00
metagn
965eeb68e2 handle typedesc params in VM (#22581)
* handle typedesc params in VM

fixes #15760

* add test

* fix getType(typedesc) test

(cherry picked from commit 2e4e2f8f50)
2023-09-11 21:33:48 +02:00
metagn
0dbac38d12 clearer error for different size int/float cast in VM (#22582)
refs #16547

(cherry picked from commit b6cea7b599)
2023-09-11 21:33:42 +02:00
metagn
f16e4dd22a correct logic for qualified symbol in templates (#22577)
* correct logic for qualified symbol in templates

fixes #19865

* add test

(cherry picked from commit 3de8d75513)
2023-09-11 21:33:35 +02:00
metagn
ede6bc4d67 define toList procs after add for lists [backport] (#22573)
fixes #22543

(cherry picked from commit 94454addb2)
2023-09-11 21:33:21 +02:00
ringabout
d2f91ab1b9 newStringOfCap now won't initialize all elements anymore (#22568)
newStringOfCap nows won't initialize all elements anymore

(cherry picked from commit 2e7c8a339f)
2023-09-11 21:33:13 +02:00
Bung
69faab3cf6 fix #22548;environment misses for type reference in iterator access n… (#22559)
* fix #22548;environment misses for type reference in iterator access nested in closure

* fix #21737

* Update lambdalifting.nim

* remove containsCallKinds

* simplify

(cherry picked from commit 0b78b7f595)
2023-09-11 21:32:58 +02:00
SirOlaf
b7a1210964 Fix #21532: Check if template return is untyped (#22517)
* Don't ignore return in semTemplateDef

* Add test

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit 3de75ffc02)
2023-09-11 21:32:22 +02:00
ringabout
0d5999e6a8 fixes #22481; fixes card undefined misalignment behavior (#22484)
* fixes `card` undefined misalignment behavior

* Update lib/system/sets.nim

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit ade75a1483)
2023-09-11 21:31:40 +02:00
Jason Beetham
60dc41a5e4 When in object handles procedure call again, fixes #22474 (#22480)
Ping @narimiran please backport to the 2.0 line.

(cherry picked from commit 6c4e7835bf)
2023-09-11 21:31:32 +02:00
Emery Hemingway
ba5d873f63 Add Linux constant SO_BINDTODEVICE (#22468)
(cherry picked from commit 1927ae72d0)
2023-09-11 21:31:20 +02:00
Bung
f55f3d6ffd Fix #5780 (#22428)
* fix #5780

(cherry picked from commit 46e94c83d4)
2023-09-11 21:30:06 +02:00
Jake Leahy
118f83f965 Fix crash when using uninstantiated generic (#22379)
* Add test case

* Add in a bounds check when accessing generic types

Removes idnex out of bounds exception when comparing a generic that isn't fully instantiated

(cherry picked from commit 3efabd3ec6)
2023-09-11 20:41:29 +02:00
Eric N. Vander Weele
72afd29a9a Remove declared and not used variable in packedsets.bitincl (#22334)
When compiling code that uses PackedSet with warnings enabled, `var ret`
in `bitincl` emits a "XDeclaredButNotUsed" warning.

(cherry picked from commit f1ac979184)
2023-09-11 20:41:29 +02:00
SirOlaf
30921aaff5 Check try block for endsInNoReturn (#22314)
Co-authored-by: SirOlaf <>
(cherry picked from commit 62869a5c68)
2023-09-11 20:41:28 +02:00
SirOlaf
a3b65da80f Open scope for defer (#22315)
Co-authored-by: SirOlaf <>
(cherry picked from commit 3ebe24977c)
2023-09-11 20:41:28 +02:00
ringabout
ba2d8ba468 fixes #22297; return in the finally in the closure iterators (#22300)
ref #22297; return in the finally in the closure iterators

(cherry picked from commit b02c1dd6ca)
2023-09-11 20:41:28 +02:00
Anna
0ac3461c7d Fix #22281 (#22289)
Respect `--gcc.exe` and similar options when `--genScript:on` is used.

(cherry picked from commit 14a9929464)
2023-09-11 20:24:58 +02:00
ringabout
e7fc94e130 gendepends now supports pkgs2 (#22277)
(cherry picked from commit 3b377937de)
2023-09-11 20:24:21 +02:00
ringabout
44708f4b01 fixes #22237; fixes #21160; wrong cursor on unowned parameters in the for loop in ORC (#22240)
fixes #22237; fixes #21160; wrong cursor on unowned parameters

(cherry picked from commit ecc6ab7ee0)
2023-09-11 20:24:11 +02:00
narimiran
0e9250264b fix wrong import 2023-09-11 16:10:50 +02:00
Jake Leahy
5ffd507014 Fix nimsuggest not showing suggestions for imported tuples (#22241)
* Add tests

Also test if exported all tuple fields works. This seems like a hacky solution so will try and dive further to find a better solution

* Always suggest tuple fields if it passes the filter

If the tuple we are accessing is in scope then all the fields will also be in scope

* Update tests so line numbers are correct

(cherry picked from commit 1b132ddaa2)
2023-09-11 13:52:59 +02:00
Andreas Rumpf
322fc31041 fixes #22137 (#22170)
(cherry picked from commit ce0909f047)
2023-09-11 13:52:59 +02:00
Jacek Sieka
5ab9945345 fix Sigaction struct definition (#22160)
SigInfo is still wrong (most of its fields are in a union)

(cherry picked from commit 47635d3031)
2023-09-11 13:52:59 +02:00
Jacek Sieka
b0cee7c0c5 uint arithmetic for pointers (#22159)
pointers are not signed and arithmetic may correctly cross int.max
threshold

this PR only fixes 2 occurances - there are plenty however in the std
lib

(cherry picked from commit cb40f11e6c)
2023-09-11 13:52:59 +02:00
metagn
5e4648232b make var object match better than object (#22152)
* fix `var object` not matching better than `object`

fixes #13302

* remove comment for brevity

* try note

* try minimize breaks

(cherry picked from commit 20037a4749)
2023-09-11 13:52:59 +02:00
ringabout
3bd03d71a0 fixes #21110; duplicate proc definitions for inline iters (#21136)
fixes #21110; duplicate proc definitions for iters

(cherry picked from commit 88114948c4)
2023-09-11 13:52:58 +02:00
ringabout
238efc025e fixes #21231; template with module as parameter elides usage/checking of module name specifier (#22109)
* fixes #21231; template with module as parameter elides usage/checking of module name specifier

* add a test case

(cherry picked from commit ac7b8b678c)
2023-09-11 13:52:58 +02:00
Bung
a66158dd3d fix #20023 hash for generic tables (#20346)
* fix #20023 hash for generic tables

* use default computation

* Update lib/pure/collections/tables.nim

Co-authored-by: Dan Rose <dan@digilabs.io>

* Update lib/pure/collections/tables.nim

Co-authored-by: Dan Rose <dan@digilabs.io>

* Update lib/pure/collections/tables.nim

* Update lib/pure/collections/tables.nim

* Update t20023.nim

---------

Co-authored-by: Dan Rose <dan@digilabs.io>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 3ad2e7df1c)
2023-09-11 13:52:58 +02:00
Zoom
6863b5d289 strutils.split/rsplit now return src on an empty sep (#22136)
This is a rebase of an earlier rejected PR. Following the discussion
around it, this commit provides a valid output for and edge case
of an empty separator for `split` and `rsplit` routines. The empty
separator is interpreted as "split by no separators" and the initial
string is returned. This is consistent with the behaviour of the
`set[char]` version of `split`/`rsplit` routines and unifies them all.

Compared to a commit merged earlier, this one has a benefit of
not using assertions that will be removed in release builds
and thus still not preventing possible infinite loops (which was the
earlier behaviour for this edge case for separator of type `string`).

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 5e529b3bfa)
2023-09-11 13:52:58 +02:00
Andreas Rumpf
9d573f4a1d fixes #16331; aliasing of tuple construction within a single assignme… (#22113)
* fixes #16331; aliasing of tuple construction within a single assignment, great coding style

* added test case

(cherry picked from commit e8d0f1c3ae)
2023-09-11 13:52:58 +02:00
ringabout
070ecb036c fixes #22049; fixes #22054; implicit conversion keeps varness (#22097)
* fixes #22054; codegen for var tuples conv

* rethink fixes

* add test cases

* templates only

* fixes var tuples

* keep varness no matter what

* fixes typ.isNil

* make it work for generics

* restore isSubrange

* add a test case as requested

(cherry picked from commit 77beb15214)
2023-09-11 13:52:58 +02:00
metagn
107ec62baf consider object types as declarative in templates (#22106)
* consider object types as declarative in templates

fixes #16005

* correct logic for nkRecList children, inject fields

* don't actually inject fields

(cherry picked from commit 3ac2d81601)
2023-09-11 13:52:58 +02:00
ringabout
ffcccd5986 clean up isNilConversion for seqs, strings (#22057)
(cherry picked from commit 49e11d9dcc)
2023-09-11 12:02:29 +02:00
Juan Carlos
c001b11320 Improve compiler messages (#22040)
* Improve compiler messages

(cherry picked from commit ea91cfb305)
2023-09-11 12:02:29 +02:00
Juan Carlos
e4c13c3fd4 Improve compiler messages (#22028)
* Improve compiler messages with simpler code

(cherry picked from commit 9f3d1b1290)
2023-09-11 12:02:29 +02:00
heterodoxic
6b11a9ec28 fixes #15428 by updating deep open array copy codegen (#21935)
* fix #15428

* add test

(cherry picked from commit af3fd5a010)
2023-09-11 12:02:28 +02:00
Bung
173a15b370 fix #21251 Compiler SIGSEGV when using SharedTable (#21876)
fix #21251

(cherry picked from commit 76a98fee65)
2023-09-11 12:02:28 +02:00
Jason Beetham
c4380107d6 Fixed generic parameters failing to be used in inheritance (#21866)
(cherry picked from commit 28a116a477)
2023-09-11 12:02:28 +02:00
narimiran
09fe696fdd disable yaml package testing 2023-09-11 12:02:28 +02:00
metagn
6fbff263e6 just set CallNodes = nnkCallKinds, follows up #21829 (#21833)
These sets are now equal

(cherry picked from commit 9810b8cf7f)
2023-09-11 10:54:35 +02:00
ringabout
fcaacbf374 cursor fields cannot form reference cycles (#21832)
* cursor fields cannot form a reference cycle

* fixes typo

* fixes position

(cherry picked from commit ebbad9e960)
2023-09-11 10:54:35 +02:00
Matt Wilson
2d19520b5c Add nnkHiddenCallConv to nnkCallKinds (#21781) (#21829)
(cherry picked from commit 802d57c237)
2023-09-11 10:54:35 +02:00
Jordan Gillard
1cca8ccca0 Improve and refactor cellseqs_v2 in Nim standard library (#21796)
* Refactor and optimize cellseqs_v2 in Nim standard library

* Extract resizing logic into a separate 'resize' procedure for better readability and separation of concerns
* Implement realloc for non-threaded cases to improve memory operations efficiency
* Use ',' instead of ';' between parameters in 'add' procedure for consistency with other Nim code

* Respond to Araq's feedback: Refactor resize function to use reallocShared

This commit replaces the usage of allocShared and deallocShared with reallocShared to optimize memory allocation and deallocation while resizing the CellSeq.

(cherry picked from commit b169dad1e5)
2023-09-11 10:54:35 +02:00
Jordan Gillard
a9f1e2dfcd 🚀 Enhancing CellSeq for Better Readability and Maintainability (#21797)
Refactor and improve readability of CellSeq in system directory

* Use half-open range in the contains procedure for better readability and to avoid potential off-by-one errors
* Extract resizing logic from add procedure into a separate resize procedure for better code readability and separation of concerns

(cherry picked from commit 71f2e1a502)
2023-09-11 10:54:35 +02:00
ringabout
7a747fe320 fixes #21792; enable checks for sum, prod, cumsummed and cumsum (#21793)
* enable checks for sum, prod, cumsummed  and cumsum

* fixes #21792

* add test cases

(cherry picked from commit 07233ceca0)
2023-09-11 10:54:34 +02:00
metagn
547f205794 error on user pragma args (#21776)
closes #20978

(cherry picked from commit 44736d26cd)
2023-09-11 10:54:34 +02:00
metagn
fa3639ba33 line info for strformat + fix issue with typed templates (#21761)
* line info in strformat

* also fix #20381

(cherry picked from commit e5d0907a42)
2023-09-11 10:54:34 +02:00
metagn
cd0f805832 cheap fix for #10853 + better tuple subscript error message (#21767)
* cheap fix for #10853

* also better tuple subscript error message

* weird

(cherry picked from commit c2bcfd8cd9)
2023-09-11 10:54:34 +02:00
ringabout
579efdabb0 fixes #21703; moveOrCopy should consider when vm (#21721)
(cherry picked from commit 0f226c0e48)
2023-09-11 10:54:34 +02:00
metagn
7b99712bcf fix iterator equality + add test for proc equality + fix sameType (#21707)
* fix iterator equality + add test also for procs

fixes #21706

* all targets

* and isNil and repr

* separate overloads, fix sameType

* more restricted sameType?

* merge overloads again??

* remove sametype change for now

* fix sameType anyway (CI failure was not related)

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit 380dafcc32)
2023-09-11 10:54:34 +02:00
ringabout
58c7474838 static link pthread correctly (#21693)
(cherry picked from commit f9477396a6)
2023-09-11 10:36:10 +02:00
ringabout
a2521b1dc7 Delete parse directory, which was pushed wrongly before [backport] (#22401)
Delete parse directory

(cherry picked from commit 614a18cd05)
2023-08-11 12:46:13 +02:00
ringabout
5d39a8283c fixes #20516; system.create doesn't work with bitfield objects (#20518)
* Revert "fixes #19000 (#19032)"

This reverts commit 2bda4a30a6.

* fixes #20516; add testcase

(cherry picked from commit 5e4dd571d4)
2023-08-11 12:42:20 +02:00
ringabout
01ef1e1500 fixes #22208; Ambiguous error when import modules with same names but… (#22211)
fixes #22208; Ambiguous error when import modules with same names but different aliases

(cherry picked from commit d9a24b9b81)
2023-08-11 12:41:50 +02:00
narimiran
80ece5921f use unsafeAddr 2023-08-11 12:35:56 +02:00
ringabout
bd4609f20e fixes #22419; async/closure environment does not align local variables (#22425)
* fixes #22419; async/closure environment does not align local variables

* Apply suggestions from code review

* Update tests/align/talign.nim

Co-authored-by: Jacek Sieka <arnetheduck@gmail.com>

* apply code review

* update tests

---------

Co-authored-by: Jacek Sieka <arnetheduck@gmail.com>
(cherry picked from commit 5334dc921f)
2023-08-11 10:53:36 +02:00
ringabout
b901e94936 fixes #22387; Undefined behavior when with hash(...) (#22404)
* fixes #22387; Undefined behavior when with hash(...)

* fixes vm

* fixes nimscript

(cherry picked from commit 47d06d3d4c)
2023-08-11 10:53:24 +02:00
norrath-hero-cn
0cb84726d0 fixes AddressSanitizer: global-buffer-overflow in getAppFilename on windows 10 (#22380)
fixes AddressSanitizer: global-buffer-overflow

(cherry picked from commit 73a29d72e3)
2023-08-11 10:53:01 +02:00
metagn
1cd48e4b2a fix new type inference for noreturn [backport] (#22182)
fixes #22180

Backported since apparently the new type inference was backported

(cherry picked from commit b35942ef83)
2023-07-03 11:58:59 +02:00
Jacek Sieka
bb56a37732 fix controlflow test (#22194)
the function actually returns

(cherry picked from commit 4d2ebbb877)
2023-07-03 11:58:23 +02:00
narimiran
d1b5df06b0 bump NimVersion to 1.6.15 2023-07-03 11:57:42 +02:00
158 changed files with 2427 additions and 582 deletions

View File

@@ -2,10 +2,10 @@ name: Nim Docs CI
on:
push:
paths:
- 'compiler/docgen.nim'
- 'compiler/renderverbatim.nim'
- 'compiler/**.nim'
- 'config/nimdoc.cfg'
- 'doc/**.rst'
- 'doc/**.md'
- 'doc/nimdoc.css'
- 'lib/**.nim'
- 'nimdoc/testproject/expected/testproject.html'
@@ -13,13 +13,14 @@ on:
- 'tools/kochdocs.nim'
- '.github/workflows/ci_docs.yml'
- 'koch.nim'
pull_request:
# Run only on changes on these files.
paths:
- 'compiler/docgen.nim'
- 'compiler/renderverbatim.nim'
- 'compiler/**.nim'
- 'config/nimdoc.cfg'
- 'doc/**.rst'
- 'doc/**.md'
- 'doc/nimdoc.css'
- 'lib/**.nim'
- 'nimdoc/testproject/expected/testproject.html'
@@ -28,6 +29,10 @@ on:
- '.github/workflows/ci_docs.yml'
- 'koch.nim'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
@@ -36,11 +41,11 @@ jobs:
target: [linux, windows, osx]
include:
- target: linux
os: ubuntu-20.04
os: ubuntu-22.04
- target: windows
os: windows-2019
os: windows-latest
- target: osx
os: macos-11
os: macos-15
name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}
@@ -48,7 +53,7 @@ jobs:
steps:
- name: 'Checkout'
uses: actions/checkout@v2
uses: actions/checkout@v6
with:
fetch-depth: 2
@@ -104,7 +109,7 @@ jobs:
if: |
github.event_name == 'push' && github.ref == 'refs/heads/devel' &&
matrix.target == 'linux'
uses: crazy-max/ghaction-github-pages@v1
uses: crazy-max/ghaction-github-pages@v5
with:
build_dir: doc/html
env:

View File

@@ -1,13 +1,24 @@
name: Packages CI
on: [push, pull_request]
on:
pull_request:
push:
branches:
- 'devel'
- 'version-2-2'
- 'version-2-0'
- 'version-1-6'
- 'version-1-2'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, macos-11]
cpu: [amd64]
os: [ubuntu-latest, macos-14]
batch: ["allowed_failures", "0_3", "1_3", "2_3"] # list of `index_num`
name: '${{ matrix.os }} (batch: ${{ matrix.batch }})'
runs-on: ${{ matrix.os }}
@@ -17,26 +28,27 @@ jobs:
NIM_TESTAMENT_BATCH: ${{ matrix.batch }}
steps:
- name: 'Checkout'
uses: actions/checkout@v2
uses: actions/checkout@v6
with:
fetch-depth: 2
- name: 'Install node.js 16.x'
uses: actions/setup-node@v2
- name: 'Install node.js'
uses: actions/setup-node@v6
with:
node-version: '16.x'
node-version: 24
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
run: |
sudo apt-fast update -qq
sudo apt-get update -qq
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends -yq \
sudo apt-get install --no-install-recommends -yq \
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev \
valgrind libc6-dbg libblas-dev xorg-dev
valgrind libc6-dbg libblas-dev liblapack-dev libpcre3 xorg-dev
- name: 'Install dependencies (macOS)'
if: runner.os == 'macOS'
run: brew install boehmgc make sfml gtk+3
# XXX can't find boehm and gtk on macos 13
- name: 'Install dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash

View File

@@ -1,7 +1,8 @@
trigger:
branches:
include:
- '*'
- 'devel'
- 'version-*'
pr:
branches:
include:
@@ -19,32 +20,32 @@ jobs:
strategy:
matrix:
Linux_amd64:
vmImage: 'ubuntu-20.04'
vmImage: 'ubuntu-24.04'
CPU: amd64
# regularly breaks, refs bug #17325
# Linux_i386:
# # on 'ubuntu-16.04' (not supported anymore anyways) it errored with:
# # g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
# vmImage: 'ubuntu-20.04'
# CPU: i386
OSX_amd64:
vmImage: 'macOS-11'
CPU: amd64
OSX_amd64_cpp:
vmImage: 'macOS-11'
CPU: amd64
# Linux_i386:
# # on 'ubuntu-16.04' (not supported anymore anyways) it errored with:
# # g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
# vmImage: 'ubuntu-18.04'
# CPU: i386
OSX_arm64:
vmImage: 'macos-15'
CPU: arm64
OSX_arm64_cpp:
vmImage: 'macos-15'
CPU: arm64
NIM_COMPILE_TO_CPP: true
Windows_amd64_batch0_3:
vmImage: 'windows-2019'
vmImage: 'windows-2025'
CPU: amd64
# see also: `NIM_TEST_PACKAGES`
NIM_TESTAMENT_BATCH: "0_3"
Windows_amd64_batch1_3:
vmImage: 'windows-2019'
vmImage: 'windows-2025'
CPU: amd64
NIM_TESTAMENT_BATCH: "1_3"
Windows_amd64_batch2_3:
vmImage: 'windows-2019'
vmImage: 'windows-2025'
CPU: amd64
NIM_TESTAMENT_BATCH: "2_3"
@@ -72,17 +73,19 @@ jobs:
- task: NodeTool@0
inputs:
versionSpec: '16.x'
displayName: 'Install node.js 16.x'
versionSpec: '20.x'
displayName: 'Install node.js 20.x'
condition: and(succeeded(), eq(variables['skipci'], 'false'))
- bash: |
set -e
. ci/funs.sh
echo_run sudo apt-fast update -qq
echo_run sudo add-apt-repository universe
echo_run sudo apt-get update -qq
DEBIAN_FRONTEND='noninteractive' \
echo_run sudo apt-fast install --no-install-recommends -yq \
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev valgrind libc6-dbg
echo_run sudo apt-get install --no-install-recommends -yq \
gcc-14 g++-14 libpcre3 liblapack-dev libpcre3 liblapack-dev libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev valgrind libc6-dbg
echo_run sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 60 --slave /usr/bin/g++ g++ /usr/bin/g++-14
displayName: 'Install dependencies (amd64 Linux)'
condition: and(succeeded(), eq(variables['skipci'], 'false'), eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'amd64'))
@@ -99,15 +102,16 @@ jobs:
Pin-Priority: 1001
EOF
# echo_run sudo apt-fast update -qq
echo_run sudo apt-fast update -qq || echo "failed, see bug #17343"
# echo_run sudo apt-get update -qq
echo_run sudo apt-get update -qq || echo "failed, see bug #17343"
# `:i386` (e.g. in `libffi-dev:i386`) is needed otherwise you may get:
# `could not load: libffi.so` during dynamic loading.
DEBIAN_FRONTEND='noninteractive' \
echo_run sudo apt-fast install --no-install-recommends --allow-downgrades -yq \
echo_run sudo apt-get install --no-install-recommends --allow-downgrades -yq \
g++-multilib gcc-multilib libcurl4-openssl-dev:i386 libgc-dev:i386 \
libsdl1.2-dev:i386 libsfml-dev:i386 libglib2.0-dev:i386 libffi-dev:i386
cat << EOF > bin/gcc
#!/bin/bash
@@ -129,6 +133,7 @@ jobs:
- bash: brew install boehmgc make sfml
displayName: 'Install dependencies (OSX)'
condition: and(succeeded(), eq(variables['skipci'], 'false'), eq(variables['Agent.OS'], 'Darwin'))
# XXX can't find boehm on macos 13
- bash: |
set -e

View File

@@ -887,6 +887,7 @@ type
info*: TLineInfo
when defined(nimsuggest):
endInfo*: TLineInfo
hasUserSpecifiedType*: bool # used for determining whether to display inlay type hints
owner*: PSym
flags*: TSymFlags
ast*: PNode # syntax tree of proc, iterator, etc.:

View File

@@ -444,9 +444,10 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) =
[addrLoc(p.config, dest), rdLoc(src),
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
of tyOpenArray, tyVarargs:
let source = addrLocOrTemp(src)
linefmt(p, cpsStmts,
"#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
[addrLoc(p.config, dest), addrLocOrTemp(src),
"#genericDeepCopyOpenArray((void*)$1, (void*)$2, $2->Field1, $3);$n",
[addrLoc(p.config, dest), source,
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
of tySet:
if mapSetType(p.config, ty) == ctArray:
@@ -599,7 +600,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
if t.kind == tyInt64: prc64[m] else: prc[m])
putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res])
else:
let res = "($1)($2 $3 $4)" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
let res = "($1)(($2) $3 ($4))" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
putIntoDest(p, d, e, res)
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
@@ -1446,6 +1447,7 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
getSeqPayloadType(p.module, seqtype),
])
else:
if d.k == locNone: getTemp(p, e.typ, d, needsInit=false) # bug #22560
putIntoDest(p, d, e, ropecg(p.module,
"($1)#nimNewSeqOfCap($2, $3)", [
getTypeDesc(p.module, seqtype),
@@ -1804,9 +1806,9 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
if optBoundsCheck in p.options:
genBoundsCheck(p, m, b, c)
if op == mHigh:
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)", [rdLoc(b), rdLoc(c)]))
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1))", [rdLoc(b), rdLoc(c)]))
else:
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)+1", [rdLoc(b), rdLoc(c)]))
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1)+1)", [rdLoc(b), rdLoc(c)]))
else:
if not reifiedOpenArray(a):
if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)")
@@ -2566,15 +2568,30 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
if not handleConstExpr(p, n, d):
let t = n.typ
discard getTypeDesc(p.module, t) # so that any fields are initialized
if d.k == locNone: getTemp(p, t, d)
var tmp: TLoc
# bug #16331
let doesAlias = lhsDoesAlias(d.lode, n)
let dest = if doesAlias: addr(tmp) else: addr(d)
if doesAlias:
getTemp(p, n.typ, tmp)
elif d.k == locNone:
getTemp(p, n.typ, d)
for i in 0..<n.len:
var it = n[i]
if it.kind == nkExprColonExpr: it = it[1]
initLoc(rec, locExpr, it, d.storage)
rec.r = "$1.Field$2" % [rdLoc(d), rope(i)]
initLoc(rec, locExpr, it, dest[].storage)
rec.r = "$1.Field$2" % [rdLoc(dest[]), rope(i)]
rec.flags.incl(lfEnforceDeref)
expr(p, it, rec)
if doesAlias:
if d.k == locNone:
d = tmp
else:
genAssignment(p, d, tmp, {})
proc isConstClosure(n: PNode): bool {.inline.} =
result = n[0].kind == nkSym and isRoutine(n[0].sym) and
n[1].kind == nkNilLit

View File

@@ -83,7 +83,7 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
lineCg(p, cpsStmts, "$1.ClP_0 = NIM_NIL;$n", [accessor])
else:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
of tyChar, tyBool, tyEnum, tyInt..tyUInt64:
of tyChar, tyBool, tyEnum, tyRange, tyInt..tyUInt64:
lineCg(p, cpsStmts, "$1 = 0;$n", [accessor])
of tyCstring, tyPointer, tyPtr, tyVar, tyLent:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
@@ -97,7 +97,7 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
else:
doAssert false, "unexpected set type kind"
of {tyNone, tyEmpty, tyNil, tyUntyped, tyTyped, tyGenericInvocation,
tyGenericParam, tyOrdinal, tyRange, tyOpenArray, tyForward, tyVarargs,
tyGenericParam, tyOrdinal, tyOpenArray, tyForward, tyVarargs,
tyUncheckedArray, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot,
tyAnything, tyStatic, tyFromExpr, tyConcept, tyVoid, tyIterable}:

View File

@@ -35,14 +35,94 @@ proc mangleField(m: BModule; name: PIdent): string =
if isKeyword(name):
result.add "_0"
proc encodeName*(name: string): string =
result = mangle(name)
result = $result.len & result
proc makeUnique(m: BModule; s: PSym, name: string = ""): Rope =
let str = if name == "": s.name.s else: name
result.add str
result.add "__"
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
result.add "_u"
result.add $s.itemId.item
proc encodeSym*(m: BModule; s: PSym; makeUnique: bool = false): string =
#Module::Type
var name = s.name.s
if makeUnique:
name = $makeUnique(m, s, name)
"N" & encodeName(s.skipGenericOwner.name.s) & encodeName(name) & "E"
proc elementType*(n: PType): PType {.inline.} = n.sons[^1]
proc encodeType*(m: BModule; t: PType): string =
result = ""
var kindName = ($t.kind)[2..^1]
kindName[0] = toLower($kindName[0])[0]
case t.kind
of tyObject, tyEnum, tyDistinct, tyUserTypeClass, tyGenericParam:
result = encodeSym(m, t.sym)
of tyGenericInst, tyUserTypeClassInst, tyGenericBody:
result = encodeName(t[0].sym.name.s)
result.add "I"
for i in 1..<t.len - 1:
result.add encodeType(m, t[i])
result.add "E"
of tySequence, tyOpenArray, tyArray, tyVarargs, tyTuple, tyProc, tySet, tyTypeDesc,
tyPtr, tyRef, tyVar, tyLent, tySink, tyStatic, tyUncheckedArray, tyOr, tyAnd, tyBuiltInTypeClass:
result =
case t.kind:
of tySequence: encodeName("seq")
else: encodeName(kindName)
result.add "I"
for i in 0..<t.len:
let s = t[i]
if s.isNil: continue
result.add encodeType(m, s)
result.add "E"
of tyRange:
var val = "range_"
if t.n[0].typ.kind in {tyFloat..tyFloat128}:
val.addFloat t.n[0].floatVal
val.add "_"
val.addFloat t.n[1].floatVal
else:
val.add $t.n[0].intVal & "_" & $t.n[1].intVal
result = encodeName(val)
of tyString..tyUInt64, tyPointer, tyBool, tyChar, tyVoid, tyAnything, tyNil, tyEmpty:
result = encodeName(kindName)
of tyAlias, tyInferred, tyOwned:
result = encodeType(m, t.elementType)
else:
assert false, "encodeType " & $t.kind
proc mangleProc(m: BModule; s: PSym; makeUnique: bool): string =
result = "_Z" # Common prefix in Itanium ABI
result.add encodeSym(m, s, makeUnique)
if s.typ.len > 1: #we dont care about the return param
for i in 1..<s.typ.len:
if s.typ[i].isNil: continue
result.add encodeType(m, s.typ[i])
if result in m.g.mangledPrcs:
result = mangleProc(m, s, true)
else:
m.g.mangledPrcs.incl(result)
proc mangleName(m: BModule; s: PSym): Rope =
result = s.loc.r
if result == nil:
result = s.name.s.mangle.rope
result.add "__"
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
result.add "_"
result.add rope s.itemId.item
if $s.loc.r == "":
var result: Rope
if s.kind in routineKinds and optCDebug in m.g.config.globalOptions and
m.g.config.symbolFiles == disabledSf:
result = mangleProc(m, s, false).rope
else:
result = s.name.s.mangle.rope
result.add "__"
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
result.add "_u"
result.add $s.itemId.item # s.disamb #
if m.hcrOn:
result.add "_"
result.add(idOrSig(s, m.module.name.s.mangle, m.sigConflicts, m.config))

View File

@@ -13,6 +13,11 @@ import
ast, types, hashes, strutils, msgs, wordrecg,
platform, trees, options, cgendata
import std/[hashes, strutils]
when defined(nimPreviewSlimSystem):
import std/assertions
proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
case n.kind
of nkStmtList:
@@ -141,4 +146,3 @@ proc ccgIntroducedPtr*(conf: ConfigRef; s: PSym, retType: PType): bool =
if s.position == 0 and retType != nil and retType.kind == tyLent:
result = not (pt.kind in {tyVar, tyArray, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} or
pt.kind == tySet and mapSetType(conf, pt) == ctArray)

View File

@@ -1266,10 +1266,10 @@ proc genVarPrototype(m: BModule, n: PNode) =
if sym.owner.id != m.module.id:
# else we already have the symbol generated!
assert(sym.loc.r != nil)
incl(m.declaredThings, sym.id)
if sfThread in sym.flags:
declareThreadVar(m, sym, true)
else:
incl(m.declaredThings, sym.id)
if sym.kind in {skLet, skVar, skField, skForVar} and sym.alignment > 0:
m.s[cfsVars].addf "NIM_ALIGN($1) ", [rope(sym.alignment)]
m.s[cfsVars].add(if m.hcrOn: "static " else: "extern ")

View File

@@ -138,6 +138,7 @@ type
# unconditionally...
# nimtvDeps is VERY hard to cache because it's
# not a list of IDs nor can it be made to be one.
mangledPrcs*: HashSet[string]
TCGen = object of PPassContext # represents a C source file
s*: TCFileSections # sections of the C file

View File

@@ -852,7 +852,9 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
case n.kind
of nkReturnStmt:
# We're somewhere in try, transform to finally unrolling
assert(ctx.nearestFinally != 0)
if ctx.nearestFinally == 0:
# return is within the finally
return
result = newNodeI(nkStmtList, n.info)

View File

@@ -58,12 +58,16 @@ proc toNimblePath(s: string, isStdlib: bool): string =
sub.add "/pkgs/"
var start = s.find(sub)
if start < 0:
result = s
else:
start += sub.len
start += skipUntil(s, '/', start)
start += 1
result = pkgPrefix & s[start..^1]
sub[^1] = '2'
sub.add '/'
start = s.find(sub) # /pkgs2
if start < 0:
return s
start += sub.len
start += skipUntil(s, '/', start)
start += 1
result = pkgPrefix & s[start..^1]
proc addDependency(c: PPassContext, g: PGen, b: Backend, n: PNode) =
doAssert n.kind == nkSym, $n.kind

View File

@@ -565,7 +565,7 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
compilePattern = joinPath(conf.cCompilerPath, exe)
else:
compilePattern = getCompilerExe(conf, c, isCpp)
compilePattern = exe
includeCmd.add(join([CC[c].includeCmd, quoteShell(conf.projectPath.string)]))

View File

@@ -247,7 +247,7 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym, importHidden: bool)
result.options.incl optImportHidden
c.unusedImports.add((result, n.info))
c.importModuleMap[result.id] = realModule.id
c.importModuleLookup.mgetOrPut(realModule.name.id, @[]).addUnique realModule.id
c.importModuleLookup.mgetOrPut(result.name.id, @[]).addUnique realModule.id
proc transformImportAs(c: PContext; n: PNode): tuple[node: PNode, importHidden: bool] =
var ret: typeof(result)

View File

@@ -706,6 +706,11 @@ template handleNestedTempl(n, processCall: untyped, willProduceStmt = false) =
of nkWhen: # This should be a "when nimvm" node.
result = copyTree(n)
result[1][0] = processCall(n[1][0], s)
of nkPragmaBlock:
result = shallowCopy(n)
for i in 0 ..< n.len-1:
result[i] = p(n[i], c, s, normal)
result[^1] = maybeVoid(n[^1], s)
else: assert(false)
proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
@@ -735,7 +740,7 @@ proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
if n.kind in {nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt,
nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkParForStmt, nkTryStmt}:
nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkParForStmt, nkTryStmt, nkPragmaBlock}:
template process(child, s): untyped = p(child, c, s, mode)
handleNestedTempl(n, process)
elif mode == sinkArg:
@@ -915,7 +920,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
result = n
of nkStringToCString, nkCStringToString, nkChckRangeF, nkChckRange64, nkChckRange, nkPragmaBlock:
of nkStringToCString, nkCStringToString, nkChckRangeF, nkChckRange64, nkChckRange:
result = shallowCopy(n)
for i in 0 ..< n.len:
result[i] = p(n[i], c, s, normal)
@@ -997,7 +1002,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
proc sameLocation*(a, b: PNode): bool =
proc sameConstant(a, b: PNode): bool =
a.kind in nkLiterals and a.intVal == b.intVal
a.kind in nkLiterals and b.kind in nkLiterals and a.intVal == b.intVal
const nkEndPoint = {nkSym, nkDotExpr, nkCheckedFieldExpr, nkBracketExpr}
if a.kind in nkEndPoint and b.kind in nkEndPoint:
@@ -1054,7 +1059,8 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNod
else:
result = newTree(nkFastAsgn, dest, p(ri, c, s, normal))
else:
case ri.kind
let ri2 = if ri.kind == nkWhen: ri[1][0] else: ri
case ri2.kind
of nkCallKinds:
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
of nkBracketExpr:

View File

@@ -298,6 +298,7 @@ type
processed, capturedVars: IntSet
ownerToType: Table[int, PType]
somethingToDo: bool
inTypeOf: bool
graph: ModuleGraph
idgen: IdGenerator
@@ -401,6 +402,9 @@ Consider:
"""
proc isTypeOf(n: PNode): bool =
n.kind == nkSym and n.sym.magic in {mTypeOf, mType}
proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) =
var cp = getEnvParam(fn)
let owner = if fn.kind == skIterator: fn else: fn.skipGenericOwner
@@ -437,7 +441,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
c.somethingToDo = true
addClosureParam(c, owner, n.info)
if interestingIterVar(s):
if not c.capturedVars.containsOrIncl(s.id):
if not c.capturedVars.contains(s.id):
if not c.inTypeOf: c.capturedVars.incl(s.id)
let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
#let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef, tyPtr})
@@ -463,10 +468,12 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
addClosureParam(c, owner, n.info)
#echo "capturing ", n.info
# variable 's' is actually captured:
if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id):
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
discard addField(obj, s, c.graph.cache, c.idgen)
if interestingVar(s):
if not c.capturedVars.contains(s.id):
if not c.inTypeOf: c.capturedVars.incl(s.id)
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
discard addField(obj, s, c.graph.cache, c.idgen)
# create required upFields:
var w = owner.skipGenericOwner
if isInnerProc(w) or owner.isIterator:
@@ -498,9 +505,14 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
detectCapturedVars(n[namePos], owner, c)
of nkReturnStmt:
detectCapturedVars(n[0], owner, c)
of nkIdentDefs:
detectCapturedVars(n[^1], owner, c)
else:
if n.isCallExpr and n[0].isTypeOf:
c.inTypeOf = true
for i in 0..<n.len:
detectCapturedVars(n[i], owner, c)
c.inTypeOf = false
type
LiftingPass = object
@@ -780,6 +792,8 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass;
of nkTypeOfExpr:
result = n
else:
if n.isCallExpr and n[0].isTypeOf:
return
if owner.isIterator:
if nfLL in n.flags:
# special case 'when nimVm' due to bug #3636:

View File

@@ -11,7 +11,7 @@
import std/[algorithm, strutils, tables]
import
intsets, ast, astalgo, idents, semdata, types, msgs, options,
renderer, nimfix/prettybase, lineinfos, modulegraphs, astmsgs
renderer, nimfix/prettybase, lineinfos, modulegraphs, astmsgs, wordrecg
proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope)
@@ -311,10 +311,10 @@ proc wrongRedefinition*(c: PContext; info: TLineInfo, s: string;
proc addDeclAt*(c: PContext; scope: PScope, sym: PSym, info: TLineInfo) =
let conflict = scope.addUniqueSym(sym)
if conflict != nil:
if sym.kind == skModule and conflict.kind == skModule:
if sym.kind == skModule and conflict.kind == skModule:
# e.g.: import foo; import foo
# xxx we could refine this by issuing a different hint for the case
# where a duplicate import happens inside an include.
# where a duplicate import happens inside an include.
if c.importModuleMap[sym.id] == c.importModuleMap[conflict.id]:
#only hints if the conflict is the actual module not just a shared name
localError(c.config, info, hintDuplicateModuleImport,
@@ -604,6 +604,9 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
result = errorUndeclaredIdentifierHint(c, n[1], ident)
elif n[1].kind == nkSym:
result = n[1].sym
if result.owner != nil and result.owner != m and checkUndeclared in flags:
# dotExpr in templates can end up here
result = errorUndeclaredIdentifierHint(c, n[1], considerQuotedIdent(c, n[1]))
elif checkUndeclared in flags and
n[1].kind notin {nkOpenSymChoice, nkClosedSymChoice}:
localError(c.config, n[1].info, "identifier expected, but got: " &

View File

@@ -129,7 +129,7 @@ proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; idgen: IdGenerator; o
var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3)
vpart[0] = tempAsNode
vpart[1] = newNodeI(nkEmpty, value.info)
vpart[1] = newNodeI(nkTupleClassTy, value.info)
vpart[2] = value
v.add vpart
result.add(v)
@@ -235,6 +235,9 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym
field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
let t = skipIntLit(s.typ, idgen)
field.typ = t
if s.kind in {skLet, skVar, skField, skForVar}:
#field.bitsize = s.bitsize
field.alignment = s.alignment
assert t.kind != tyTyped
propagateToOwner(obj, t)
field.position = obj.n.len

View File

@@ -53,6 +53,7 @@ type
SymInfoPair* = object
sym*: PSym
info*: TLineInfo
isDecl*: bool
ModuleGraph* {.acyclic.} = ref object
ifaces*: seq[Iface] ## indexed by int32 fileIdx

View File

@@ -36,11 +36,14 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
localError(n.info, "only '/' supported with $package notation")
result = ""
else:
let modname = getModuleName(conf, n[2])
# hacky way to implement 'x / y /../ z':
result = getModuleName(conf, n1)
result.add renderTree(n0, {renderNoComments}).replace(" ")
result.add modname
if n0.kind == nkIdent and n0.ident.s[0] == '/':
let modname = getModuleName(conf, n[2])
# hacky way to implement 'x / y /../ z':
result = getModuleName(conf, n1)
result.add renderTree(n0, {renderNoComments}).replace(" ")
result.add modname
else:
result = ""
of nkPrefix:
when false:
if n[0].kind == nkIdent and n[0].ident.s == "$":

View File

@@ -417,14 +417,18 @@ To create a stacktrace, rerun compilation with './koch temp $1 <file>', see $2 f
proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string, ignoreMsg: bool) =
if msg in fatalMsgs:
if conf.cmd == cmdIdeTools: log(s)
quit(conf, msg)
if conf.cmd != cmdIdeTools or msg != errFatal:
quit(conf, msg)
if msg >= errMin and msg <= errMax or
(msg in warnMin..hintMax and msg in conf.warningAsErrors and not ignoreMsg):
inc(conf.errorCounter)
conf.exitcode = 1'i8
if conf.errorCounter >= conf.errorMax:
# only really quit when we're not in the new 'nim check --def' mode:
if conf.ideCmd == ideNone:
when defined(nimsuggest):
#we need to inform the user that something went wrong when initializing NimSuggest
raiseRecoverableError(s)
else:
quit(conf, msg)
elif eh == doAbort and conf.cmd != cmdIdeTools:
quit(conf, msg)

View File

@@ -12,7 +12,9 @@ import
ast, astalgo, modules, passes, condsyms,
options, sem, llstream, lineinfos, vm,
vmdef, modulegraphs, idents, os, pathutils,
passaux, scriptconfig, std/compilesettings
passaux,
scriptconfig, std/[compilesettings, tables]
type
Interpreter* = ref object ## Use Nim as an interpreter with this object
@@ -72,6 +74,9 @@ proc evalScript*(i: Interpreter; scriptStream: PLLStream = nil) =
assert i != nil
assert i.mainModule != nil, "no main module selected"
initStrTables(i.graph, i.mainModule)
i.graph.cacheSeqs.clear()
i.graph.cacheCounters.clear()
i.graph.cacheTables.clear()
i.mainModule.ast = nil
let s = if scriptStream != nil: scriptStream

View File

@@ -185,7 +185,7 @@ type
IdeCmd* = enum
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideChkFile, ideMod,
ideHighlight, ideOutline, ideKnown, ideMsg, ideProject, ideGlobalSymbols,
ideRecompile, ideChanged, ideType, ideDeclaration, ideExpand
ideRecompile, ideChanged, ideType, ideDeclaration, ideExpand, ideInlayHints
Feature* = enum ## experimental features; DO NOT RENAME THESE!
implicitDeref,
@@ -266,9 +266,24 @@ type
version*: int
endLine*: uint16
endCol*: int
inlayHintInfo*: SuggestInlayHint
Suggestions* = seq[Suggest]
SuggestInlayHintKind* = enum
sihkType = "Type",
sihkParameter = "Parameter"
SuggestInlayHint* = ref object
kind*: SuggestInlayHintKind
line*: int # Starts at 1
column*: int # Starts at 0
label*: string
paddingLeft*: bool
paddingRight*: bool
allowInsert*: bool
tooltip*: string
ProfileInfo* = object
time*: float
count*: int
@@ -402,6 +417,8 @@ type
expandNodeResult*: string
expandPosition*: TLineInfo
clientProcessId*: int
proc parseNimVersion*(a: string): NimVer =
# could be moved somewhere reusable
if a.len > 0:
@@ -1035,6 +1052,7 @@ proc `$`*(c: IdeCmd): string =
of ideRecompile: "recompile"
of ideChanged: "changed"
of ideType: "type"
of ideInlayHints: "inlayHints"
proc floatInt64Align*(conf: ConfigRef): int16 =
## Returns either 4 or 8 depending on reasons.

View File

@@ -816,7 +816,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
validPragmas: TSpecialWords,
comesFromPush, isStatement: bool): bool =
var it = n[i]
var key = if it.kind in nkPragmaCallKinds and it.len > 1: it[0] else: it
let keyDeep = it.kind in nkPragmaCallKinds and it.len > 1
var key = if keyDeep: it[0] else: it
if key.kind == nkBracketExpr:
processNote(c, it)
return
@@ -842,6 +843,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
if c.instCounter > 100:
globalError(c.config, it.info, "recursive dependency: " & userPragma.name.s)
if keyDeep:
localError(c.config, it.info, "user pragma cannot have arguments")
pragma(c, sym, userPragma.ast, validPragmas, isStatement)
n.sons[i..i] = userPragma.ast.sons # expand user pragma with its content
i.inc(userPragma.ast.len - 1) # inc by -1 is ok, user pragmas was empty

View File

@@ -203,12 +203,58 @@ proc commonType*(c: PContext; x, y: PType): PType =
result.addSonSkipIntLit(r, c.idgen)
proc endsInNoReturn(n: PNode): bool =
# check if expr ends in raise exception or call of noreturn proc
## check if expr ends the block like raising or call of noreturn procs do
result = false # assume it does return
template checkBranch(branch) =
if not endsInNoReturn(branch):
# proved a branch returns
return false
var it = n
# skip these beforehand, no special handling needed
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
it = it.lastSon
result = it.kind in nkLastBlockStmts or
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags
case it.kind
of nkIfStmt:
var hasElse = false
for branch in it:
checkBranch:
if branch.len == 2:
branch[1]
elif branch.len == 1:
hasElse = true
branch[0]
else:
raiseAssert "Malformed `if` statement during endsInNoReturn"
# none of the branches returned
result = hasElse # Only truly a no-return when it's exhaustive
of nkCaseStmt:
for i in 1 ..< it.len:
let branch = it[i]
checkBranch:
case branch.kind
of nkOfBranch:
branch[^1]
of nkElifBranch:
branch[1]
of nkElse:
branch[0]
else:
raiseAssert "Malformed `case` statement in endsInNoReturn"
# none of the branches returned
result = true
of nkTryStmt:
checkBranch(it[0])
for i in 1 ..< it.len:
let branch = it[i]
checkBranch(branch[^1])
# none of the branches returned
result = true
else:
result = it.kind in nkLastBlockStmts or
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags
proc commonType*(c: PContext; x: PType, y: PNode): PType =
# ignore exception raising branches in case/if expressions

View File

@@ -660,14 +660,18 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
onUse(info, s)
result = newSymNode(newInst, info)
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
assert n.kind == nkBracketExpr
proc setGenericParams(c: PContext, n: PNode) =
## sems generic params in subscript expression
for i in 1..<n.len:
let e = semExprWithType(c, n[i])
if e.typ == nil:
n[i].typ = errorType(c)
else:
n[i].typ = e.typ.skipTypes({tyTypeDesc})
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
assert n.kind == nkBracketExpr
setGenericParams(c, n)
var s = s
var a = n[0]
if a.kind == nkSym:

View File

@@ -946,10 +946,6 @@ proc bracketedMacro(n: PNode): PSym =
if result.kind notin {skMacro, skTemplate}:
result = nil
proc setGenericParams(c: PContext, n: PNode) =
for i in 1..<n.len:
n[i].typ = semTypeNode(c, n[i], nil)
proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
if efNoSemCheck notin flags and n.typ != nil and n.typ.kind == tyError:
return errorNode(c, n)
@@ -1054,7 +1050,6 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
msg.addDeclaredLocMaybe(c.config, typ)
localError(c.config, n.info, msg)
return errorNode(c, n)
result = nil
else:
result = m.call
instGenericConvertersSons(c, result, m)
@@ -1627,7 +1622,10 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
{tyInt..tyInt64}:
let idx = getOrdValue(n[1])
if idx >= 0 and idx < arr.len: n.typ = arr[toInt(idx)]
else: localError(c.config, n.info, "invalid index value for tuple subscript")
else:
localError(c.config, n.info,
"invalid index $1 in subscript for tuple of length $2" %
[$idx, $arr.len])
result = n
else:
result = nil
@@ -1805,7 +1803,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
result.add(n[1])
if mode == noOverloadedSubscript:
bracketNotFoundError(c, result)
return n
return errorNode(c, n)
else:
result = semExprNoType(c, result)
return result
@@ -2881,7 +2879,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
defer:
if isCompilerDebug():
echo ("<", c.config$n.info, n, ?.result.typ)
template directLiteral(typeKind: TTypeKind) =
if result.typ == nil:
if expectedType != nil and (
@@ -2927,6 +2925,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
else:
{checkUndeclared, checkModule, checkAmbiguity, checkPureEnumFields}
s = qualifiedLookUp(c, n, checks)
if s == nil:
return
if c.matchedConcept == nil: semCaptureSym(s, c.p.owner)
case s.kind
of skProc, skFunc, skMethod, skConverter, skIterator:
@@ -3214,7 +3214,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
of nkDefer:
if c.currentScope == c.topLevelScope:
localError(c.config, n.info, "defer statement not supported at top level")
openScope(c)
n[0] = semExpr(c, n[0])
closeScope(c)
if not n[0].typ.isEmptyType and not implicitlyDiscardable(n[0]):
localError(c.config, n.info, "'defer' takes a 'void' expression")
#localError(c.config, n.info, errGenerated, "'defer' not allowed in this context")

View File

@@ -371,7 +371,9 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
openScope(c)
let gp = n[genericParamsPos]
internalAssert c.config, gp.kind == nkGenericParams
if gp.kind != nkGenericParams:
# bug #22137
globalError(c.config, info, "generic instantiation too nested")
n[namePos] = newSymNode(result)
pushInfoContext(c.config, info, fn.detailedInfo)
var entry = TInstantiation.new

View File

@@ -51,7 +51,7 @@ proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
x[0] = newIdentNode(getIdent(c.cache, "[]"), n.info)
bracketNotFoundError(c, x)
#localError(c.config, n.info, "could not resolve: " & $n)
result = n
result = errorNode(c, n)
proc semArrPut(c: PContext; n: PNode; flags: TExprFlags): PNode =
# rewrite `[]=`(a, i, x) back to ``a[i] = x``.

View File

@@ -1076,7 +1076,7 @@ proc track(tracked: PEffects, n: PNode) =
elif child.kind == nkVarTuple and last.kind != nkEmpty:
for i in 0..<child.len-1:
if child[i].kind == nkEmpty or
child[i].kind == nkSym and child[i].sym.name.s == "_":
child[i].kind == nkSym and child[i].sym.name.id == ord(wUnderscore):
continue
initVar(tracked, child[i], volatileCheck=false)
if last.kind in {nkPar, nkTupleConstr}:

View File

@@ -181,13 +181,15 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil):
it[0] = forceBool(c, semExprWithType(c, it[0], expectedType = getSysType(c.graph, n.info, tyBool)))
it[1] = semExprBranch(c, it[1], flags, expectedType)
typ = commonType(c, typ, it[1])
expectedType = typ
if not endsInNoReturn(it[1]):
expectedType = typ
closeScope(c)
elif it.len == 1:
hasElse = true
it[0] = semExprBranchScope(c, it[0], expectedType)
typ = commonType(c, typ, it[0])
expectedType = typ
if not endsInNoReturn(it[0]):
expectedType = typ
else: illFormedAst(it, c.config)
if isEmptyType(typ) or typ.kind in {tyNil, tyUntyped} or
(not hasElse and efInTypeof notin flags):
@@ -227,8 +229,9 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil)
var typ = commonTypeBegin
var expectedType = expectedType
n[0] = semExprBranchScope(c, n[0], expectedType)
typ = commonType(c, typ, n[0].typ)
expectedType = typ
if not endsInNoReturn(n[0]):
typ = commonType(c, typ, n[0].typ)
expectedType = typ
var last = n.len - 1
var catchAllExcepts = 0
@@ -289,7 +292,8 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil)
if a.kind != nkFinally:
a[^1] = semExprBranchScope(c, a[^1], expectedType)
typ = commonType(c, typ, a[^1])
expectedType = typ
if not endsInNoReturn(a[^1]):
expectedType = typ
else:
a[^1] = semExprBranchScope(c, a[^1])
dec last
@@ -302,7 +306,8 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil)
result.typ = c.enforceVoidContext
else:
if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon, flags)
n[0] = fitNode(c, typ, n[0], n[0].info)
if not endsInNoReturn(n[0]):
n[0] = fitNode(c, typ, n[0], n[0].info)
for i in 1..last:
var it = n[i]
let j = it.len-1
@@ -383,7 +388,7 @@ proc addToVarSection(c: PContext; result: PNode; orig, identDefs: PNode) =
result.add identDefs
proc isDiscardUnderscore(v: PSym): bool =
if v.name.s == "_":
if v.name.id == ord(wUnderscore):
v.flags.incl(sfGenSym)
result = true
@@ -564,9 +569,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
if a.kind notin {nkIdentDefs, nkVarTuple}: illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var hasUserSpecifiedType = false
var typ: PType = nil
if a[^2].kind != nkEmpty:
typ = semTypeNode(c, a[^2], nil)
hasUserSpecifiedType = true
var typFlags: TTypeAllowedFlags
@@ -639,6 +646,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
addToVarSection(c, result, n, a)
continue
var v = semIdentDef(c, a[j], symkind, false)
when defined(nimsuggest):
v.hasUserSpecifiedType = hasUserSpecifiedType
styleCheckDef(c, v)
onDef(a[j].info, v)
if sfGenSym notin v.flags:
@@ -719,9 +728,11 @@ proc semConst(c: PContext, n: PNode): PNode =
if a.kind notin {nkConstDef, nkVarTuple}: illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var hasUserSpecifiedType = false
var typ: PType = nil
if a[^2].kind != nkEmpty:
typ = semTypeNode(c, a[^2], nil)
hasUserSpecifiedType = true
var typFlags: TTypeAllowedFlags
@@ -766,6 +777,8 @@ proc semConst(c: PContext, n: PNode): PNode =
for j in 0..<a.len-2:
var v = semIdentDef(c, a[j], skConst)
when defined(nimsuggest):
v.hasUserSpecifiedType = hasUserSpecifiedType
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
styleCheckDef(c, v)
@@ -1059,7 +1072,8 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil
var last = x.len-1
x[last] = semExprBranchScope(c, x[last], expectedType)
typ = commonType(c, typ, x[last])
expectedType = typ
if not endsInNoReturn(x[last]):
expectedType = typ
of nkElifBranch:
chckCovered = false
checkSonsLen(x, 2, c.config)
@@ -1067,13 +1081,15 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil
x[0] = forceBool(c, semExprWithType(c, x[0], expectedType = getSysType(c.graph, n.info, tyBool)))
x[1] = semExprBranch(c, x[1], expectedType = expectedType)
typ = commonType(c, typ, x[1])
expectedType = typ
if not endsInNoReturn(x[1]):
expectedType = typ
closeScope(c)
of nkElse:
checkSonsLen(x, 1, c.config)
x[0] = semExprBranchScope(c, x[0], expectedType)
typ = commonType(c, typ, x[0])
expectedType = typ
if not endsInNoReturn(x[0]):
expectedType = typ
if (chckCovered and covered == toCover(c, n[0].typ)) or hasElse:
message(c.config, x.info, warnUnreachableElse)
hasElse = true
@@ -2419,9 +2435,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType =
var m = n[i]
while m.kind in {nkStmtListExpr, nkStmtList} and m.len > 0: # from templates
m = m.lastSon
if m.kind in nkLastBlockStmts or
m.kind in nkCallKinds and m[0].kind == nkSym and
sfNoReturn in m[0].sym.flags:
if endsInNoReturn(m):
for j in i + 1..<n.len:
case n[j].kind
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkState: discard

View File

@@ -70,6 +70,9 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
onUse(info, s)
else:
result = n
elif i == 0:
# forced open but symbol not in scope, retain information
result = n
else:
# semantic checking requires a type; ``fitNode`` deals with it
# appropriately
@@ -110,14 +113,10 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
proc semMixinStmt(c: PContext, n: PNode, toMixin: var IntSet): PNode =
result = copyNode(n)
var count = 0
for i in 0..<n.len:
toMixin.incl(considerQuotedIdent(c, n[i]).id)
let x = symChoice(c, n[i], nil, scForceOpen)
inc count, x.len
result.add x
if count == 0:
result = newNodeI(nkEmpty, n.info)
proc replaceIdentBySym(c: PContext; n: var PNode, s: PNode) =
case n.kind
@@ -187,11 +186,12 @@ proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
incl(result.flags, sfShadowed)
proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
# locals default to 'gensym':
if n.kind == nkPragmaExpr and symBinding(n[1]) == spInject:
# locals default to 'gensym', fields default to 'inject':
if (n.kind == nkPragmaExpr and symBinding(n[1]) == spInject) or
k == skField:
# even if injected, don't produce a sym choice here:
#n = semTemplBody(c, n)
var x = n[0]
var x = n
while true:
case x.kind
of nkPostfix: x = x[1]
@@ -206,7 +206,7 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
illFormedAst(x, c.c.config)
let ident = getIdentNode(c, x)
if not isTemplParam(c, ident):
c.toInject.incl(x.ident.id)
if k != skField: c.toInject.incl(x.ident.id)
else:
replaceIdentBySym(c.c, n, ident)
else:
@@ -227,7 +227,7 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
closeScope(c)
let ident = getIdentNode(c, n)
if not isTemplParam(c, ident):
if n.kind != nkSym and not (n.kind == nkIdent and n.ident.s == "_"):
if n.kind != nkSym and not (n.kind == nkIdent and n.ident.id == ord(wUnderscore)):
let local = newGenSym(k, ident, c)
addPrelimDecl(c.c, local)
styleCheckDef(c.c, n.info, local)
@@ -331,21 +331,24 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
# close scope for parameters
closeScope(c)
proc semTemplIdentDef(c: var TemplCtx, a: PNode, symKind: TSymKind) =
checkMinSonsLen(a, 3, c.c.config)
when defined(nimsuggest):
inc c.c.inTypeContext
a[^2] = semTemplBody(c, a[^2])
when defined(nimsuggest):
dec c.c.inTypeContext
a[^1] = semTemplBody(c, a[^1])
for j in 0..<a.len-2:
addLocalDecl(c, a[j], symKind)
proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind; start = 0) =
for i in start..<n.len:
var a = n[i]
case a.kind:
of nkCommentStmt: continue
of nkIdentDefs, nkVarTuple, nkConstDef:
checkMinSonsLen(a, 3, c.c.config)
when defined(nimsuggest):
inc c.c.inTypeContext
a[^2] = semTemplBody(c, a[^2])
when defined(nimsuggest):
dec c.c.inTypeContext
a[^1] = semTemplBody(c, a[^1])
for j in 0..<a.len-2:
addLocalDecl(c, a[j], symKind)
semTemplIdentDef(c, a, symKind)
else:
illFormedAst(a, c.c.config)
@@ -485,6 +488,25 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
closeScope(c)
else:
a[2] = semTemplBody(c, a[2])
of nkObjectTy:
openScope(c)
result = semTemplBodySons(c, n)
closeScope(c)
of nkRecList:
for i in 0..<n.len:
var a = n[i]
case a.kind:
of nkCommentStmt, nkNilLit, nkSym, nkEmpty: continue
of nkIdentDefs:
semTemplIdentDef(c, a, skField)
of nkRecCase, nkRecWhen:
n[i] = semTemplBody(c, a)
else:
illFormedAst(a, c.c.config)
of nkRecCase:
semTemplIdentDef(c, n[0], skField)
for i in 1..<n.len:
n[i] = semTemplBody(c, n[i])
of nkProcDef, nkLambdaKinds:
result = semRoutineInTemplBody(c, n, skProc)
of nkFuncDef:
@@ -548,6 +570,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
# so we use the generic code for nkDotExpr too
let s = qualifiedLookUp(c.c, n, {})
if s != nil:
# mirror the nkIdent case
# do not symchoice a quoted template parameter (bug #2390):
if s.owner == c.owner and s.kind == skParam and
n.kind == nkAccQuoted and n.len == 1:
@@ -559,7 +582,9 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
elif contains(c.toMixin, s.name.id):
return symChoice(c.c, n, s, scForceOpen, c.noGenSym > 0)
else:
return symChoice(c.c, n, s, scOpen, c.noGenSym > 0)
if s.kind in {skType, skVar, skLet, skConst}:
discard qualifiedLookUp(c.c, n, {checkAmbiguity, checkModule})
return semTemplSymbol(c.c, n, s, c.noGenSym > 0)
if n.kind == nkDotExpr:
result = n
result[0] = semTemplBody(c, n[0])
@@ -653,6 +678,9 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
# a template's parameters are not gensym'ed even if that was originally the
# case as we determine whether it's a template parameter in the template
# body by the absence of the sfGenSym flag:
let retType = s.typ[0]
if retType != nil and retType.kind != tyUntyped:
allUntyped = false
for i in 1..<s.typ.n.len:
let param = s.typ.n[i].sym
param.flags.incl sfTemplateParam

View File

@@ -142,6 +142,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
result.n.add symNode
styleCheckDef(c, e)
onDef(e.info, e)
suggestSym(c.graph, e.info, e, c.graph.usageSym)
if sfGenSym notin e.flags:
if not isPure:
if overloadableEnums in c.features:
@@ -276,7 +277,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
elif not isOrdinalType(rangeT[0]) and rangeT[0].kind notin {tyFloat..tyFloat128} or
rangeT[0].kind == tyBool:
localError(c.config, n.info, "ordinal or float type expected")
localError(c.config, n.info, "ordinal or float type expected, but got " & typeToString(rangeT[0]))
elif enumHasHoles(rangeT[0]):
localError(c.config, n.info, "enum '$1' has holes" % typeToString(rangeT[0]))
@@ -287,9 +288,8 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
else:
result.n.add semConstExpr(c, range[i])
if (result.n[0].kind in {nkFloatLit..nkFloat64Lit} and result.n[0].floatVal.isNaN) or
(result.n[1].kind in {nkFloatLit..nkFloat64Lit} and result.n[1].floatVal.isNaN):
localError(c.config, n.info, "NaN is not a valid start or end for a range")
if result.n[i].kind in {nkFloatLit..nkFloat64Lit} and result.n[i].floatVal.isNaN:
localError(c.config, n.info, "NaN is not a valid range " & (if i == 0: "start" else: "end"))
if weakLeValue(result.n[0], result.n[1]) == impNo:
localError(c.config, n.info, "range is empty")
@@ -882,12 +882,18 @@ proc skipGenericInvocation(t: PType): PType {.inline.} =
while result.kind in {tyGenericInst, tyGenericBody, tyRef, tyPtr, tyAlias, tySink, tyOwned}:
result = lastSon(result)
proc addInheritedFields(c: PContext, check: var IntSet, pos: var int,
obj: PType) =
assert obj.kind == tyObject
if (obj.len > 0) and (obj[0] != nil):
addInheritedFields(c, check, pos, obj[0].skipGenericInvocation)
addInheritedFieldsAux(c, check, pos, obj.n)
proc tryAddInheritedFields(c: PContext, check: var IntSet, pos: var int,
obj: PType, n: PNode, isPartial = false): bool =
if (not isPartial) and (obj.kind notin {tyObject, tyGenericParam} or tfFinal in obj.flags):
localError(c.config, n.info, "Cannot inherit from: '" & $obj & "'")
result = false
elif obj.kind == tyObject:
result = true
if (obj.len > 0) and (obj[0] != nil):
result = result and tryAddInheritedFields(c, check, pos, obj[0].skipGenericInvocation, n)
addInheritedFieldsAux(c, check, pos, obj.n)
else:
result = true
proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType =
if n.len == 0:
@@ -914,7 +920,9 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType
if concreteBase.sym != nil and concreteBase.sym.magic == mException and
sfSystemModule notin c.module.flags:
message(c.config, n.info, warnInheritFromException, "")
addInheritedFields(c, check, pos, concreteBase)
if not tryAddInheritedFields(c, check, pos, concreteBase, n):
return newType(tyError, nextTypeId c.idgen, result.owner)
else:
if concreteBase.kind != tyError:
localError(c.config, n[1].info, "inheritance only works with non-final objects; " &
@@ -932,7 +940,9 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType
result.n = newNodeI(nkRecList, n.info)
else:
# partial object so add things to the check
addInheritedFields(c, check, pos, result)
if not tryAddInheritedFields(c, check, pos, result, n, isPartial = true):
return newType(tyError, nextTypeId c.idgen, result.owner)
semRecordNodeAux(c, n[2], check, pos, result.n, result)
if n[0].kind != nkEmpty:
# dummy symbol for `pragma`:
@@ -1443,19 +1453,21 @@ proc semGenericParamInInvocation(c: PContext, n: PNode): PType =
result = semTypeNode(c, n, nil)
n.typ = makeTypeDesc(c, result)
proc semObjectTypeForInheritedGenericInst(c: PContext, n: PNode, t: PType) =
proc trySemObjectTypeForInheritedGenericInst(c: PContext, n: PNode, t: PType): bool =
var
check = initIntSet()
pos = 0
let
realBase = t[0]
base = skipTypesOrNil(realBase, skipPtrs)
result = true
if base.isNil:
localError(c.config, n.info, errIllegalRecursionInTypeX % "object")
else:
let concreteBase = skipGenericInvocation(base)
if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags:
addInheritedFields(c, check, pos, concreteBase)
if not tryAddInheritedFields(c, check, pos, concreteBase, n):
return false
else:
if concreteBase.kind != tyError:
localError(c.config, n.info, errInheritanceOnlyWithNonFinalObjects)
@@ -1535,7 +1547,8 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
return errorType(c)
if tx != result and tx.kind == tyObject:
if tx[0] != nil:
semObjectTypeForInheritedGenericInst(c, n, tx)
if not trySemObjectTypeForInheritedGenericInst(c, n, tx):
return newOrPrevType(tyError, prev, c)
var position = 0
recomputeFieldPositions(tx, tx.n, position)

View File

@@ -43,7 +43,8 @@ proc searchInstTypes*(g: ModuleGraph; key: PType): PType =
# XXX: This happens for prematurely cached
# types such as Channel[empty]. Why?
# See the notes for PActor in handleGenericInvocation
return
# if this is return the same type gets cached more than it needs to
continue
if not sameFlags(inst, key):
continue
@@ -200,7 +201,7 @@ proc hasValuelessStatics(n: PNode): bool =
a
proc doThing(_: MyThing)
]#
if n.safeLen == 0:
if n.safeLen == 0 and n.kind != nkEmpty: # Some empty nodes can get in here
n.typ == nil or n.typ.kind == tyStatic
else:
for x in n:

View File

@@ -211,7 +211,7 @@ proc sumGeneric(t: PType): int =
# and Foo[T] has the value 2 so that we know Foo[Foo[T]] is more
# specific than Foo[T].
var t = t
var isvar = 1
var isvar = 0
while true:
case t.kind
of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyUncheckedArray,
@@ -247,6 +247,8 @@ proc sumGeneric(t: PType): int =
of tyBool, tyChar, tyEnum, tyObject, tyPointer,
tyString, tyCstring, tyInt..tyInt64, tyFloat..tyFloat128,
tyUInt..tyUInt64, tyCompositeTypeClass:
return isvar + 1
of tyBuiltInTypeClass:
return isvar
else:
return 0
@@ -362,7 +364,7 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
of tyOwned:
# bug #11257: the comparison system.`==`[T: proc](x, y: T) works
# better without the 'owned' type:
if f != nil and f.len > 0 and f[0].skipTypes({tyBuiltInTypeClass}).kind == tyProc:
if f != nil and f.len > 0 and f[0].skipTypes({tyBuiltInTypeClass, tyOr}).kind == tyProc:
result = t.lastSon
else:
result = t
@@ -1169,7 +1171,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyArray:
var fRange = f[0]
var aRange = a[0]
if fRange.kind == tyGenericParam:
if fRange.kind in {tyGenericParam, tyAnything}:
var prev = PType(idTableGet(c.bindings, fRange))
if prev == nil:
put(c, fRange, a[0])
@@ -1264,8 +1266,6 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
result = isSubtype
else:
result = isNone
elif tfNotNil in f.flags and tfNotNil notin a.flags:
result = isNilConversion
of tyNil: result = isNone
else: discard
of tyOrdinal:
@@ -1362,11 +1362,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
else: discard
of tyString:
case a.kind
of tyString:
if tfNotNil in f.flags and tfNotNil notin a.flags:
result = isNilConversion
else:
result = isEqual
of tyString: result = isEqual
of tyNil: result = isNone
else: discard
of tyCstring:
@@ -1501,6 +1497,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
if x.kind == tyGenericInvocation:
if f[0] == x[0]:
for i in 1..<f.len:
# Handle when checking against a generic that isn't fully instantiated
if i >= x.len: return
let tr = typeRel(c, f[i], x[i], flags)
if tr <= isSubtype: return
result = isGeneric
@@ -1636,7 +1634,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
elif a.len > 0 and a.lastSon == f:
# Needed for checking `Y` == `Addable` in the following
#[
type
type
Addable = concept a, type A
a + a is A
MyType[T: Addable; Y: static T] = object
@@ -1894,10 +1892,21 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
else:
result.typ = errorType(c)
else:
result.typ = f.skipTypes({tySink, tyVar})
result.typ = f.skipTypes({tySink})
# keep varness
if arg.typ != nil and arg.typ.kind == tyVar:
result.typ = toVar(result.typ, tyVar, c.idgen)
else:
result.typ = result.typ.skipTypes({tyVar})
if result.typ == nil: internalError(c.graph.config, arg.info, "implicitConv")
result.add c.graph.emptyNode
result.add arg
if arg.typ != nil and arg.typ.kind == tyLent:
let a = newNodeIT(nkHiddenDeref, arg.info, arg.typ[0])
a.add arg
result.add a
else:
result.add arg
proc isLValue(c: PContext; n: PNode): bool {.inline.} =
let aa = isAssignable(nil, n)

View File

@@ -81,7 +81,16 @@ proc cmpSuggestions(a, b: Suggest): int =
# independent of hashing order:
result = cmp(a.name[], b.name[])
proc getTokenLenFromSource(conf: ConfigRef; ident: string; info: TLineInfo): int =
proc scanForTrailingAsterisk(line: string, start: int): int =
result = 0
while start+result < line.len and line[start+result] in {' ', '\t'}:
inc result
if start+result < line.len and line[start+result] == '*':
inc result
else:
result = 0
proc getTokenLenFromSource(conf: ConfigRef; ident: string; info: TLineInfo; skipTrailingAsterisk: bool = false): int =
let
line = sourceLine(conf, info)
column = toColumn(info)
@@ -103,8 +112,10 @@ proc getTokenLenFromSource(conf: ConfigRef; ident: string; info: TLineInfo): int
result = 0
elif ident[0] in linter.Letters and ident[^1] != '=':
result = identLen(line, column)
if cmpIgnoreStyle(line[column..column + result - 1], ident) != 0:
if cmpIgnoreStyle(line[column..column + result - 1], ident[0..min(result-1,len(ident)-1)]) != 0:
result = 0
if skipTrailingAsterisk and result > 0:
result += scanForTrailingAsterisk(line, column + result)
else:
var sourceIdent: string
result = parseWhile(line, sourceIdent,
@@ -154,7 +165,10 @@ proc symToSuggest*(g: ModuleGraph; s: PSym, isLocal: bool, section: IdeCmd, info
result.qualifiedPath.add(s.name.s)
if s.typ != nil:
result.forth = typeToString(s.typ)
if section == ideInlayHints:
result.forth = typeToString(s.typ, preferInlayHint)
else:
result.forth = typeToString(s.typ, preferInferredEffects)
else:
result.forth = ""
when defined(nimsuggest) and not defined(noDocgen) and not defined(leanCompiler):
@@ -173,58 +187,90 @@ proc symToSuggest*(g: ModuleGraph; s: PSym, isLocal: bool, section: IdeCmd, info
result.filePath = toFullPath(g.config, infox)
result.line = toLinenumber(infox)
result.column = toColumn(infox)
result.tokenLen = if section != ideHighlight:
result.tokenLen = if section notin {ideHighlight, ideInlayHints}:
s.name.s.len
else:
getTokenLenFromSource(g.config, s.name.s, infox)
getTokenLenFromSource(g.config, s.name.s, infox, section == ideInlayHints)
result.version = g.config.suggestVersion
result.endLine = endLine
result.endCol = endCol
proc `$`*(suggest: Suggest): string =
result = $suggest.section
proc `$`*(suggest: SuggestInlayHint): string =
result = $suggest.kind
result.add(sep)
if suggest.section == ideHighlight:
if suggest.symkind.TSymKind == skVar and suggest.isGlobal:
result.add("skGlobalVar")
elif suggest.symkind.TSymKind == skLet and suggest.isGlobal:
result.add("skGlobalLet")
result.add($suggest.line)
result.add(sep)
result.add($suggest.column)
result.add(sep)
result.add(suggest.label)
result.add(sep)
result.add($suggest.paddingLeft)
result.add(sep)
result.add($suggest.paddingRight)
result.add(sep)
result.add($suggest.allowInsert)
result.add(sep)
result.add(suggest.tooltip)
proc `$`*(suggest: Suggest): string =
if suggest.section == ideInlayHints:
result = $suggest.inlayHintInfo
else:
result = $suggest.section
result.add(sep)
if suggest.section == ideHighlight:
if suggest.symkind.TSymKind == skVar and suggest.isGlobal:
result.add("skGlobalVar")
elif suggest.symkind.TSymKind == skLet and suggest.isGlobal:
result.add("skGlobalLet")
else:
result.add($suggest.symkind.TSymKind)
result.add(sep)
result.add($suggest.line)
result.add(sep)
result.add($suggest.column)
result.add(sep)
result.add($suggest.tokenLen)
else:
result.add($suggest.symkind.TSymKind)
result.add(sep)
result.add($suggest.line)
result.add(sep)
result.add($suggest.column)
result.add(sep)
result.add($suggest.tokenLen)
else:
result.add($suggest.symkind.TSymKind)
result.add(sep)
if suggest.qualifiedPath.len != 0:
result.add(suggest.qualifiedPath.join("."))
result.add(sep)
result.add(suggest.forth)
result.add(sep)
result.add(suggest.filePath)
result.add(sep)
result.add($suggest.line)
result.add(sep)
result.add($suggest.column)
result.add(sep)
when defined(nimsuggest) and not defined(noDocgen) and not defined(leanCompiler):
result.add(suggest.doc.escape)
if suggest.version in {0, 3}:
result.add(sep)
result.add($suggest.quality)
if suggest.section == ideSug:
if suggest.qualifiedPath.len != 0:
result.add(suggest.qualifiedPath.join("."))
result.add(sep)
result.add(suggest.forth)
result.add(sep)
result.add(suggest.filePath)
result.add(sep)
result.add($suggest.line)
result.add(sep)
result.add($suggest.column)
result.add(sep)
when defined(nimsuggest) and not defined(noDocgen) and not defined(leanCompiler):
result.add(suggest.doc.escape)
if suggest.version in {0, 3}:
result.add(sep)
result.add($suggest.prefix)
result.add($suggest.quality)
if suggest.section == ideSug:
result.add(sep)
result.add($suggest.prefix)
if (suggest.version == 3 and suggest.section in {ideOutline, ideExpand}):
result.add(sep)
result.add($suggest.endLine)
result.add(sep)
result.add($suggest.endCol)
if (suggest.version == 3 and suggest.section in {ideOutline, ideExpand}):
result.add(sep)
result.add($suggest.endLine)
result.add(sep)
result.add($suggest.endCol)
proc suggestToSuggestInlayHint*(sug: Suggest): SuggestInlayHint =
SuggestInlayHint(
kind: sihkType,
line: sug.line,
column: sug.column + sug.tokenLen,
label: ": " & sug.forth,
paddingLeft: false,
paddingRight: false,
allowInsert: true,
tooltip: ""
)
proc suggestResult*(conf: ConfigRef; s: Suggest) =
if not isNil(conf.suggestionResultHook):
@@ -439,7 +485,15 @@ proc suggestFieldAccess(c: PContext, n, field: PNode, outputs: var Suggestions)
if t[0] == nil: break
t = skipTypes(t[0], skipPtrs)
elif typ.kind == tyTuple and typ.n != nil:
suggestSymList(c, typ.n, field, n.info, outputs)
# All tuple fields are in scope
# So go through each field and add it to the suggestions (If it passes the filter)
for node in typ.n:
if node.kind == nkSym:
let s = node.sym
var pm: PrefixMatch
if filterSym(s, field, pm):
outputs.add(symToSuggest(c.graph, s, isLocal=true, ideSug, n.info,
s.getQuality, pm, c.inTypeContext > 0, 0))
suggestOperations(c, n, field, orig, outputs)
if typ != orig:
@@ -498,7 +552,7 @@ proc findDefinition(g: ModuleGraph; info: TLineInfo; s: PSym; usageSym: var PSym
if s.isNil: return
if isTracked(info, g.config.m.trackPos, s.name.s.len) or (s == usageSym and sfForward notin s.flags):
suggestResult(g.config, symToSuggest(g, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0, useSuppliedInfo = s == usageSym))
if sfForward notin s.flags and g.config.suggestVersion != 3:
if sfForward notin s.flags and g.config.suggestVersion < 3:
suggestQuit()
else:
usageSym = s
@@ -513,7 +567,7 @@ proc suggestSym*(g: ModuleGraph; info: TLineInfo; s: PSym; usageSym: var PSym; i
## misnamed: should be 'symDeclared'
let conf = g.config
when defined(nimsuggest):
g.suggestSymbols.mgetOrPut(info.fileIndex, @[]).add SymInfoPair(sym: s, info: info)
g.suggestSymbols.mgetOrPut(info.fileIndex, @[]).add SymInfoPair(sym: s, info: info, isDecl: isDecl)
if conf.suggestVersion == 0:
if s.allUsages.len == 0:
@@ -712,7 +766,7 @@ proc suggestSentinel*(c: PContext) =
when defined(nimsuggest):
proc onDef(graph: ModuleGraph, s: PSym, info: TLineInfo) =
if graph.config.suggestVersion == 3 and info.exactEquals(s.info):
if graph.config.suggestVersion >= 3 and info.exactEquals(s.info):
suggestSym(graph, info, s, graph.usageSym)
template getPContext(): untyped =

View File

@@ -316,6 +316,14 @@ proc introduceNewLocalVars(c: PTransf, n: PNode): PNode =
if a.kind == nkSym:
n[1] = transformSymAux(c, a)
return n
of nkProcDef: # todo optimize nosideeffects?
result = newTransNode(n)
let x = freshVar(c, n[namePos].sym)
idNodeTablePut(c.transCon.mapping, n[namePos].sym, x)
result[namePos] = x # we have to copy proc definitions for iters
for i in 1..<n.len:
result[i] = introduceNewLocalVars(c, n[i])
result[namePos].sym.ast = result
else:
result = newTransNode(n)
for i in 0..<n.len:
@@ -638,7 +646,7 @@ proc findWrongOwners(c: PTransf, n: PNode) =
else:
for i in 0..<n.safeLen: findWrongOwners(c, n[i])
proc isSimpleIteratorVar(c: PTransf; iter: PSym): bool =
proc isSimpleIteratorVar(c: PTransf; iter: PSym; call: PNode; owner: PSym): bool =
proc rec(n: PNode; owner: PSym; dangerousYields: var int) =
case n.kind
of nkEmpty..nkNilLit: discard
@@ -650,9 +658,22 @@ proc isSimpleIteratorVar(c: PTransf; iter: PSym): bool =
else:
for c in n: rec(c, owner, dangerousYields)
proc recSym(n: PNode; owner: PSym; sameOwner: var bool) =
case n.kind
of {nkEmpty..nkNilLit} - {nkSym}: discard
of nkSym:
if n.sym.owner != owner:
sameOwner = false
else:
for c in n: recSym(c, owner, sameOwner)
var dangerousYields = 0
rec(getBody(c.graph, iter), iter, dangerousYields)
result = dangerousYields == 0
# the parameters should be owned by the owner
# bug #22237
for i in 1..<call.len:
recSym(call[i], owner, result)
template destructor(t: PType): PSym = getAttachedOp(c.graph, t, attachedDestructor)
@@ -696,7 +717,7 @@ proc transformFor(c: PTransf, n: PNode): PNode =
for j in 0..<n[i].len-1:
addVar(v, copyTree(n[i][j])) # declare new vars
else:
if n[i].kind == nkSym and isSimpleIteratorVar(c, iter):
if n[i].kind == nkSym and isSimpleIteratorVar(c, iter, call, n[i].sym.owner):
incl n[i].sym.flags, sfCursor
addVar(v, copyTree(n[i])) # declare new vars
stmtList.add(v)

View File

@@ -11,7 +11,7 @@
import
intsets, ast, astalgo, trees, msgs, strutils, platform, renderer, options,
lineinfos, int128, modulegraphs, astmsgs
lineinfos, int128, modulegraphs, astmsgs, wordrecg
type
TPreferedDesc* = enum
@@ -25,6 +25,8 @@ type
preferMixed,
# most useful, shows: symbol + resolved symbols if it differs, e.g.:
# tuple[a: MyInt{int}, b: float]
preferInlayHint,
preferInferredEffects,
TTypeRelation* = enum # order is important!
isNone, isConvertible,
@@ -372,15 +374,18 @@ proc canFormAcycleAux(g: ModuleGraph; marker: var IntSet, typ: PType, orig: PTyp
proc canFormAcycleNode(g: ModuleGraph; marker: var IntSet, n: PNode, orig: PType, withRef: bool, hasTrace: bool): bool =
result = false
if n != nil:
result = canFormAcycleAux(g, marker, n.typ, orig, withRef, hasTrace)
if not result:
case n.kind
of nkNone..nkNilLit:
discard
else:
for i in 0..<n.len:
result = canFormAcycleNode(g, marker, n[i], orig, withRef, hasTrace)
if result: return
var hasCursor = n.kind == nkSym and sfCursor in n.sym.flags
# cursor fields don't own the refs, which cannot form reference cycles
if hasTrace or not hasCursor:
result = canFormAcycleAux(g, marker, n.typ, orig, withRef, hasTrace)
if not result:
case n.kind
of nkNone..nkNilLit:
discard
else:
for i in 0..<n.len:
result = canFormAcycleNode(g, marker, n[i], orig, withRef, hasTrace)
if result: return
proc sameBackendType*(x, y: PType): bool
@@ -500,7 +505,7 @@ const
"void", "iterable"]
const preferToResolveSymbols = {preferName, preferTypeName, preferModuleInfo,
preferGenericArg, preferResolved, preferMixed}
preferGenericArg, preferResolved, preferMixed, preferInlayHint, preferInferredEffects}
template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
tc.add concrete
@@ -534,7 +539,10 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
if prefer in preferToResolveSymbols and t.sym != nil and
sfAnon notin t.sym.flags and t.kind != tySequence:
if t.kind == tyInt and isIntLit(t):
result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
if prefer == preferInlayHint:
result = t.sym.name.s
else:
result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
elif t.kind == tyAlias and t[0].kind != tyAlias:
result = typeToString(t[0])
elif prefer in {preferResolved, preferMixed}:
@@ -550,7 +558,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
result = t.sym.name.s
if prefer == preferMixed and result != t.sym.name.s:
result = t.sym.name.s & "{" & result & "}"
elif prefer in {preferName, preferTypeName} or t.sym.owner.isNil:
elif prefer in {preferName, preferTypeName, preferInlayHint, preferInferredEffects} or t.sym.owner.isNil:
# note: should probably be: {preferName, preferTypeName, preferGenericArg}
result = t.sym.name.s
if t.kind == tyGenericParam and t.len > 0:
@@ -569,8 +577,11 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
if not isIntLit(t) or prefer == preferExported:
result = typeToStr[t.kind]
else:
if prefer == preferGenericArg:
case prefer:
of preferGenericArg:
result = $t.n.intVal
of preferInlayHint:
result = "int"
else:
result = "int literal(" & $t.n.intVal & ")"
of tyGenericInst, tyGenericInvocation:
@@ -743,6 +754,15 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
result.add(')')
if t.len > 0 and t[0] != nil: result.add(": " & typeToString(t[0]))
var prag = if t.callConv == ccNimCall and tfExplicitCallConv notin t.flags: "" else: $t.callConv
var hasImplicitRaises = false
if not isNil(t.owner) and not isNil(t.owner.ast) and (t.owner.ast.len - 1) >= pragmasPos:
let pragmasNode = t.owner.ast[pragmasPos]
let raisesSpec = effectSpec(pragmasNode, wRaises)
if not isNil(raisesSpec):
addSep(prag)
prag.add("raises: ")
prag.add($raisesSpec)
hasImplicitRaises = true
if tfNoSideEffect in t.flags:
addSep(prag)
prag.add("noSideEffect")
@@ -752,6 +772,20 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
if t.lockLevel.ord != UnspecifiedLockLevel.ord:
addSep(prag)
prag.add("locks: " & $t.lockLevel)
if not hasImplicitRaises and prefer == preferInferredEffects and not isNil(t.owner) and not isNil(t.owner.typ) and not isNil(t.owner.typ.n) and (t.owner.typ.n.len > 0):
let effects = t.owner.typ.n[0]
if effects.kind == nkEffectList and effects.len == effectListLen:
var inferredRaisesStr = ""
let effs = effects[exceptionEffects]
if not isNil(effs):
for eff in items(effs):
if not isNil(eff):
addSep(inferredRaisesStr)
inferredRaisesStr.add($eff.typ)
addSep(prag)
prag.add("raises: <inferred> [")
prag.add(inferredRaisesStr)
prag.add("]")
if prag.len != 0: result.add("{." & prag & ".}")
of tyVarargs:
result = typeToStr[t.kind] % typeToString(t[0])
@@ -797,11 +831,11 @@ proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
result = firstOrd(conf, lastSon(t))
of tyOrdinal:
if t.len > 0: result = firstOrd(conf, lastSon(t))
else: internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
else: fatal(conf, unknownLineInfo, "invalid kind for firstOrd(" & $t.kind & ')')
of tyUncheckedArray, tyCstring:
result = Zero
else:
internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
fatal(conf, unknownLineInfo, "invalid kind for firstOrd(" & $t.kind & ')')
result = Zero
proc firstFloat*(t: PType): BiggestFloat =
@@ -856,11 +890,11 @@ proc lastOrd*(conf: ConfigRef; t: PType): Int128 =
of tyProxy: result = Zero
of tyOrdinal:
if t.len > 0: result = lastOrd(conf, lastSon(t))
else: internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
else: fatal(conf, unknownLineInfo, "invalid kind for lastOrd(" & $t.kind & ')')
of tyUncheckedArray:
result = Zero
else:
internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
fatal(conf, unknownLineInfo, "invalid kind for lastOrd(" & $t.kind & ')')
result = Zero
proc lastFloat*(t: PType): BiggestFloat =
@@ -1223,7 +1257,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
assert a[0].len == 0
assert b.len == 1
assert b[0].len == 0
result = a[0].kind == b[0].kind
result = a[0].kind == b[0].kind and sameFlags(a[0], b[0])
if result and a[0].kind == tyProc and IgnoreCC notin c.flags:
let ecc = a[0].flags * {tfExplicitCallConv}
result = ecc == b[0].flags * {tfExplicitCallConv} and
(ecc == {} or a[0].callConv == b[0].callConv)
of tyGenericInvocation, tyGenericBody, tySequence, tyOpenArray, tySet, tyRef,
tyPtr, tyVar, tyLent, tySink, tyUncheckedArray, tyArray, tyProc, tyVarargs,
tyOrdinal, tyCompositeTypeClass, tyUserTypeClass, tyUserTypeClassInst,

View File

@@ -772,6 +772,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
else:
if src.kind notin {nkEmpty..nkTripleStrLit} and idx <% src.len:
takeAddress regs[ra], src.sons[idx]
elif src.kind in nkStrKinds and idx <% src.strVal.len:
regs[ra] = takeCharAddress(c, src, idx, pc)
else:
stackTrace(c, tos, pc, formatErrorIndexBound(idx, src.safeLen-1))
of opcLdStrIdx:
@@ -995,7 +997,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcLenCstring:
decodeBImm(rkInt)
assert regs[rb].kind == rkNode
regs[ra].intVal = regs[rb].node.strVal.cstring.len - imm
if regs[rb].node.kind == nkNilLit:
regs[ra].intVal = -imm
else:
regs[ra].intVal = regs[rb].node.strVal.cstring.len - imm
of opcIncl:
decodeB(rkNode)
let b = regs[rb].regToNode
@@ -1193,6 +1198,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcEqStr:
decodeBC(rkInt)
regs[ra].intVal = ord(regs[rb].node.strVal == regs[rc].node.strVal)
of opcEqCString:
decodeBC(rkInt)
let bNil = regs[rb].node.kind == nkNilLit
let cNil = regs[rc].node.kind == nkNilLit
regs[ra].intVal = ord((bNil and cNil) or
(not bNil and not cNil and regs[rb].node.strVal == regs[rc].node.strVal))
of opcLeStr:
decodeBC(rkInt)
regs[ra].intVal = ord(regs[rb].node.strVal <= regs[rc].node.strVal)
@@ -1463,7 +1474,13 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node
c.currentExceptionA = raised
# Set the `name` field of the exception
c.currentExceptionA[2].skipColon.strVal = c.currentExceptionA.typ.sym.name.s
var exceptionNameNode = newStrNode(nkStrLit, c.currentExceptionA.typ.sym.name.s)
if c.currentExceptionA[2].kind == nkExprColonExpr:
exceptionNameNode.typ = c.currentExceptionA[2][1].typ
c.currentExceptionA[2][1] = exceptionNameNode
else:
exceptionNameNode.typ = c.currentExceptionA[2].typ
c.currentExceptionA[2] = exceptionNameNode
c.exceptionInstr = pc
var frame = tos

View File

@@ -99,7 +99,7 @@ type
opcLeFloat, opcLtFloat, opcLeu, opcLtu,
opcEqRef, opcEqNimNode, opcSameNodeType,
opcXor, opcNot, opcUnaryMinusInt, opcUnaryMinusFloat, opcBitnotInt,
opcEqStr, opcLeStr, opcLtStr, opcEqSet, opcLeSet, opcLtSet,
opcEqStr, opcEqCString, opcLeStr, opcLtStr, opcEqSet, opcLeSet, opcLtSet,
opcMulSet, opcPlusSet, opcMinusSet, opcConcatStr,
opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq,
opcIsNil, opcOf, opcIs,

View File

@@ -30,7 +30,7 @@
import tables
import
strutils, ast, types, msgs, renderer, vmdef, trees,
strutils, ast, types, msgs, renderer, vmdef,
intsets, magicsys, options, lowerings, lineinfos, transf, astmsgs
from modulegraphs import getBody
@@ -408,13 +408,19 @@ proc genIf(c: PCtx, n: PNode; dest: var TDest) =
c.gen(it[0], tmp)
elsePos = c.xjmp(it[0], opcFJmp, tmp) # if false
c.clearDest(n, dest)
c.gen(it[1], dest) # then part
if isEmptyType(it[1].typ): # maybe noreturn call, don't touch `dest`
c.gen(it[1])
else:
c.gen(it[1], dest) # then part
if i < n.len-1:
endings.add(c.xjmp(it[1], opcJmp, 0))
c.patch(elsePos)
else:
c.clearDest(n, dest)
c.gen(it[0], dest)
if isEmptyType(it[0].typ): # maybe noreturn call, don't touch `dest`
c.gen(it[0])
else:
c.gen(it[0], dest)
for endPos in endings: c.patch(endPos)
c.clearDest(n, dest)
@@ -508,17 +514,25 @@ proc genCase(c: PCtx; n: PNode; dest: var TDest) =
let it = n[i]
if it.len == 1:
# else stmt:
if it[0].kind != nkNilLit or it[0].typ != nil:
let body = it[0]
if body.kind != nkNilLit or body.typ != nil:
# an nkNilLit with nil for typ implies there is no else branch, this
# avoids unused related errors as we've already consumed the dest
c.gen(it[0], dest)
if isEmptyType(body.typ): # maybe noreturn call, don't touch `dest`
c.gen(body)
else:
c.gen(body, dest)
else:
let b = rawGenLiteral(c, it)
c.gABx(it, opcBranch, tmp, b)
let elsePos = c.xjmp(it.lastSon, opcFJmp, tmp)
c.gen(it.lastSon, dest)
let body = it.lastSon
let elsePos = c.xjmp(body, opcFJmp, tmp)
if isEmptyType(body.typ): # maybe noreturn call, don't touch `dest`
c.gen(body)
else:
c.gen(body, dest)
if i < n.len-1:
endings.add(c.xjmp(it.lastSon, opcJmp, 0))
endings.add(c.xjmp(body, opcJmp, 0))
c.patch(elsePos)
c.clearDest(n, dest)
for endPos in endings: c.patch(endPos)
@@ -534,7 +548,10 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
var endings: seq[TPosition] = @[]
let ehPos = c.xjmp(n, opcTry, 0)
c.gen(n[0], dest)
if isEmptyType(n[0].typ): # maybe noreturn call, don't touch `dest`
c.gen(n[0])
else:
c.gen(n[0], dest)
c.clearDest(n, dest)
# Add a jump past the exception handling code
let jumpToFinally = c.xjmp(n, opcJmp, 0)
@@ -552,7 +569,11 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
if it.len == 1:
# general except section:
c.gABx(it, opcExcept, 0, 0)
c.gen(it.lastSon, dest)
let body = it.lastSon
if isEmptyType(body.typ): # maybe noreturn call, don't touch `dest`
c.gen(body)
else:
c.gen(body, dest)
c.clearDest(n, dest)
if i < n.len:
endings.add(c.xjmp(it, opcJmp, 0))
@@ -884,6 +905,8 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
let dst = n[0].typ.skipTypes(abstractRange)#.kind
let srcSize = getSize(c.config, src)
let dstSize = getSize(c.config, dst)
const unsupportedCastDifferentSize =
"VM does not support 'cast' from $1 with size $2 to $3 with size $4 due to different sizes"
if src.kind in allowedIntegers and dst.kind in allowedIntegers:
let tmp = c.genx(n[1])
if dest < 0: dest = c.getTemp(n[0].typ)
@@ -900,8 +923,11 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
# is smaller than source.
c.gABC(n, opcNarrowU, dest, TRegister(dstSize*8))
c.freeTemp(tmp)
elif srcSize == dstSize and src.kind in allowedIntegers and
dst.kind in {tyFloat, tyFloat32, tyFloat64}:
elif src.kind in allowedIntegers and
dst.kind in {tyFloat, tyFloat32, tyFloat64}:
if srcSize != dstSize:
globalError(c.config, n.info, unsupportedCastDifferentSize %
[$src.kind, $srcSize, $dst.kind, $dstSize])
let tmp = c.genx(n[1])
if dest < 0: dest = c.getTemp(n[0].typ)
if dst.kind == tyFloat32:
@@ -910,8 +936,11 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
c.gABC(n, opcCastIntToFloat64, dest, tmp)
c.freeTemp(tmp)
elif srcSize == dstSize and src.kind in {tyFloat, tyFloat32, tyFloat64} and
elif src.kind in {tyFloat, tyFloat32, tyFloat64} and
dst.kind in allowedIntegers:
if srcSize != dstSize:
globalError(c.config, n.info, unsupportedCastDifferentSize %
[$src.kind, $srcSize, $dst.kind, $dstSize])
let tmp = c.genx(n[1])
if dest < 0: dest = c.getTemp(n[0].typ)
if src.kind == tyFloat32:
@@ -1153,7 +1182,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
c.gABC(n, opcNarrowU, dest, TRegister(size*8))
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
genConv(c, n, n[1], dest)
of mEqStr, mEqCString: genBinaryABC(c, n, dest, opcEqStr)
of mEqStr: genBinaryABC(c, n, dest, opcEqStr)
of mEqCString: genBinaryABC(c, n, dest, opcEqCString)
of mLeStr: genBinaryABC(c, n, dest, opcLeStr)
of mLtStr: genBinaryABC(c, n, dest, opcLtStr)
of mEqSet: genBinarySet(c, n, dest, opcEqSet)
@@ -1541,6 +1571,7 @@ proc checkCanEval(c: PCtx; n: PNode) =
# little hack ahead for bug #12612: assume gensym'ed variables
# are in the right scope:
if sfGenSym in s.flags and c.prc.sym == nil: discard
elif s.kind == skParam and s.typ.kind == tyTypeDesc: discard
else: cannotEval(c, n)
elif s.kind in {skProc, skFunc, skConverter, skMethod,
skIterator} and sfForward in s.flags:
@@ -1794,7 +1825,6 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags
let setLit = c.genx(checkExpr[1])
var rs = c.getTemp(getSysType(c.graph, n.info, tyBool))
c.gABC(n, opcContainsSet, rs, setLit, discVal)
c.freeTemp(discVal)
c.freeTemp(setLit)
# If the check fails let the user know
let lab1 = c.xjmp(n, if negCheck: opcFJmp else: opcTJmp, rs)
@@ -1807,6 +1837,7 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags
strLit.typ = strType
c.genLit(strLit, msgReg)
c.gABC(n, opcInvalidField, msgReg, discVal)
c.freeTemp(discVal)
c.freeTemp(msgReg)
c.patch(lab1)
@@ -1878,10 +1909,10 @@ proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode =
result = newNodeIT(nkUIntLit, info, t)
of tyFloat..tyFloat128:
result = newNodeIT(nkFloatLit, info, t)
of tyCstring, tyString:
of tyString:
result = newNodeIT(nkStrLit, info, t)
result.strVal = ""
of tyVar, tyLent, tyPointer, tyPtr, tyUntyped,
of tyCstring, tyVar, tyLent, tyPointer, tyPtr, tyUntyped,
tyTyped, tyTypeDesc, tyRef, tyNil:
result = newNodeIT(nkNilLit, info, t)
of tyProc:
@@ -2085,8 +2116,13 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
let s = n.sym
checkCanEval(c, n)
case s.kind
of skVar, skForVar, skTemp, skLet, skParam, skResult:
of skVar, skForVar, skTemp, skLet, skResult:
genRdVar(c, n, dest, flags)
of skParam:
if s.typ.kind == tyTypeDesc:
genTypeLit(c, s.typ, dest)
else:
genRdVar(c, n, dest, flags)
of skProc, skFunc, skConverter, skMacro, skTemplate, skMethod, skIterator:
# 'skTemplate' is only allowed for 'getAst' support:
if s.kind == skIterator and s.typ.callConv == TCallingConvention.ccClosure:
@@ -2096,10 +2132,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
genLit(c, n, dest)
of skConst:
let constVal = if s.ast != nil: s.ast else: s.typ.n
if dontInlineConstant(n, constVal):
genLit(c, constVal, dest)
else:
gen(c, constVal, dest)
gen(c, constVal, dest)
of skEnumField:
# we never reach this case - as of the time of this comment,
# skEnumField is folded to an int in semfold.nim, but this code

View File

@@ -32,6 +32,7 @@ type
wColon = ":", wColonColon = "::", wEquals = "=", wDot = ".", wDotDot = "..",
wStar = "*", wMinus = "-",
wUnderscore = "_",
wMagic = "magic", wThread = "thread", wFinal = "final", wProfiler = "profiler",
wMemTracker = "memtracker", wObjChecks = "objchecks",
wIntDefine = "intdefine", wStrDefine = "strdefine", wBoolDefine = "booldefine",

View File

@@ -156,7 +156,10 @@ nimblepath="$home/.nimble/pkgs/"
# Configuration for the GNU C/C++ compiler:
@if windows:
#gcc.path = r"$nim\dist\mingw\bin"
@if gcc or tcc:
@if gcc:
gcc.options.linker %= "-Wl,-Bstatic -lpthread"
@end
@if tcc:
tlsEmulation:on
@end
@end

View File

@@ -10,6 +10,6 @@ const
## is the minor number of Nim's version.
## Odd for devel, even for releases.
NimPatch* {.intdefine.}: int = 14
NimPatch* {.intdefine.}: int = 21
## is the patch number of Nim's version.
## Odd for devel, even for releases.

View File

@@ -135,8 +135,9 @@ type
const
nnkLiterals* = {nnkCharLit..nnkNilLit}
# see matching set CallNodes below
nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
nnkCallStrLit}
nnkCallStrLit, nnkHiddenCallConv}
nnkPragmaCallKinds = {nnkExprColonExpr, nnkCall, nnkCallStrLit}
{.push warnings: off.}
@@ -1174,8 +1175,8 @@ const
RoutineNodes* = {nnkProcDef, nnkFuncDef, nnkMethodDef, nnkDo, nnkLambda,
nnkIteratorDef, nnkTemplateDef, nnkConverterDef, nnkMacroDef}
AtomicNodes* = {nnkNone..nnkNilLit}
CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
nnkCallStrLit, nnkHiddenCallConv}
# see matching set nnkCallKinds above
CallNodes* = nnkCallKinds
proc expectKind*(n: NimNode; k: set[NimNodeKind]) =
## Checks that `n` is of kind `k`. If this is not the case,

View File

@@ -309,7 +309,7 @@ type
sa_mask*: Sigset ## Set of signals to be blocked during execution of
## the signal handling function.
sa_flags*: cint ## Special flags.
sa_sigaction*: proc (x: cint, y: ptr SigInfo, z: pointer) {.noconv.}
sa_restorer: proc() {.noconv.} ## not intended for application use.
Stack* {.importc: "stack_t",
header: "<signal.h>", final, pure.} = object ## stack_t
@@ -325,9 +325,9 @@ type
SigInfo* {.importc: "siginfo_t",
header: "<signal.h>", final, pure.} = object ## siginfo_t
si_signo*: cint ## Signal number.
si_code*: cint ## Signal code.
si_errno*: cint ## If non-zero, an errno value associated with
## this signal, as defined in <errno.h>.
si_code*: cint ## Signal code.
si_pid*: Pid ## Sending process ID.
si_uid*: Uid ## Real user ID of sending process.
si_addr*: pointer ## Address of faulting instruction.
@@ -336,6 +336,12 @@ type
si_value*: SigVal ## Signal value.
pad {.importc: "_pad".}: array[128 - 56, uint8]
template sa_sigaction*(v: Sigaction): proc (x: cint, y: ptr SigInfo, z: pointer) {.noconv.} =
cast[proc (x: cint, y: ptr SigInfo, z: pointer) {.noconv.}](v.sa_handler)
proc `sa_sigaction=`*(v: var Sigaction, x: proc (x: cint, y: ptr SigInfo, z: pointer) {.noconv.}) =
v.sa_handler = cast[proc (x: cint) {.noconv.}](x)
type
Nl_item* {.importc: "nl_item", header: "<nl_types.h>".} = cint
Nl_catd* {.importc: "nl_catd", header: "<nl_types.h>".} = pointer

View File

@@ -464,6 +464,7 @@ const MSG_EOR* = cint(128)
const MSG_OOB* = cint(1)
const SCM_RIGHTS* = cint(1)
const SO_ACCEPTCONN* = cint(30)
const SO_BINDTODEVICE* = cint(25)
const SO_BROADCAST* = cint(6)
const SO_DEBUG* = cint(1)
const SO_DONTROUTE* = cint(5)

View File

@@ -473,6 +473,7 @@ var MSG_EOR* {.importc: "MSG_EOR", header: "<sys/socket.h>".}: cint
var MSG_OOB* {.importc: "MSG_OOB", header: "<sys/socket.h>".}: cint
var SCM_RIGHTS* {.importc: "SCM_RIGHTS", header: "<sys/socket.h>".}: cint
var SO_ACCEPTCONN* {.importc: "SO_ACCEPTCONN", header: "<sys/socket.h>".}: cint
var SO_BINDTODEVICE* {.importc: "SO_BINDTODEVICE", header: "<sys/socket.h>".}: cint
var SO_BROADCAST* {.importc: "SO_BROADCAST", header: "<sys/socket.h>".}: cint
var SO_DEBUG* {.importc: "SO_DEBUG", header: "<sys/socket.h>".}: cint
var SO_DONTROUTE* {.importc: "SO_DONTROUTE", header: "<sys/socket.h>".}: cint

View File

@@ -149,7 +149,7 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] =
protocol)
result.orig = protocol
i.inc protocol.parseSaturatedNatural(result.major, i)
i.inc # Skip .
if i < protocol.len: inc i # Skip .
i.inc protocol.parseSaturatedNatural(result.minor, i)
proc sendStatus(client: AsyncSocket, status: string): Future[void] =
@@ -375,7 +375,7 @@ const
proc listen*(server: AsyncHttpServer; port: Port; address = ""; domain = AF_INET) =
## Listen to the given port and address.
when declared(maxDescriptors):
server.maxFDs = try: maxDescriptors() except: nimMaxDescriptorsFallback
server.maxFDs = try: maxDescriptors() except OSError: nimMaxDescriptorsFallback
else:
server.maxFDs = nimMaxDescriptorsFallback
server.socket = newAsyncSocket(domain)

View File

@@ -66,14 +66,10 @@ template cbBase(a, b): untyped = [
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', a, b]
let
const
cb64 = cbBase('+', '/')
cb64safe = cbBase('-', '_')
const
cb64VM = cbBase('+', '/')
cb64safeVM = cbBase('-', '_')
const
invalidChar = 255
@@ -132,14 +128,10 @@ template encodeInternal(s, alphabet: typed): untyped =
result.setLen(outputIndex)
template encodeImpl() {.dirty.} =
when nimvm:
block:
let lookupTableVM = if safe: cb64safeVM else: cb64VM
encodeInternal(s, lookupTableVM)
if safe:
encodeInternal(s, cb64safe)
else:
block:
let lookupTable = if safe: unsafeAddr(cb64safe) else: unsafeAddr(cb64)
encodeInternal(s, lookupTable)
encodeInternal(s, cb64)
proc encode*[T: SomeInteger|char](s: openArray[T], safe = false): string =
## Encodes `s` into base64 representation.
@@ -247,7 +239,7 @@ proc decode*(s: string): string =
inputLen = s.len
inputEnds = 0
# strip trailing characters
while s[inputLen - 1] in {'\n', '\r', ' ', '='}:
while inputLen > 0 and s[inputLen - 1] in {'\n', '\r', ' ', '='}:
dec inputLen
# hot loop: read 4 characters at at time
inputEnds = inputLen - 4

View File

@@ -71,9 +71,8 @@ template initImpl(result: typed, initialSize: int) =
newSeq(result.data, correctSize)
template checkIfInitialized(deq: typed) =
when compiles(defaultInitialSize):
if deq.mask == 0:
initImpl(deq, defaultInitialSize)
if deq.mask == 0:
initImpl(deq, defaultInitialSize)
proc initDeque*[T](initialSize: int = defaultInitialSize): Deque[T] =
## Creates a new empty deque.

View File

@@ -166,28 +166,6 @@ proc newSinglyLinkedNode*[T](value: T): SinglyLinkedNode[T] =
new(result)
result.value = value
func toSinglyLinkedList*[T](elems: openArray[T]): SinglyLinkedList[T] {.since: (1, 5, 1).} =
## Creates a new `SinglyLinkedList` from the members of `elems`.
runnableExamples:
from std/sequtils import toSeq
let a = [1, 2, 3, 4, 5].toSinglyLinkedList
assert a.toSeq == [1, 2, 3, 4, 5]
result = initSinglyLinkedList[T]()
for elem in elems.items:
result.add(elem)
func toDoublyLinkedList*[T](elems: openArray[T]): DoublyLinkedList[T] {.since: (1, 5, 1).} =
## Creates a new `DoublyLinkedList` from the members of `elems`.
runnableExamples:
from std/sequtils import toSeq
let a = [1, 2, 3, 4, 5].toDoublyLinkedList
assert a.toSeq == [1, 2, 3, 4, 5]
result = initDoublyLinkedList[T]()
for elem in elems.items:
result.add(elem)
template itemsListImpl() {.dirty.} =
var it = L.head
while it != nil:
@@ -994,3 +972,25 @@ proc appendMoved*[T: SomeLinkedList](a, b: var T) {.since: (1, 5, 1).} =
## * `addMoved proc <#addMoved,SinglyLinkedList[T],SinglyLinkedList[T]>`_
## * `addMoved proc <#addMoved,DoublyLinkedList[T],DoublyLinkedList[T]>`_
a.addMoved(b)
func toSinglyLinkedList*[T](elems: openArray[T]): SinglyLinkedList[T] {.since: (1, 5, 1).} =
## Creates a new `SinglyLinkedList` from the members of `elems`.
runnableExamples:
from std/sequtils import toSeq
let a = [1, 2, 3, 4, 5].toSinglyLinkedList
assert a.toSeq == [1, 2, 3, 4, 5]
result = initSinglyLinkedList[T]()
for elem in elems.items:
result.add(elem)
func toDoublyLinkedList*[T](elems: openArray[T]): DoublyLinkedList[T] {.since: (1, 5, 1).} =
## Creates a new `DoublyLinkedList` from the members of `elems`.
runnableExamples:
from std/sequtils import toSeq
let a = [1, 2, 3, 4, 5].toDoublyLinkedList
assert a.toSeq == [1, 2, 3, 4, 5]
result = initDoublyLinkedList[T]()
for elem in elems.items:
result.add(elem)

View File

@@ -11,6 +11,9 @@
include hashcommon
const
defaultInitialSize* = 32
template rawGetDeepImpl() {.dirty.} = # Search algo for unconditional add
genHashImpl(key, hc)
var h: Hash = hc and maxHash(t)
@@ -31,9 +34,8 @@ proc rawInsert[X, A, B](t: var X, data: var KeyValuePairSeq[A, B],
rawInsertImpl()
template checkIfInitialized() =
when compiles(defaultInitialSize):
if t.dataLen == 0:
initImpl(t, defaultInitialSize)
if t.dataLen == 0:
initImpl(t, defaultInitialSize)
template addImpl(enlarge) {.dirty.} =
checkIfInitialized()

View File

@@ -217,8 +217,6 @@ type
## For creating a new empty TableRef, use `newTable proc
## <#newTable>`_.
const
defaultInitialSize* = 32
# ------------------------------ helpers ---------------------------------
@@ -2891,3 +2889,18 @@ iterator mvalues*[A](t: CountTableRef[A]): var int =
if t.data[h].val != 0:
yield t.data[h].val
assert(len(t) == L, "the length of the table changed while iterating over it")
proc hash*[K,V](s: Table[K,V]): Hash =
for p in pairs(s):
result = result xor hash(p)
result = !$result
proc hash*[K,V](s: OrderedTable[K,V]): Hash =
for p in pairs(s):
result = result !& hash(p)
result = !$result
proc hash*[V](s: CountTable[V]): Hash =
for p in pairs(s):
result = result xor hash(p)
result = !$result

View File

@@ -315,16 +315,24 @@ proc murmurHash(x: openArray[byte]): Hash =
h1: uint32
i = 0
template impl =
var j = stepSize
while j > 0:
dec j
k1 = (k1 shl 8) or (ord(x[i+j])).uint32
# body
while i < n * stepSize:
var k1: uint32
when defined(js) or defined(sparc) or defined(sparc64):
var j = stepSize
while j > 0:
dec j
k1 = (k1 shl 8) or (ord(x[i+j])).uint32
when nimvm:
impl()
else:
k1 = cast[ptr uint32](unsafeAddr x[i])[]
when declared(copyMem):
copyMem(unsafeAddr k1, unsafeAddr x[i], 4)
else:
impl()
inc i, stepSize
k1 = imul(k1, c1)

View File

@@ -328,68 +328,8 @@ func nextPowerOfTwo*(x: int): int =
result = result or (result shr 1)
result += 1 + ord(x <= 0)
func sum*[T](x: openArray[T]): T =
## Computes the sum of the elements in `x`.
##
## If `x` is empty, 0 is returned.
##
## **See also:**
## * `prod func <#prod,openArray[T]>`_
## * `cumsum func <#cumsum,openArray[T]>`_
## * `cumsummed func <#cumsummed,openArray[T]>`_
runnableExamples:
doAssert sum([1, 2, 3, 4]) == 10
doAssert sum([-4, 3, 5]) == 4
for i in items(x): result = result + i
func prod*[T](x: openArray[T]): T =
## Computes the product of the elements in `x`.
##
## If `x` is empty, 1 is returned.
##
## **See also:**
## * `sum func <#sum,openArray[T]>`_
## * `fac func <#fac,int>`_
runnableExamples:
doAssert prod([1, 2, 3, 4]) == 24
doAssert prod([-4, 3, 5]) == -60
result = T(1)
for i in items(x): result = result * i
func cumsummed*[T](x: openArray[T]): seq[T] =
## Returns the cumulative (aka prefix) summation of `x`.
##
## If `x` is empty, `@[]` is returned.
##
## **See also:**
## * `sum func <#sum,openArray[T]>`_
## * `cumsum func <#cumsum,openArray[T]>`_ for the in-place version
runnableExamples:
doAssert cumsummed([1, 2, 3, 4]) == @[1, 3, 6, 10]
let xLen = x.len
if xLen == 0:
return @[]
result.setLen(xLen)
result[0] = x[0]
for i in 1 ..< xLen: result[i] = result[i - 1] + x[i]
func cumsum*[T](x: var openArray[T]) =
## Transforms `x` in-place (must be declared as `var`) into its
## cumulative (aka prefix) summation.
##
## **See also:**
## * `sum func <#sum,openArray[T]>`_
## * `cumsummed func <#cumsummed,openArray[T]>`_ for a version which
## returns a cumsummed sequence
runnableExamples:
var a = [1, 2, 3, 4]
cumsum(a)
doAssert a == @[1, 3, 6, 10]
for i in 1 ..< x.len: x[i] = x[i - 1] + x[i]
when not defined(js): # C
func sqrt*(x: float32): float32 {.importc: "sqrtf", header: "<math.h>".}
@@ -1135,6 +1075,69 @@ func sgn*[T: SomeNumber](x: T): int {.inline.} =
{.pop.}
{.pop.}
func sum*[T](x: openArray[T]): T =
## Computes the sum of the elements in `x`.
##
## If `x` is empty, 0 is returned.
##
## **See also:**
## * `prod func <#prod,openArray[T]>`_
## * `cumsum func <#cumsum,openArray[T]>`_
## * `cumsummed func <#cumsummed,openArray[T]>`_
runnableExamples:
doAssert sum([1, 2, 3, 4]) == 10
doAssert sum([-4, 3, 5]) == 4
for i in items(x): result = result + i
func prod*[T](x: openArray[T]): T =
## Computes the product of the elements in `x`.
##
## If `x` is empty, 1 is returned.
##
## **See also:**
## * `sum func <#sum,openArray[T]>`_
## * `fac func <#fac,int>`_
runnableExamples:
doAssert prod([1, 2, 3, 4]) == 24
doAssert prod([-4, 3, 5]) == -60
result = T(1)
for i in items(x): result = result * i
func cumsummed*[T](x: openArray[T]): seq[T] =
## Returns the cumulative (aka prefix) summation of `x`.
##
## If `x` is empty, `@[]` is returned.
##
## **See also:**
## * `sum func <#sum,openArray[T]>`_
## * `cumsum func <#cumsum,openArray[T]>`_ for the in-place version
runnableExamples:
doAssert cumsummed([1, 2, 3, 4]) == @[1, 3, 6, 10]
let xLen = x.len
if xLen == 0:
return @[]
result.setLen(xLen)
result[0] = x[0]
for i in 1 ..< xLen: result[i] = result[i - 1] + x[i]
func cumsum*[T](x: var openArray[T]) =
## Transforms `x` in-place (must be declared as `var`) into its
## cumulative (aka prefix) summation.
##
## **See also:**
## * `sum func <#sum,openArray[T]>`_
## * `cumsummed func <#cumsummed,openArray[T]>`_ for a version which
## returns a cumsummed sequence
runnableExamples:
var a = [1, 2, 3, 4]
cumsum(a)
doAssert a == @[1, 3, 6, 10]
for i in 1 ..< x.len: x[i] = x[i - 1] + x[i]
func `^`*[T: SomeNumber](x: T, y: Natural): T =
## Computes `x` to the power of `y`.
##

View File

@@ -3145,14 +3145,14 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noW
when defined(windows):
var bufsize = int32(MAX_PATH)
when useWinUnicode:
var buf = newWideCString("", bufsize)
var buf = newWideCString(bufsize)
while true:
var L = getModuleFileNameW(0, buf, bufsize)
if L == 0'i32:
result = "" # error!
break
elif L > bufsize:
buf = newWideCString("", L)
buf = newWideCString(L)
bufsize = L
else:
result = buf$L

View File

@@ -559,7 +559,7 @@ template matchOrParse(mopProc: untyped) =
# procs. For the former, *enter* and *leave* event handler code generators
# are provided which just return *discard*.
proc mopProc(s: string, p: Peg, start: int, c: var Captures): int =
proc mopProc(s: string, p: Peg, start: int, c: var Captures): int {.gcsafe, raises: [].} =
proc matchBackRef(s: string, p: Peg, start: int, c: var Captures): int =
# Parse handler code must run in an *of* clause of its own for each
# *PegKind*, so we encapsulate the identical clause body for

View File

@@ -573,7 +573,8 @@ template formatValue(result: var string; value: char; specifier: string) =
template formatValue(result: var string; value: cstring; specifier: string) =
result.add value
proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
proc strformatImpl(f: string; openChar, closeChar: char,
lineInfoNode: NimNode = nil): NimNode =
template missingCloseChar =
error("invalid format string: missing closing character '" & closeChar & "'")
@@ -581,7 +582,7 @@ proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
error "openChar and closeChar must not be ':'"
var i = 0
let res = genSym(nskVar, "fmtRes")
result = newNimNode(nnkStmtListExpr)
result = newNimNode(nnkStmtListExpr, lineInfoNode)
# XXX: https://github.com/nim-lang/Nim/issues/8405
# When compiling with -d:useNimRtl, certain procs such as `count` from the strutils
# module are not accessible at compile-time:
@@ -640,6 +641,7 @@ proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
x = parseExpr(subexpr)
except ValueError as e:
error("could not parse `$#` in `$#`.\n$#" % [subexpr, f, e.msg])
x.copyLineInfo(lineInfoNode)
let formatSym = bindSym("formatValue", brOpen)
var options = ""
if f[i] == ':':
@@ -665,10 +667,22 @@ proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
if strlit.len > 0:
result.add newCall(bindSym"add", res, newLit(strlit))
result.add res
# workaround for #20381
var blockExpr = newNimNode(nnkBlockExpr, lineInfoNode)
blockExpr.add(newEmptyNode())
blockExpr.add(result)
result = blockExpr
when defined(debugFmtDsl):
echo repr result
macro fmt*(pattern: static string; openChar: static char, closeChar: static char): string =
macro fmt(pattern: static string; openChar: static char, closeChar: static char, lineInfoNode: untyped): string =
## version of `fmt` with dummy untyped param for line info
strformatImpl(pattern, openChar, closeChar, lineInfoNode)
when not defined(nimHasCallsitePragma):
{.pragma: callsite.}
template fmt*(pattern: static string; openChar: static char, closeChar: static char): string {.callsite.} =
## Interpolates `pattern` using symbols in scope.
runnableExamples:
let x = 7
@@ -685,13 +699,13 @@ macro fmt*(pattern: static string; openChar: static char, closeChar: static char
assert "<x>".fmt('<', '>') == "7"
assert "<<<x>>>".fmt('<', '>') == "<7>"
assert "`x`".fmt('`', '`') == "7"
strformatImpl(pattern, openChar, closeChar)
fmt(pattern, openChar, closeChar, dummyForLineInfo)
template fmt*(pattern: static string): untyped =
template fmt*(pattern: static string): untyped {.callsite.} =
## Alias for `fmt(pattern, '{', '}')`.
fmt(pattern, '{', '}')
fmt(pattern, '{', '}', dummyForLineInfo)
macro `&`*(pattern: string{lit}): string =
template `&`*(pattern: string{lit}): string {.callsite.} =
## `&pattern` is the same as `pattern.fmt`.
## For a specification of the `&` macro, see the module level documentation.
# pending bug #18275, bug #18278, use `pattern: static string`
@@ -701,6 +715,6 @@ macro `&`*(pattern: string{lit}): string =
runnableExamples:
let x = 7
assert &"{x}\n" == "7\n" # regular string literal
assert &"{x}\n" == "7\n".fmt # `fmt` can be used instead
assert &"{x}\n" != fmt"7\n" # see `fmt` docs, this would use a raw string literal
strformatImpl(pattern.strVal, '{', '}')
assert &"{x}\n" == "{x}\n".fmt # `fmt` can be used instead
assert &"{x}\n" != fmt"{x}\n" # see `fmt` docs, this would use a raw string literal
fmt(pattern, '{', '}', dummyForLineInfo)

View File

@@ -346,11 +346,14 @@ func cmpIgnoreStyle*(a, b: string): int {.rtl, extern: "nsuCmpIgnoreStyle".} =
# --------- Private templates for different split separators -----------
func substrEq(s: string, pos: int, substr: string): bool =
var i = 0
# Always returns false for empty `substr`
var length = substr.len
while i < length and pos+i < s.len and s[pos+i] == substr[i]:
inc i
return i == length
if length > 0:
var i = 0
while i < length and pos+i < s.len and s[pos+i] == substr[i]:
inc i
i == length
else: false
template stringHasSep(s: string, index: int, seps: set[char]): bool =
s[index] in seps
@@ -492,12 +495,17 @@ iterator split*(s: string, sep: string, maxsplit: int = -1): string =
## "is"
## "corrupted"
##
## .. note:: Empty separator string results in returning an original string,
## following the interpretation "split by no element".
##
## See also:
## * `rsplit iterator<#rsplit.i,string,string,int,bool>`_
## * `splitLines iterator<#splitLines.i,string>`_
## * `splitWhitespace iterator<#splitWhitespace.i,string,int>`_
## * `split func<#split,string,string,int>`_
splitCommon(s, sep, maxsplit, sep.len)
let sepLen = if sep.len == 0: 1 # prevents infinite loop
else: sep.len
splitCommon(s, sep, maxsplit, sepLen)
template rsplitCommon(s, sep, maxsplit, sepLen) =
@@ -567,6 +575,9 @@ iterator rsplit*(s: string, seps: set[char] = Whitespace,
##
## Substrings are separated from the right by the set of chars `seps`
##
## .. note:: Empty separator set results in returning an original string,
## following the interpretation "split by no element".
##
## See also:
## * `split iterator<#split.i,string,set[char],int>`_
## * `splitLines iterator<#splitLines.i,string>`_
@@ -592,12 +603,17 @@ iterator rsplit*(s: string, sep: string, maxsplit: int = -1,
##
## Substrings are separated from the right by the string `sep`
##
## .. note:: Empty separator string results in returning an original string,
## following the interpretation "split by no element".
##
## See also:
## * `split iterator<#split.i,string,string,int>`_
## * `splitLines iterator<#splitLines.i,string>`_
## * `splitWhitespace iterator<#splitWhitespace.i,string,int>`_
## * `rsplit func<#rsplit,string,string,int>`_
rsplitCommon(s, sep, maxsplit, sep.len)
let sepLen = if sep.len == 0: 1 # prevents infinite loop
else: sep.len
rsplitCommon(s, sep, maxsplit, sepLen)
iterator splitLines*(s: string, keepEol = false): string =
## Splits the string `s` into its containing lines.
@@ -708,6 +724,9 @@ func split*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): seq[
## The same as the `split iterator <#split.i,string,set[char],int>`_ (see its
## documentation), but is a func that returns a sequence of substrings.
##
## .. note:: Empty separator set results in returning an original string,
## following the interpretation "split by no element".
##
## See also:
## * `split iterator <#split.i,string,set[char],int>`_
## * `rsplit func<#rsplit,string,set[char],int>`_
@@ -716,6 +735,7 @@ func split*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): seq[
runnableExamples:
doAssert "a,b;c".split({',', ';'}) == @["a", "b", "c"]
doAssert "".split({' '}) == @[""]
doAssert "empty seps return unsplit s".split({}) == @["empty seps return unsplit s"]
accResult(split(s, seps, maxsplit))
func split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
@@ -725,6 +745,9 @@ func split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
## Substrings are separated by the string `sep`. This is a wrapper around the
## `split iterator <#split.i,string,string,int>`_.
##
## .. note:: Empty separator string results in returning an original string,
## following the interpretation "split by no element".
##
## See also:
## * `split iterator <#split.i,string,string,int>`_
## * `rsplit func<#rsplit,string,string,int>`_
@@ -737,8 +760,7 @@ func split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
doAssert "a largely spaced sentence".split(" ") == @["a", "", "largely",
"", "", "", "spaced", "sentence"]
doAssert "a largely spaced sentence".split(" ", maxsplit = 1) == @["a", " largely spaced sentence"]
doAssert(sep.len > 0)
doAssert "empty sep returns unsplit s".split("") == @["empty sep returns unsplit s"]
accResult(split(s, sep, maxsplit))
func rsplit*(s: string, sep: char, maxsplit: int = -1): seq[string] {.rtl,
@@ -788,6 +810,9 @@ func rsplit*(s: string, seps: set[char] = Whitespace,
## .. code-block:: nim
## @["Root#Object#Method", "Index"]
##
## .. note:: Empty separator set results in returning an original string,
## following the interpretation "split by no element".
##
## See also:
## * `rsplit iterator <#rsplit.i,string,set[char],int>`_
## * `split func<#split,string,set[char],int>`_
@@ -815,6 +840,9 @@ func rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
## .. code-block:: nim
## @["Root#Object#Method", "Index"]
##
## .. note:: Empty separator string results in returning an original string,
## following the interpretation "split by no element".
##
## See also:
## * `rsplit iterator <#rsplit.i,string,string,int,bool>`_
## * `split func<#split,string,string,int>`_
@@ -829,6 +857,7 @@ func rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
doAssert "".rsplit("Elon Musk") == @[""]
doAssert "a largely spaced sentence".rsplit(" ") == @["a", "",
"largely", "", "", "", "spaced", "sentence"]
doAssert "empty sep returns unsplit s".rsplit("") == @["empty sep returns unsplit s"]
accResult(rsplit(s, sep, maxsplit))
result.reverse()

View File

@@ -111,7 +111,6 @@ proc intSetPut[A](t: var PackedSet[A], key: int): Trunk =
t.data[h] = result
proc bitincl[A](s: var PackedSet[A], key: int) {.inline.} =
var ret: Trunk
var t = intSetPut(s, key shr TrunkShift)
var u = key and TrunkMask
t.bits[u shr IntShift] = t.bits[u shr IntShift] or

View File

@@ -1619,7 +1619,7 @@ proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}
proc isNil*[T: proc](x: T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*[T: proc | iterator {.closure.}](x: T): bool {.noSideEffect, magic: "IsNil".}
## Fast check whether `x` is nil. This is sometimes more efficient than
## `== nil`.

View File

@@ -992,7 +992,7 @@ template instantiateForRegion(allocator: untyped) {.dirty.} =
proc realloc0Impl(p: pointer, oldSize, newSize: Natural): pointer =
result = realloc(allocator, p, newSize)
if newSize > oldSize:
zeroMem(cast[pointer](cast[int](result) + oldSize), newSize - oldSize)
zeroMem(cast[pointer](cast[uint](result) + uint(oldSize)), newSize - oldSize)
when false:
proc countFreeMem(): int =

View File

@@ -16,18 +16,21 @@ type
d: PCellArray
proc contains(s: CellSeq, c: PCell): bool {.inline.} =
for i in 0 .. s.len-1:
if s.d[i] == c: return true
for i in 0 ..< s.len:
if s.d[i] == c:
return true
return false
proc resize(s: var CellSeq) =
s.cap = s.cap * 3 div 2
let d = cast[PCellArray](alloc(s.cap * sizeof(PCell)))
copyMem(d, s.d, s.len * sizeof(PCell))
dealloc(s.d)
s.d = d
proc add(s: var CellSeq, c: PCell) {.inline.} =
if s.len >= s.cap:
s.cap = s.cap * 3 div 2
var d = cast[PCellArray](alloc(s.cap * sizeof(PCell)))
copyMem(d, s.d, s.len * sizeof(PCell))
dealloc(s.d)
s.d = d
# XXX: realloc?
resize(s)
s.d[s.len] = c
inc(s.len)

View File

@@ -16,20 +16,17 @@ type
len, cap: int
d: CellArray[T]
proc add[T](s: var CellSeq[T], c: T; t: PNimTypeV2) {.inline.} =
proc resize[T](s: var CellSeq[T]) =
s.cap = s.cap * 3 div 2
var newSize = s.cap * sizeof(CellTuple[T])
when compileOption("threads"):
s.d = cast[CellArray[T]](reallocShared(s.d, newSize))
else:
s.d = cast[CellArray[T]](realloc(s.d, newSize))
proc add[T](s: var CellSeq[T], c: T, t: PNimTypeV2) {.inline.} =
if s.len >= s.cap:
s.cap = s.cap * 3 div 2
when compileOption("threads"):
var d = cast[CellArray[T]](allocShared(uint(s.cap * sizeof(CellTuple[T]))))
else:
var d = cast[CellArray[T]](alloc(s.cap * sizeof(CellTuple[T])))
copyMem(d, s.d, s.len * sizeof(CellTuple[T]))
when compileOption("threads"):
deallocShared(s.d)
else:
dealloc(s.d)
s.d = d
# XXX: realloc?
s.resize()
s.d[s.len] = (c, t)
inc(s.len)

View File

@@ -35,7 +35,7 @@ proc `==`*[T](x, y: ref T): bool {.magic: "EqRef", noSideEffect.}
## Checks that two `ref` variables refer to the same item.
proc `==`*[T](x, y: ptr T): bool {.magic: "EqRef", noSideEffect.}
## Checks that two `ptr` variables refer to the same item.
proc `==`*[T: proc](x, y: T): bool {.magic: "EqProc", noSideEffect.}
proc `==`*[T: proc | iterator](x, y: T): bool {.magic: "EqProc", noSideEffect.}
## Checks that two `proc` variables refer to the same procedure.
proc `<=`*[Enum: enum](x, y: Enum): bool {.magic: "LeEnum", noSideEffect.}

View File

@@ -116,9 +116,6 @@ when hasAlloc and not defined(js):
##
## See also:
## * `create <#create,typedesc>`_
static:
when sizeof(T) <= 0:
{.fatal: "createU does not support types T where sizeof(T) == 0".}
cast[ptr T](alloc(T.sizeof * size))
template alloc0*(size: Natural): pointer =
@@ -144,9 +141,6 @@ when hasAlloc and not defined(js):
##
## The allocated memory belongs to its allocating thread!
## Use `createShared <#createShared,typedesc>`_ to allocate from a shared heap.
static:
when sizeof(T) <= 0:
{.fatal: "create does not support types T where sizeof(T) == 0".}
cast[ptr T](alloc0(sizeof(T) * size))
template realloc*(p: pointer, newSize: Natural): pointer =

View File

@@ -22,7 +22,7 @@ proc reallocImpl(p: pointer, newSize: Natural): pointer =
proc realloc0Impl(p: pointer, oldsize, newSize: Natural): pointer =
result = realloc(p, newSize.csize_t)
if newSize > oldSize:
zeroMem(cast[pointer](cast[int](result) + oldSize), newSize - oldSize)
zeroMem(cast[pointer](cast[uint](result) + uint(oldSize)), newSize - oldSize)
proc deallocImpl(p: pointer) =
c_free(p)
@@ -88,7 +88,7 @@ type
proc alloc(r: var MemRegion, size: int): pointer =
result = alloc(size)
proc alloc0Impl(r: var MemRegion, size: int): pointer =
proc alloc0(r: var MemRegion, size: int): pointer =
result = alloc0Impl(size)
proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
proc deallocOsPages(r: var MemRegion) = discard

View File

@@ -88,7 +88,7 @@ proc repr*(p: pointer): string =
result[j] = HexChars[n and 0xF]
n = n shr 4
proc repr*(p: proc): string =
proc repr*(p: proc | iterator {.closure.}): string =
## repr of a proc as its address
repr(cast[ptr pointer](unsafeAddr p)[])

View File

@@ -13,9 +13,11 @@
proc cardSetImpl(s: ptr UncheckedArray[uint8], len: int): int {.inline.} =
var i = 0
result = 0
var num = 0'u64
when defined(x86) or defined(amd64):
while i < len - 8:
inc(result, countBits64((cast[ptr uint64](s[i].unsafeAddr))[]))
copyMem(addr num, addr s[i], 8)
inc(result, countBits64(num))
inc(i, 8)
while i < len:

View File

@@ -34,53 +34,72 @@ template frees(s) =
else:
dealloc(s.p)
template allocPayload(newLen: int): ptr NimStrPayload =
when compileOption("threads"):
cast[ptr NimStrPayload](allocShared(contentSize(newLen)))
else:
cast[ptr NimStrPayload](alloc(contentSize(newLen)))
template allocPayload0(newLen: int): ptr NimStrPayload =
when compileOption("threads"):
cast[ptr NimStrPayload](allocShared0(contentSize(newLen)))
else:
cast[ptr NimStrPayload](alloc0(contentSize(newLen)))
template reallocPayload(p: pointer, newLen: int): ptr NimStrPayload =
when compileOption("threads"):
cast[ptr NimStrPayload](reallocShared(p, contentSize(newLen)))
else:
cast[ptr NimStrPayload](realloc(p, contentSize(newLen)))
template reallocPayload0(p: pointer; oldLen, newLen: int): ptr NimStrPayload =
when compileOption("threads"):
cast[ptr NimStrPayload](reallocShared0(p, contentSize(oldLen), contentSize(newLen)))
else:
cast[ptr NimStrPayload](realloc0(p, contentSize(oldLen), contentSize(newLen)))
proc resize(old: int): int {.inline.} =
if old <= 0: result = 4
elif old < 65536: result = old * 2
else: result = old * 3 div 2 # for large arrays * 3/2 is better
proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} =
let newLen = s.len + addlen
proc prepareAdd(s: var NimStringV2; addLen: int) {.compilerRtl.} =
let newLen = s.len + addLen
if isLiteral(s):
let oldP = s.p
# can't mutate a literal, so we need a fresh copy here:
when compileOption("threads"):
s.p = cast[ptr NimStrPayload](allocShared0(contentSize(newLen)))
else:
s.p = cast[ptr NimStrPayload](alloc0(contentSize(newLen)))
s.p = allocPayload(newLen)
s.p.cap = newLen
if s.len > 0:
# we are about to append, so there is no need to copy the \0 terminator:
copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], min(s.len, newLen))
elif oldP == nil:
# In the case of `newString(0) & ""`, since `src.len == 0`, `appendString`
# will not set the `\0` terminator, so we set it here.
s.p.data[0] = '\0'
else:
let oldCap = s.p.cap and not strlitFlag
if newLen > oldCap:
let newCap = max(newLen, resize(oldCap))
when compileOption("threads"):
s.p = cast[ptr NimStrPayload](reallocShared0(s.p, contentSize(oldCap), contentSize(newCap)))
else:
s.p = cast[ptr NimStrPayload](realloc0(s.p, contentSize(oldCap), contentSize(newCap)))
s.p = reallocPayload(s.p, newCap)
s.p.cap = newCap
if newLen < newCap:
zeroMem(cast[pointer](addr s.p.data[newLen+1]), newCap - newLen)
proc nimAddCharV1(s: var NimStringV2; c: char) {.compilerRtl, inline.} =
#if (s.p == nil) or (s.len+1 > s.p.cap and not strlitFlag):
prepareAdd(s, 1)
s.p.data[s.len] = c
s.p.data[s.len+1] = '\0'
inc s.len
s.p.data[s.len] = '\0'
proc toNimStr(str: cstring, len: int): NimStringV2 {.compilerproc.} =
if len <= 0:
result = NimStringV2(len: 0, p: nil)
else:
when compileOption("threads"):
var p = cast[ptr NimStrPayload](allocShared0(contentSize(len)))
else:
var p = cast[ptr NimStrPayload](alloc0(contentSize(len)))
var p = allocPayload(len)
p.cap = len
if len > 0:
# we are about to append, so there is no need to copy the \0 terminator:
copyMem(unsafeAddr p.data[0], str, len)
copyMem(unsafeAddr p.data[0], str, len+1)
result = NimStringV2(len: len, p: p)
proc cstrToNimstr(str: cstring): NimStringV2 {.compilerRtl.} =
@@ -99,29 +118,24 @@ proc appendString(dest: var NimStringV2; src: NimStringV2) {.compilerproc, inlin
proc appendChar(dest: var NimStringV2; c: char) {.compilerproc, inline.} =
dest.p.data[dest.len] = c
dest.p.data[dest.len+1] = '\0'
inc dest.len
dest.p.data[dest.len] = '\0'
proc rawNewString(space: int): NimStringV2 {.compilerproc.} =
# this is also 'system.newStringOfCap'.
if space <= 0:
result = NimStringV2(len: 0, p: nil)
else:
when compileOption("threads"):
var p = cast[ptr NimStrPayload](allocShared0(contentSize(space)))
else:
var p = cast[ptr NimStrPayload](alloc0(contentSize(space)))
var p = allocPayload(space)
p.cap = space
p.data[0] = '\0'
result = NimStringV2(len: 0, p: p)
proc mnewString(len: int): NimStringV2 {.compilerproc.} =
if len <= 0:
result = NimStringV2(len: 0, p: nil)
else:
when compileOption("threads"):
var p = cast[ptr NimStrPayload](allocShared0(contentSize(len)))
else:
var p = cast[ptr NimStrPayload](alloc0(contentSize(len)))
var p = allocPayload0(len)
p.cap = len
result = NimStringV2(len: len, p: p)
@@ -129,8 +143,25 @@ proc setLengthStrV2(s: var NimStringV2, newLen: int) {.compilerRtl.} =
if newLen == 0:
discard "do not free the buffer here, pattern 's.setLen 0' is common for avoiding allocations"
else:
if newLen > s.len or isLiteral(s):
prepareAdd(s, newLen - s.len)
if isLiteral(s):
let oldP = s.p
s.p = allocPayload(newLen)
s.p.cap = newLen
if s.len > 0:
copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], min(s.len, newLen))
if newLen > s.len:
zeroMem(cast[pointer](addr s.p.data[s.len]), newLen - s.len + 1)
else:
s.p.data[newLen] = '\0'
else:
zeroMem(cast[pointer](addr s.p.data[0]), newLen + 1)
elif newLen > s.len:
let oldCap = s.p.cap and not strlitFlag
if newLen > oldCap:
let newCap = max(newLen, resize(oldCap))
s.p = reallocPayload0(s.p, oldCap, newCap)
s.p.cap = newCap
s.p.data[newLen] = '\0'
s.len = newLen
@@ -147,10 +178,7 @@ proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
# 'let y = newStringOfCap(); var x = y'
# on the other hand... These get turned into moves now.
frees(a)
when compileOption("threads"):
a.p = cast[ptr NimStrPayload](allocShared0(contentSize(b.len)))
else:
a.p = cast[ptr NimStrPayload](alloc0(contentSize(b.len)))
a.p = allocPayload(b.len)
a.p.cap = b.len
a.len = b.len
copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
@@ -158,10 +186,7 @@ proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
proc nimPrepareStrMutationImpl(s: var NimStringV2) =
let oldP = s.p
# can't mutate a literal, so we need a fresh copy here:
when compileOption("threads"):
s.p = cast[ptr NimStrPayload](allocShared0(contentSize(s.len)))
else:
s.p = cast[ptr NimStrPayload](alloc0(contentSize(s.len)))
s.p = allocPayload(s.len)
s.p.cap = s.len
copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], s.len+1)

View File

@@ -13,6 +13,7 @@ import algorithm
import tables
import std/sha1
import times
import procmonitor
## Nimsuggest is a tool that helps to give editors IDE like capabilities.
@@ -35,6 +36,7 @@ when defined(windows):
else:
import posix
const HighestSuggestProtocolVersion = 4
const DummyEof = "!EOF!"
const Usage = """
Nimsuggest - Tool to give every editor IDE like capabilities for Nim
@@ -47,12 +49,18 @@ Options:
--address:HOST binds to that address, by default ""
--stdin read commands from stdin and write results to
stdout instead of using sockets
--clientProcessId:PID shutdown nimsuggest in case this process dies
--epc use emacs epc mode
--debug enable debug output
--log enable verbose logging to nimsuggest.log file
--v1 use version 1 of the protocol; for backwards compatibility
--v2 use version 2(default) of the protocol
--v3 use version 3 of the protocol
--v4 use version 4 of the protocol
--info:X information
--info:nimVer return the Nim compiler version that nimsuggest uses internally
--info:protocolVer return the newest protocol version that is supported
--info:capabilities return the capabilities supported by nimsuggest
--refresh perform automatic refreshes to keep the analysis precise
--maxresults:N limit the number of suggestions to N
--tester implies --stdin and outputs a line
@@ -109,6 +117,11 @@ const
"type 'quit' to quit\n" &
"type 'debug' to toggle debug mode on/off\n" &
"type 'terse' to toggle terse mode on/off"
#List of currently supported capabilities. So lang servers/ides can iterate over and check for what's enabled
Capabilities = [
"con", #current NimSuggest supports the `con` commmand
"unknownFile", #current NimSuggest can handle unknown files
]
proc parseQuoted(cmd: string; outp: var string; start: int): int =
var i = start
@@ -153,7 +166,7 @@ proc listEpc(): SexpNode =
argspecs = sexp("file line column dirtyfile".split(" ").map(newSSymbol))
docstring = sexp("line starts at 1, column at 0, dirtyfile is optional")
result = newSList()
for command in ["sug", "con", "def", "use", "dus", "chk", "mod", "globalSymbols", "recompile", "saved", "chkFile", "declaration"]:
for command in ["sug", "con", "def", "use", "dus", "chk", "mod", "globalSymbols", "recompile", "saved", "chkFile", "declaration", "inlayHints"]:
let
cmd = sexp(command)
methodDesc = newSList()
@@ -189,7 +202,7 @@ proc executeNoHooks(cmd: IdeCmd, file, dirtyfile: AbsoluteFile, line, col: int,
graph: ModuleGraph) =
let conf = graph.config
if conf.suggestVersion == 3:
if conf.suggestVersion >= 3:
let command = fmt "cmd = {cmd} {file}:{line}:{col}"
benchmark command:
executeNoHooksV3(cmd, file, dirtyfile, line, col, tag, graph)
@@ -478,6 +491,11 @@ proc execCmd(cmd: string; graph: ModuleGraph; cachedMsgs: CachedMsgs) =
of "chkfile": conf.ideCmd = ideChkFile
of "recompile": conf.ideCmd = ideRecompile
of "type": conf.ideCmd = ideType
of "inlayhints":
if conf.suggestVersion >= 4:
conf.ideCmd = ideInlayHints
else:
err()
else: err()
var dirtyfile = ""
var orig = ""
@@ -542,7 +560,7 @@ proc mainThread(graph: ModuleGraph) =
else:
os.sleep 250
idle += 1
if idle == 20 and gRefresh and conf.suggestVersion != 3:
if idle == 20 and gRefresh and conf.suggestVersion < 3:
# we use some nimsuggest activity to enable a lazy recompile:
conf.ideCmd = ideChk
conf.writelnHook = proc (s: string) = discard
@@ -572,7 +590,7 @@ proc mainCommand(graph: ModuleGraph) =
# do not print errors, but log them
conf.writelnHook = proc (msg: string) = discard
if graph.config.suggestVersion == 3:
if graph.config.suggestVersion >= 3:
graph.config.structuredErrorHook = proc (conf: ConfigRef; info: TLineInfo; msg: string; sev: Severity) =
let suggest = Suggest(section: ideChk, filePath: toFullPath(conf, info),
line: toLinenumber(info), column: toColumn(info), doc: msg, forth: $sev)
@@ -586,6 +604,9 @@ proc mainCommand(graph: ModuleGraph) =
open(requests)
open(results)
if graph.config.clientProcessId != 0:
hookProcMonitor(graph.config.clientProcessId)
case gMode
of mstdin: createThread(inputThread, replStdin, (gPort, gAddress))
of mtcp: createThread(inputThread, replTcp, (gPort, gAddress))
@@ -636,6 +657,20 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; conf: ConfigRef) =
of "v1": conf.suggestVersion = 1
of "v2": conf.suggestVersion = 0
of "v3": conf.suggestVersion = 3
of "v4": conf.suggestVersion = 4
of "info":
case p.val.normalize
of "protocolver":
stdout.writeLine(HighestSuggestProtocolVersion)
quit 0
of "nimver":
stdout.writeLine(system.NimVersion)
quit 0
of "capabilities":
stdout.writeLine(Capabilities.toSeq.mapIt($it).join(" "))
quit 0
else:
processSwitch(pass, p, conf)
of "tester":
gMode = mstdin
gEmitEof = true
@@ -650,6 +685,8 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; conf: ConfigRef) =
conf.suggestMaxResults = parseInt(p.val)
of "find":
findProject = true
of "clientprocessid":
conf.clientProcessId = parseInt(p.val)
else: processSwitch(pass, p, conf)
of cmdArgument:
let a = unixToNativePath(p.key)
@@ -747,6 +784,18 @@ proc findSymData(graph: ModuleGraph, trackPos: TLineInfo):
result[] = s
break
func isInRange*(current, startPos, endPos: TLineInfo, tokenLen: int): bool =
result = current.fileIndex == startPos.fileIndex and
(current.line > startPos.line or (current.line == startPos.line and current.col>=startPos.col)) and
(current.line < endPos.line or (current.line == endPos.line and current.col <= endPos.col))
proc findSymDataInRange(graph: ModuleGraph, startPos, endPos: TLineInfo):
seq[SymInfoPair] =
result = newSeq[SymInfoPair]()
for s in graph.fileSymbols(startPos.fileIndex).deduplicateSymInfoPair:
if isInRange(s.info, startPos, endPos, s.sym.name.s.len):
result.add(s)
proc findSymData(graph: ModuleGraph, file: AbsoluteFile; line, col: int):
ref SymInfoPair =
let
@@ -754,6 +803,14 @@ proc findSymData(graph: ModuleGraph, file: AbsoluteFile; line, col: int):
trackPos = newLineInfo(fileIdx, line, col)
result = findSymData(graph, trackPos)
proc findSymDataInRange(graph: ModuleGraph, file: AbsoluteFile; startLine, startCol, endLine, endCol: int):
seq[SymInfoPair] =
let
fileIdx = fileInfoIdx(graph.config, file)
startPos = newLineInfo(fileIdx, startLine, startCol)
endPos = newLineInfo(fileIdx, endLine, endCol)
result = findSymDataInRange(graph, startPos, endPos)
proc markDirtyIfNeeded(graph: ModuleGraph, file: string, originalFileIdx: FileIndex) =
let sha = $sha1.secureHashFile(file)
if graph.config.m.fileInfos[originalFileIdx.int32].hash != sha or graph.config.ideCmd == ideSug:
@@ -776,6 +833,23 @@ proc suggestResult(graph: ModuleGraph, sym: PSym, info: TLineInfo,
endLine = endLine, endCol = endCol)
suggestResult(graph.config, suggest)
proc suggestInlayHintResult(graph: ModuleGraph, sym: PSym, info: TLineInfo,
defaultSection = ideNone, endLine: uint16 = 0, endCol = 0) =
let section = if defaultSection != ideNone:
defaultSection
elif sym.info.exactEquals(info):
ideDef
else:
ideUse
var suggestDef = symToSuggest(graph, sym, isLocal=false, section,
info, 100, PrefixMatch.None, false, 0, true,
endLine = endLine, endCol = endCol)
suggestDef.inlayHintInfo = suggestToSuggestInlayHint(suggestDef)
suggestDef.section = ideInlayHints
if sym.kind == skForVar:
suggestDef.inlayHintInfo.allowInsert = false
suggestResult(graph.config, suggestDef)
const
# kinds for ideOutline and ideGlobalSymbols
searchableSymKinds = {skField, skEnumField, skIterator, skMethod, skFunc, skProc, skConverter, skTemplate}
@@ -869,10 +943,6 @@ proc executeNoHooksV3(cmd: IdeCmd, file: AbsoluteFile, dirtyfile: AbsoluteFile,
var fileIndex: FileIndex
if not (cmd in {ideRecompile, ideGlobalSymbols}):
if not fileInfoKnown(conf, file):
myLog fmt "{file} is unknown, returning no results"
return
fileIndex = fileInfoIdx(conf, file)
msgs.setDirtyFile(
conf,
@@ -883,7 +953,7 @@ proc executeNoHooksV3(cmd: IdeCmd, file: AbsoluteFile, dirtyfile: AbsoluteFile,
graph.markDirtyIfNeeded(dirtyFile.string, fileInfoIdx(conf, file))
# these commands require fully compiled project
if cmd in {ideUse, ideDus, ideGlobalSymbols, ideChk} and graph.needsCompilation():
if cmd in {ideUse, ideDus, ideGlobalSymbols, ideChk, ideInlayHints} and graph.needsCompilation():
graph.recompilePartially()
# when doing incremental build for the project root we should make sure that
# everything is unmarked as no longer beeing dirty in case there is no
@@ -892,10 +962,10 @@ proc executeNoHooksV3(cmd: IdeCmd, file: AbsoluteFile, dirtyfile: AbsoluteFile,
graph.unmarkAllDirty()
# these commands require partially compiled project
elif cmd in {ideSug, ideOutline, ideHighlight, ideDef, ideChkFile, ideType, ideDeclaration, ideExpand} and
(graph.needsCompilation(fileIndex) or cmd == ideSug):
elif cmd in {ideSug, ideCon, ideOutline, ideHighlight, ideDef, ideChkFile, ideType, ideDeclaration, ideExpand} and
(graph.needsCompilation(fileIndex) or cmd in {ideSug, ideCon}):
# for ideSug use v2 implementation
if cmd == ideSug:
if cmd in {ideSug, ideCon}:
conf.m.trackPos = newLineInfo(fileIndex, line, col)
conf.m.trackPosAttached = false
else:
@@ -941,6 +1011,9 @@ proc executeNoHooksV3(cmd: IdeCmd, file: AbsoluteFile, dirtyfile: AbsoluteFile,
# ideSug performs partial build of the file, thus mark it dirty for the
# future calls.
graph.markDirtyIfNeeded(file.string, fileIndex)
of ideCon:
graph.markDirty fileIndex
graph.markClientsDirty fileIndex
of ideOutline:
let n = parseFile(fileIndex, graph.cache, graph.config)
graph.iterateOutlineNodes(n, graph.fileSymbols(fileIndex).deduplicateSymInfoPair)
@@ -1039,6 +1112,19 @@ proc executeNoHooksV3(cmd: IdeCmd, file: AbsoluteFile, dirtyfile: AbsoluteFile,
graph.markDirty fileIndex
graph.markClientsDirty fileIndex
of ideInlayHints:
myLog fmt "Executing inlayHints"
var endLine = 0
var endCol = -1
var i = 0
i += skipWhile(tag, seps, i)
i += parseInt(tag, endLine, i)
i += skipWhile(tag, seps, i)
i += parseInt(tag, endCol, i)
let s = graph.findSymDataInRange(file, line, col, endLine, endCol)
for q in s:
if q.sym.kind in {skLet, skVar, skForVar, skConst} and q.isDecl and not q.sym.hasUserSpecifiedType:
graph.suggestInlayHintResult(q.sym, q.info, ideInlayHints)
else:
myLog fmt "Discarding {cmd}"

View File

@@ -0,0 +1,34 @@
# Monitor a client process and shutdown the current process, if the client
# process is found to be dead
import os
when defined(posix):
import posix_utils
import posix
when defined(windows):
import winlean
when defined(posix):
proc monitorClientProcessIdThreadProc(pid: int) {.thread.} =
while true:
sleep(1000)
try:
sendSignal(Pid(pid), 0)
except:
discard kill(Pid(getCurrentProcessId()), cint(SIGTERM))
when defined(windows):
proc monitorClientProcessIdThreadProc(pid: int) {.thread.} =
var process = openProcess(SYNCHRONIZE, 0, DWORD(pid))
if process != 0:
discard waitForSingleObject(process, INFINITE)
discard closeHandle(process)
quit(0)
var tid: Thread[int]
proc hookProcMonitor*(pid: int) =
when defined(posix) or defined(windows):
createThread(tid, monitorClientProcessIdThreadProc, pid)

View File

@@ -0,0 +1,6 @@
type A* = tuple
a: int
b: int
var x*: A = (a: 2, b: 10)
var y* = (a: 2, b: 10)

View File

@@ -0,0 +1,8 @@
discard """
$nimsuggest --tester $file
>sug $1
sug;;skField;;a;;int;;*module_20265.nim;;6;;10;;"";;100;;None
sug;;skField;;b;;int;;*module_20265.nim;;6;;16;;"";;100;;None
"""
import module_20265
y.#[!]#

View File

@@ -0,0 +1,8 @@
discard """
$nimsuggest --tester $file
>sug $1
sug;;skField;;a;;int;;*module_20265.nim;;2;;2;;"";;100;;None
sug;;skField;;b;;int;;*module_20265.nim;;3;;2;;"";;100;;None
"""
import module_20265
x.#[!]#

View File

@@ -1,9 +1,9 @@
discard """
$nimsuggest --tester $file
>def $1
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"Return hello";;100
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].};;$file;;9;;5;;"Return hello";;100
>def $1
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"Return hello";;100
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].};;$file;;9;;5;;"Return hello";;100
"""
proc hello(): string =

View File

@@ -15,7 +15,7 @@ discard """
$nimsuggest --tester --maxresults:2 $file
>sug $1
sug;;skProc;;tdot4.main;;proc (inp: string): string;;$file;;6;;5;;"";;100;;None
sug;;skFunc;;mstrutils.replace;;proc (s: string, sub: string, by: string): string{.noSideEffect, gcsafe, locks: 0.};;*fixtures/mstrutils.nim;;9;;5;;"this is a test version of strutils.replace, it simply returns `by`";;100;;None
sug;;skFunc;;mstrutils.replace;;proc (s: string, sub: string, by: string): string{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].};;*fixtures/mstrutils.nim;;9;;5;;"this is a test version of strutils.replace, it simply returns `by`";;100;;None
"""
# TODO - determine appropriate behaviour for further suggest output and test it

View File

@@ -0,0 +1,15 @@
{.warning: "I'm a warning!".}
{.error: "I'm an error!".}
{.fatal: "I'm a fatal error!".}
{.error: "I'm an error after fatal error!".}
#[!]#
discard """
$nimsuggest --tester $file
>chk $1
chk;;skUnknown;;;;Hint;;???;;0;;-1;;">> (toplevel): import(dirty): tests/tfatal1.nim [Processing]";;0
chk;;skUnknown;;;;Warning;;$file;;1;;9;;"I\'m a warning! [User]";;0
chk;;skUnknown;;;;Error;;$file;;2;;7;;"I\'m an error!";;0
chk;;skUnknown;;;;Error;;$file;;3;;7;;"fatal error: I\'m a fatal error!";;0
chk;;skUnknown;;;;Error;;$file;;4;;7;;"I\'m an error after fatal error!";;0
"""

View File

@@ -11,7 +11,7 @@ go()
discard """
$nimsuggest --tester $file
>def $path/tinclude.nim:7:14
def;;skProc;;minclude_import.create;;proc (greeting: string, subject: string): Greet{.noSideEffect, gcsafe, locks: 0.};;*fixtures/minclude_include.nim;;3;;5;;"";;100
def;;skProc;;minclude_import.create;;proc (greeting: string, subject: string): Greet{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].};;*fixtures/minclude_include.nim;;3;;5;;"";;100
>def $path/fixtures/minclude_include.nim:3:71
def;;skType;;minclude_types.Greet;;Greet;;*fixtures/minclude_types.nim;;4;;2;;"";;100
>def $path/fixtures/minclude_include.nim:3:71

View File

@@ -6,7 +6,7 @@ tmp#[!]#
discard """
$nimsuggest --tester $file
>sug $1
sug;;skMacro;;tsug_template.tmpb;;macro (){.noSideEffect, gcsafe, locks: 0.};;$file;;2;;6;;"";;100;;Prefix
sug;;skMacro;;tsug_template.tmpb;;macro (){.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].};;$file;;2;;6;;"";;100;;Prefix
sug;;skConverter;;tsug_template.tmpc;;converter ();;$file;;3;;10;;"";;100;;Prefix
sug;;skTemplate;;tsug_template.tmpa;;template ();;$file;;1;;9;;"";;100;;Prefix
"""

View File

@@ -14,9 +14,9 @@ proc #[!]#someProc*() =
discard """
$nimsuggest --tester $file
>use $1
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"";;100
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0.};;$file;;12;;0;;"";;100
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].};;$file;;9;;5;;"";;100
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].};;$file;;12;;0;;"";;100
>use $2
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"";;100
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0.};;$file;;12;;0;;"";;100
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].};;$file;;9;;5;;"";;100
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].};;$file;;12;;0;;"";;100
"""

View File

@@ -0,0 +1,15 @@
discard """
$nimsuggest --tester $file
>use $1
def;;skEnumField;;tuse_enum.Colour.Red;;Colour;;$file;;10;;4;;"";;100
use;;skEnumField;;tuse_enum.Colour.Red;;Colour;;$file;;14;;8;;"";;100
"""
type
Colour = enum
Red
Green
Blue
discard #[!]#Red

View File

@@ -19,7 +19,7 @@ def skField tv3.Foo.bar string $file 5 4 "" 100
>sug $1
sug skField bar string $file 5 4 "" 100 Prefix
>globalSymbols test
def skProc tv3.test proc (f: Foo){.gcsafe, locks: 0.} $file 7 5 "" 100
def skProc tv3.test proc (f: Foo){.gcsafe, locks: 0, raises: <inferred> [].} $file 7 5 "" 100
>globalSymbols Foo
def skType tv3.Foo Foo $file 4 2 "" 100
>def $2

View File

@@ -0,0 +1,13 @@
# tests v3
proc test(a: string, b:string) = discard
proc test(a: int) = discard
test(#[!]#
discard """
$nimsuggest --v3 --tester $file
>con $1
con;;skProc;;tv3_con.test;;proc (a: string, b: string);;$file;;3;;5;;"";;100
con;;skProc;;tv3_con.test;;proc (a: int);;$file;;4;;5;;"";;100
"""

View File

@@ -7,17 +7,17 @@ let a = de#[!]#mo()
discard """
$nimsuggest --v3 --tester $file
>use $1
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 1 5 "" 100
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 3 5 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 5 8 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 1 5 "" 100
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 3 5 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 5 8 "" 100
>use $2
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 1 5 "" 100
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 3 5 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 5 8 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 1 5 "" 100
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 3 5 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 5 8 "" 100
>declaration $1
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 3 5 "" 100
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 3 5 "" 100
>declaration $2
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 1 5 "" 100
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 1 5 "" 100
>declaration $3
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 1 5 "" 100
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 1 5 "" 100
"""

View File

@@ -7,8 +7,8 @@ proc BBtokenA(): int = 5
discard """
$nimsuggest --v3 --tester $file
>globalSymbols token
def skProc tv3_globalSymbols.token proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 4 5 "" 100
def skProc tv3_globalSymbols.tokenA proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 3 5 "" 100
def skProc tv3_globalSymbols.Btoken proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 2 5 "" 100
def skProc tv3_globalSymbols.BBtokenA proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 5 5 "" 100
def skProc tv3_globalSymbols.token proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 4 5 "" 100
def skProc tv3_globalSymbols.tokenA proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 3 5 "" 100
def skProc tv3_globalSymbols.Btoken proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 2 5 "" 100
def skProc tv3_globalSymbols.BBtokenA proc (): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 5 5 "" 100
"""

View File

@@ -33,13 +33,13 @@ outline skType tv3_outline.FooEnum FooEnum $file 6 2 "" 100 6 31
outline skEnumField tv3_outline.FooEnum.value1 FooEnum $file 6 17 "" 100 6 23
outline skEnumField tv3_outline.FooEnum.value2 FooEnum $file 6 25 "" 100 6 31
outline skType tv3_outline.FooPrivate FooPrivate $file 7 2 "" 100 8 22
outline skMacro tv3_outline.m macro (arg: untyped): untyped{.noSideEffect, gcsafe, locks: 0.} $file 10 6 "" 100 10 40
outline skMacro tv3_outline.m macro (arg: untyped): untyped{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 10 6 "" 100 10 40
outline skTemplate tv3_outline.t template (arg: untyped): untyped $file 11 9 "" 100 11 43
outline skProc tv3_outline.p proc (){.noSideEffect, gcsafe, locks: 0.} $file 12 5 "" 100 12 24
outline skConverter tv3_outline.c converter (s: string): int{.noSideEffect, gcsafe, locks: 0.} $file 14 10 "" 100 14 37
outline skFunc tv3_outline.f proc (){.noSideEffect, gcsafe, locks: 0.} $file 16 5 "" 100 16 24
outline skProc tv3_outline.p proc (){.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 12 5 "" 100 12 24
outline skConverter tv3_outline.c converter (s: string): int{.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 14 10 "" 100 14 37
outline skFunc tv3_outline.f proc (){.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 16 5 "" 100 16 24
outline skConst tv3_outline.con int literal(2) $file 20 6 "" 100 20 13
outline skProc tv3_outline.outer proc (){.noSideEffect, gcsafe, locks: 0.} $file 22 5 "" 100 23 24
outline skProc tv3_outline.outer.inner proc (){.noSideEffect, gcsafe, locks: 0.} $file 23 7 "" 100 23 24
outline skProc tv3_outline.procWithLocal proc (){.noSideEffect, gcsafe, locks: 0.} $file 25 5 "" 100 26 16
outline skProc tv3_outline.outer proc (){.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 22 5 "" 100 23 24
outline skProc tv3_outline.outer.inner proc (){.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 23 7 "" 100 23 24
outline skProc tv3_outline.procWithLocal proc (){.noSideEffect, gcsafe, locks: 0, raises: <inferred> [].} $file 25 5 "" 100 26 16
"""

View File

@@ -45,7 +45,7 @@ $nimsuggest --tester --maxresults:5 $file
>sug $1
sug;;skField;;age;;int;;$file;;6;;6;;"";;100;;None
sug;;skField;;name;;string;;$file;;5;;6;;"";;100;;None
sug;;skMethod;;twithin_macro.age_human_yrs;;proc (self: Animal): int;;$file;;8;;9;;"";;100;;None
sug;;skMethod;;twithin_macro.vocalize;;proc (self: Animal): string;;$file;;7;;9;;"";;100;;None
sug;;skMethod;;twithin_macro.age_human_yrs;;proc (self: Animal): int{.raises: <inferred> [].};;$file;;8;;9;;"";;100;;None
sug;;skMethod;;twithin_macro.vocalize;;proc (self: Animal): string{.raises: <inferred> [].};;$file;;7;;9;;"";;100;;None
sug;;skMethod;;twithin_macro.vocalize;;proc (self: Rabbit): string;;$file;;23;;9;;"";;100;;None
"""

View File

@@ -44,5 +44,5 @@ discard """
$nimsuggest --tester $file
>sug $1
sug;;skField;;age;;int;;$file;;6;;6;;"";;100;;Prefix
sug;;skMethod;;twithin_macro_prefix.age_human_yrs;;proc (self: Animal): int;;$file;;8;;9;;"";;100;;Prefix
sug;;skMethod;;twithin_macro_prefix.age_human_yrs;;proc (self: Animal): int{.raises: <inferred> [].};;$file;;8;;9;;"";;100;;Prefix
"""

View File

@@ -50,7 +50,7 @@ pkg "c2nim", "nim c testsuite/tester.nim"
pkg "cascade"
pkg "cello"
pkg "chroma"
pkg "chronicles", "nim c -o:chr -r chronicles.nim", url = "https://github.com/nim-lang/nim-chronicles"
pkg "chronicles", "nim c -o:chr -r chronicles.nim"
pkg "chronos", "nim c -r -d:release tests/testall"
pkg "cligen", "nim c --path:. -r cligen.nim"
pkg "combparser", "nimble test --gc:orc"
@@ -112,7 +112,6 @@ pkg "nimquery"
pkg "nimsl"
pkg "nimsvg"
pkg "nimterop", "nimble minitest"
pkg "nimwc", "nim c nimwc.nim"
pkg "nimx", "nim c --threads:on test/main.nim", allowFailure = true
pkg "nitter", "nim c src/nitter.nim", "https://github.com/zedeus/nitter"
# pkg "norm", "testament r tests/sqlite/trows.nim"
@@ -128,7 +127,7 @@ pkg "pnm"
pkg "polypbren"
pkg "prologue", "nimble tcompile"
pkg "protobuf", "nim c -o:protobuff -r src/protobuf.nim"
pkg "pylib"
# pkg "pylib"
pkg "rbtree"
pkg "react", "nimble example"
pkg "regex", "nim c src/regex"
@@ -140,7 +139,7 @@ pkg "sdl2_nim", "nim c -r sdl2/sdl.nim"
pkg "sigv4", "nim c --gc:arc -r sigv4.nim", "https://github.com/disruptek/sigv4"
pkg "sim"
pkg "snip", "nimble test", "https://github.com/genotrance/snip"
pkg "stint", "nim r stint.nim"
pkg "stint", "nim c stint.nim"
pkg "strslice"
pkg "strunicode", "nim c -r src/strunicode.nim"
pkg "supersnappy"
@@ -162,6 +161,6 @@ pkg "websocket", "nim c websocket.nim"
pkg "winim", "nim c winim.nim"
pkg "with"
pkg "ws", allowFailure = true
pkg "yaml", "nim c -r test/tserialization.nim"
# pkg "yaml", "nim c -r test/tserialization.nim"
pkg "zero_functional", "nim c -r -d:nimNoLentIterators test.nim"
pkg "zippy"

View File

@@ -51,3 +51,19 @@ type Bug[T] = object
var bug: Bug[int]
doAssert sizeof(bug) == 128, "Oops my size is " & $sizeof(bug) # 16
block: # bug #22419
type
ValidatorPubKey = object
blob: array[96, byte]
proc f(): auto =
return iterator() =
var pad: int8 = 0
var y {.align: 16.}: ValidatorPubKey
let value = cast[uint64](addr y)
doAssert value mod 16 == 0
f()()

55
tests/arc/t22237.nim Normal file
View File

@@ -0,0 +1,55 @@
discard """
matrix: "--mm:arc; --mm:orc"
"""
import std/macros
import std/streams
# bug #22237
proc iterlines_closure2(f: File | Stream): iterator (): string =
result = iterator(): string =
for line in f.lines:
if line.len == 0:
break
yield line
proc test() =
let f = newStringStream("""
1
2
3
4
5
6
7
8
""")
while not f.atEnd():
let iterator_inst = iterlines_closure2(f)
for item in iterator_inst(): # Fails with "SIGSEGV: Illegal storage access. (Attempt to read from nil?)"
discard
test()
# bug #21160
import sequtils
iterator allMoves(fls: seq[int]): seq[int] =
yield fls
proc neighbors(flrs: seq[int]): iterator: seq[int] =
return iterator(): seq[int] =
for flrs2 in allMoves(flrs):
yield flrs2
for flrs3 in allMoves(flrs2):
yield flrs3
let f = @[1]
for _ in neighbors(f):
discard
for _ in neighbors(f):
discard

View File

@@ -45,3 +45,33 @@ proc main() = # todo bug with templates
doAssert b() == @[]
static: main()
main()
block: # bug #21974
type Test[T] = ref object
values : seq[T]
counter: int
proc newTest[T](): Test[T] =
result = new(Test[T])
result.values = newSeq[T](16)
result.counter = 0
proc push[T](self: Test[T], value: T) =
self.counter += 1
if self.counter >= self.values.len:
self.values.setLen(self.values.len * 2)
self.values[self.counter - 1] = value
proc pop[T](self: Test[T]): T =
result = self.values[0]
self.values[0] = self.values[self.counter - 1] # <--- This line
self.counter -= 1
type X = tuple
priority: int
value : string
var a = newTest[X]()
a.push((1, "One"))
doAssert a.pop.value == "One"

View File

@@ -76,7 +76,7 @@ var c = Control(x: 7)
run(c)
proc sysFatal(exceptn: typedesc, message: string) {.inline, noreturn.} =
proc sysFatal(exceptn: typedesc, message: string) {.inline.} =
var buf = newStringOfCap(200)
add(buf, "##")
add(buf, message)

View File

@@ -1,5 +1,6 @@
discard """
cmd: "nim $target --hints:on --define:ssl $options $file"
disabled: osx
"""
import asyncdispatch, asyncnet, net, strutils

22
tests/ccgbugs/t15428.nim Normal file
View File

@@ -0,0 +1,22 @@
discard """
cmd: "nim $target --mm:refc $file"
output: '''5
5
[1, 2, 3, 4, 5]
(data: [1, 2, 3, 4, 5])
'''
"""
proc take[T](f: openArray[T]) =
echo f.len
let f = @[0,1,2,3,4]
take(f.toOpenArray(0,4))
{.experimental: "views".}
type
Foo = object
data: openArray[int]
let f2 = Foo(data: [1,2,3,4,5])
echo f2.data.len
echo f2.data
echo f2

19
tests/ccgbugs/t22462.nim Normal file
View File

@@ -0,0 +1,19 @@
discard """
action: "run"
output: '''
1
1
1
'''
targets: "c cpp"
"""
type Object = object
someComplexType: seq[int]
index: Natural
func newObject(): Object = result.index.inc
for i in 1..3:
let o = newObject()
echo o.index

View File

@@ -122,3 +122,13 @@ proc bug19613 =
doAssert x.bid.root.data[0] == 42
bug19613()
proc foo = # bug #23280
let foo = @[1,2,3,4,5,6]
doAssert toOpenArray(foo, 0, 5).len == 6
doAssert toOpenArray(foo, 0, 5).len mod 6 == 0 # this should output 0
doAssert toOpenArray(foo, 0, 5).max mod 6 == 0
let L = toOpenArray(foo, 0, 5).len
doAssert L mod 6 == 0
foo()

View File

@@ -1,3 +1,8 @@
discard """
targets: "c cpp"
matrix: "--gc:refc; --gc:arc"
"""
# bug #1833
iterator myitems*[T](a: var seq[T]): var T {.inline.} =
## iterates over each item of `a` so that you can modify the yielded value.
@@ -18,3 +23,13 @@ var ys = @[(1,"a"),(2,"b"),(3,"c")]
for y in myitems(ys):
inc y[0]
# bug #16331
type T1 = tuple[a, b: int]
proc p(b: bool): string =
var x: T1 = (10, 20)
x = if b: (x.b, x.a) else: (-x.b, -x.a)
$x
assert p(false) == "(a: -20, b: -10)"
assert p(true) == "(a: 20, b: 10)"

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