Compare commits

...

87 Commits

Author SHA1 Message Date
Nikolay Nikolov
b47747d318 [backport v2.0] Converted the 'invalid kind for firstOrd/lastOrd(XXX)' messages from internal errors to fatal errors. (#23443) (#23446)
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-03-27 15:58:56 +01:00
Александр Старочкин
5667fbfbf3 fix position for "imported but not used" warning for modules inside brackets (#23424) 2024-03-21 08:03:31 +01:00
narimiran
d4b58b0b06 bump NimVersion to 2.0.4 2024-03-19 16:39:02 +01:00
Nikolay Nikolov
ef356cfd4b * [backport] fixed nimsuggest crash with 'Something = concept' put (erroneously) outside of a 'type' block (#23331) (#23346)
(cherry picked from commit 37ed8c8480)
2024-03-19 05:46:52 +01:00
Juan M Gómez
e374759f29 [Backport 2.0] When NimScript errors prevents NimSuggest from Init (#23349) 2024-03-09 11:42:34 +01:00
Juan M Gómez
0de70dc7f3 [backport 2.0] nimsuggest fix (#23336) 2024-03-04 09:58:54 +01:00
Andreas Rumpf
2f15b67fd9 fixes an issue with string to 'var openArray' at compile-time; [backport] (#23363)
(cherry picked from commit 24fbacc63f)
2024-03-03 15:42:20 +01:00
ringabout
e03667e920 improve error messages [backport] (#23345)
ref https://forum.nim-lang.org/t/11052

![image](https://github.com/nim-lang/Nim/assets/43030857/1df87691-32d9-46b5-b61b-6b9f7cc94862)

(cherry picked from commit 1e7ca2dc78)
2024-02-27 08:17:37 +01:00
Nikolay Nikolov
11c048b06f fixes #22753; Nimsuggest segfault with invalid assignment to table (#22781) (#23313)
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-02-24 07:54:42 +01:00
Nikolay Nikolov
22de3ae53e * fixed nimsuggest crash when opening a .nim file, that contain a {.fatal: "msg".} pragma. (#23325) (#23328)
(cherry picked from commit 773c066634)
2024-02-24 07:40:18 +01:00
Juan M Gómez
3be2514683 [Backport 2.0] Itanium mangling scheme (#23301) 2024-02-13 08:09:23 +01:00
ringabout
57658b685c fixes regression #23280; Operations on inline toOpenArray len return a wrong result (#23285)
fixes #23280

(cherry picked from commit 4b67cccf50)
2024-02-07 20:25:45 +01:00
ringabout
5f6ff1f051 compute checksum of nim files early in the pipelines (#23268)
related https://github.com/nim-lang/Nim/issues/21717 configs will be
resolved later

(cherry picked from commit 519d976f62)
2024-02-01 12:30:21 +01:00
rockcavera
7e6f4723c3 Fix system.currentSourcePath() documentation [backport 2.0] (#23243)
The documentation links for `parentDir()` and `getCurrentDir()` are
broken as they are no longer part of `std/os`. Link changed to
`std/private/ospaths2`.

(cherry picked from commit 9c155eaccc)
2024-01-30 08:11:10 +01:00
metagn
4a1151d6b4 give typedesc param nodes type T not typedesc[T] [backport:2.0] (#23115)
fixes https://github.com/nim-lang/Nim/issues/23112, fixes a mistake in
https://github.com/nim-lang/Nim/pull/22581

This makes `getType(t)` where `t` is a typedesc param with value `T`
equal to `getType(T)`.

(cherry picked from commit 3224337550)
2024-01-19 09:19:18 +01:00
Giuliano Mega
9994b019c5 Fix reset code gen for range types (#22462, #23214) (#23215)
This PR modifies `specializeResetT` so that it generates the proper
reset code for range types. I've tested it in the examples for issues
issues I had been experiencing.

(cherry picked from commit 473f259268)
2024-01-19 09:18:23 +01:00
metagn
bb930aef2d don't render underscore identifiers with id (#22538)
(cherry picked from commit 4f891aa50c)
2024-01-16 08:43:09 +01:00
Nikolay Nikolov
be66aedb9e + show the inferred exception list (as part of the type) for functions that don't have an explicit .raises pragma (#23193) (#23210)
(cherry picked from commit 18b5fb256d)
2024-01-16 15:36:03 +08:00
Juan M Gómez
4bc305db1e backport nimsuggest capabilities to 2.0 (#23191) 2024-01-09 22:48:18 +08:00
Juan M Gómez
fdb1f4451d makes nimsuggest con work under v3 [backport 2.0.2] (#23159)
Co-authored-by: Jake Leahy <jake@leahy.dev>
2024-01-08 20:30:59 +01:00
metagn
02497c9533 2.0 branch fixes: no LineTooLong, update macos CI (#23184)
Adapts #23108 to the version-2-0 branch and makes the 2.0 compiler
define `nimHasNoLineTooLong` as the devel compiler depends on it to not
turn off `hint[LineTooLong]`, which means the 2.0 compiler errors on the
devel compiler config (as mentioned in
https://github.com/nim-lang/Nim/issues/23178#issuecomment-1880511322).

Would have these as separate PRs but the macos CI PR would have to be
merged first, then the second PR would have to be rebased.
2024-01-08 13:49:20 +01:00
ringabout
0acdce502c fixes #23148; restricts infix path concatenation to what starts with / (#23150)
fixes #23148

(cherry picked from commit c7d742e484)
2024-01-03 10:57:42 +01:00
narimiran
fe1d4a6232 bump NimVersion to 2.0.3 2024-01-03 10:57:30 +01:00
narimiran
c4c44d10df bump NimVersion to 2.0.2 2023-12-14 17:51:05 +01:00
ringabout
55bb60a56b fixes #22947; static integers in quote do [backport] (#22948)
fixes #22947

(cherry picked from commit 09ea1b168f)
2023-12-14 17:48:55 +01:00
Amjad Ben Hedhili
ef8b8317ff Fix capacity for const and shallow [backport] (#22705)
(cherry picked from commit b542be1e7d)
2023-12-14 17:47:00 +01:00
Nikolay Nikolov
fff127bec7 Skip trailing asterisk when placing inlay type hints. Fixes #23067 (backport of #23068) (#23070)
(cherry picked from commit a3739751a8)
2023-12-14 09:26:01 +08:00
Kernel-Zhang
7b5289a1a4 Correction of “Tnfds” type error (#23045)
The types in Nim don't match the actual types in the header files, this
can lead to bugs in some cases.
2023-12-08 11:09:49 +01:00
Nikolay Nikolov
3a0d09c1c5 backport to version 2.0: display raises pragma in proc types (#23026) (#23028)
This affects also nimsuggest hints (e.g. on mouse hover), as well as
compiler messages.

(cherry picked from commit 618ccb6b6a)
2023-12-04 09:46:57 +01:00
metagn
3ab6012c81 fix generic param substitution in templates (#22535)
* fix generic param substitution in templates

fixes #13527, fixes #17240, fixes #6340, fixes #20033, fixes #19576, fixes #19076

* fix bare except in test, test updated packages in CI

(cherry picked from commit 1cc4d3f622)
2023-12-01 08:27:06 +01:00
Jake Leahy
add124e07a 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:56 +01:00
tersec
8834f3e74d 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:40 +01:00
Nikolay Nikolov
489dd89a45 backport to v 2.0: nimsuggest: Added optional command line option '--clientProcessId:XXX' (#22969) (#22981)
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:27 +01:00
Nikolay Nikolov
ba9effc8a1 Backport to 2.0: Introduced version 4 of the NimSuggest protocol. The InlayHints feature made V4 or later only. (#22953) (#22963)
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:33 +08:00
Nikolay Nikolov
0d93fdf607 backport to version 2.0: nimsuggest: Instead of checking for protocol version 3 exactly, check for version 3 or later. (#22945) (#22957)
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:06 +08:00
Nikolay Nikolov
b8cec0c714 Added new command line option --info:X to nimsuggest for obtaining … (#22943)
…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-16 20:30:22 +08:00
Nikolay Nikolov
4793fc0fc1 Inlay hints backport to Nim v2.0.x (#22919)
Backport of the nimsuggest inlay hints to the Nim v2.0.x series.
2023-11-09 07:33:20 +01:00
ringabout
e1b44666b0 iNim switch to the official URL (#22762)
ref https://github.com/inim-repl/INim/pull/139

(cherry picked from commit 02ba28eda5)
2023-11-08 13:55:49 +01:00
ringabout
194d21a6e4 fixes stint CI (#22756)
(cherry picked from commit 46544f234d)
2023-11-08 13:55:41 +01:00
metagn
1b80f7126a switch back to main neo in CI (#22660)
refs https://github.com/andreaferretti/neo/pull/53

(cherry picked from commit b9f039e0c3)
2023-11-08 13:55:31 +01:00
ringabout
1dc85802e2 add union to packages (#22658)
(cherry picked from commit 009ce1e17e)
2023-11-08 13:55:23 +01:00
ringabout
9e081579bb fixes yaml tests (#22595)
(cherry picked from commit dfb3a88cc3)
2023-11-08 13:55:15 +01:00
ringabout
30dad5dfa1 deprecate std/threadpool; use malebolgia, weave, nim-taskpool instead (#22576)
* deprecate `std/threadpool`; use `malebolgia` instead

* Apply suggestions from code review

* Apply suggestions from code review

* change the URL of inim

(cherry picked from commit a7a0105d8c)
2023-11-08 13:55:01 +01:00
ringabout
6d32066055 update test command of important packages (#22485)
(cherry picked from commit 9296b45de4)
2023-11-08 13:54:54 +01:00
ringabout
86e5545c25 fixes #22866; fixes #19998; ensure destruction for Object construction with custom destructors (#22901)
fixes #22866;
fixes #19998

(cherry picked from commit b68e0aab4c)
2023-11-02 14:40:40 +01:00
ringabout
f4e80d51ff bump node to 20.x; since 16.x is End-of-Life (#22892)
(cherry picked from commit f61311f7a0)
2023-10-31 07:08:42 +01:00
ringabout
1db305af1c fixes #22868; fixes std/nre leaks under ARC/ORC (#22872)
fixes #22868

(cherry picked from commit d66f3febd1)
2023-10-29 18:14:45 +01:00
握猫猫
805b4e2dc2 fix use after free (#22854)
1. `freeAddrInfo` is called prematurely, the variable `myAddr` is still
in use
2. Use defer syntax to ensure that `freeAddrInfo` is also called on
exceptions

(cherry picked from commit 562a5fb8f9)
2023-10-24 08:57:38 +02:00
rockcavera
e8e9948223 fix #22834 (#22843)
fix #22834

Edit: also fixes `result.addrList` when IPv6, which previously only
performed a `result.addrList = cstringArrayToSeq(s.h_addr_list)` which
does not provide the textual representation of an IPv6

(cherry picked from commit 27deacecaa)
2023-10-24 08:57:25 +02:00
Amjad Ben Hedhili
75441dcdc3 Initialize newString in js [backport:1.6] (#22745)
```nim
echo newString(8)
```

results in:
```
D:\User\test.js:25
                  var code_33556944 = c_33556931.toString(16);
                                                 ^

TypeError: Cannot read properties of undefined (reading 'toString')
    at toJSStr (D:\User\test.js:25:50)
    at rawEcho (D:\User\test.js:70:16)
    at Object.<anonymous> (D:\User\test.js:101:1)
    at Module._compile (node:internal/modules/cjs/loader:1095:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1147:10)
    at Module.load (node:internal/modules/cjs/loader:975:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:17:47

Node.js v17.0.1
Error: execution of an external program failed: '"C:\Program Files\nodejs\node.exe" --unhandled-rejections=strict D:\User\test.js'
```

(cherry picked from commit eadd0d72cf)
2023-10-24 08:49:16 +02:00
SirOlaf
d30565f810 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-18 12:13:00 +02:00
Amjad Ben Hedhili
5c916b645b Remove some unnecessary initialization in string operations (#22579)
* `prepareAdd`
* `toNimStr`
* `setLengthStrV2`
* `NimAsgnStrV2`
* `prepareMutation`
* Some cleanups

(cherry picked from commit a4df44d9fb)
2023-09-18 12:13:00 +02:00
SirOlaf
9ad184841e Exclude block from endsInNoReturn, fix regression (#22632)
Co-authored-by: SirOlaf <>
(cherry picked from commit d2f36c071b)
2023-09-18 12:13:00 +02:00
metagn
7536d7f94a use dummy dest for void branches to fix noreturn in VM (#22617)
fixes #22216

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

(cherry picked from commit 6738f44af3)
2023-09-18 12:13:00 +02:00
SirOlaf
d3cf815dbe 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-18 12:12:59 +02:00
ringabout
b477c2adcc fixes #17197; fixes #22560; fixes the dest of newSeqOfCap in refc (#22594)
(cherry picked from commit 5bd1afc3f9)
2023-09-18 12:12:59 +02:00
metagn
78d4aa3d01 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-18 12:12:59 +02:00
metagn
855f5c8b81 clearer error for different size int/float cast in VM (#22582)
refs #16547

(cherry picked from commit b6cea7b599)
2023-09-18 12:12:59 +02:00
metagn
7ab0f3beec 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-18 12:12:59 +02:00
ringabout
ba8c9a9d1e newStringOfCap now won't initialize all elements anymore (#22568)
newStringOfCap nows won't initialize all elements anymore

(cherry picked from commit 2e7c8a339f)
2023-09-18 12:12:59 +02:00
metagn
87c1200c93 test case haul for old generic/template/macro issues (#22564)
* test case haul for old generic/template/macro issues

closes #12582, closes #19552, closes #2465, closes #4596, closes #15246,
closes #12683, closes #7889, closes #4547, closes #12415, closes #2002,
closes #1771, closes #5121

The test for #5648 is also moved into its own test
from `types/tissues_types` due to not being joinable.

* fix template gensym test

(cherry picked from commit c19fd69b69)
2023-09-18 12:12:58 +02:00
ringabout
d46e71bea3 fixes #22541; peg matchLen can raise an unlisted exception: Exception (#22545)
The `mopProc` is a recursive function.

(cherry picked from commit c56a712e7d)
2023-09-18 12:12:58 +02:00
SirOlaf
4cf2658235 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-18 12:12:58 +02:00
metagn
5fa48e97b6 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-18 12:12:58 +02:00
ringabout
562fb0d14b 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-18 12:12:58 +02:00
Emery Hemingway
320ecc69a0 Add Linux constant SO_BINDTODEVICE (#22468)
(cherry picked from commit 1927ae72d0)
2023-09-18 12:12:58 +02:00
Bung
106cf7a9f7 Fix #5780 (#22428)
* fix #5780

(cherry picked from commit 46e94c83d4)
2023-09-18 10:13:38 +02:00
Jake Leahy
7221c6f156 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-18 10:13:27 +02:00
ringabout
4a7cdaecb4 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-18 10:13:09 +02:00
Amjad Ben Hedhili
81d58d2cc8 Make capacity work with refc [backport] (#22697)
followup of #19771.

(cherry picked from commit 325341866f)
2023-09-14 06:02:46 +02:00
Andreas Rumpf
1080f5eba2 produce better code for object constructions and 'result' [backport] (#22668)
(cherry picked from commit 8f5b90f886)
2023-09-14 06:02:30 +02:00
ringabout
18e62ad136 fixes #22619; don't lift cursor fields in the hook calls (#22638)
fixes https://github.com/nim-lang/Nim/issues/22619

It causes double free for closure iterators because cursor fields are
destroyed in the lifted destructors of `Env`.

Besides, according to the Nim manual

> In fact, cursor more generally prevents object
construction/destruction pairs and so can also be useful in other
contexts.

At least, destruction of cursor fields might cause troubles.

todo
- [x] tests
- [x] revert a certain old PR

---------

Co-authored-by: zerbina <100542850+zerbina@users.noreply.github.com>
(cherry picked from commit eb91cf991a)
2023-09-05 11:50:59 +02:00
metagn
f03aa1d0b5 define toList procs after add for lists [backport] (#22573)
fixes #22543

(cherry picked from commit 94454addb2)
2023-09-05 11:50:41 +02:00
Daniel Belmes
ef63d47ecd fix server caching issue causing Theme failures (#22378)
* fix server caching issue causing Theme failures

* Fix tester to ignore version cache param

* fix case of people using -d:nimTestsNimdocFixup

* rsttester needed the same fix

(cherry picked from commit 7bf7496557)
2023-08-22 08:28:30 +02:00
ringabout
0a58af8cbf fixes #22357; don't sink elements of var tuple cursors (#22486)
(cherry picked from commit 940b1607b8)
2023-08-22 08:23:56 +02:00
Jason Beetham
8359f9683a 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-08-22 08:23:32 +02:00
ringabout
c3425c05e9 relax the parameter of ensureMove; allow let statements (#22466)
* relax the parameter of `ensureMove`; allow let statements

* fixes the test

(cherry picked from commit 4c89223171)
2023-08-22 08:23:06 +02:00
Alberto Torres
3fa378533a Fix #22366 by making nimlf_/nimln_ part of the same line (backport) (#22508) 2023-08-22 08:22:58 +02:00
Amjad Ben Hedhili
4850bb5a59 fix seq.capacity [backport] (#22505) 2023-08-22 08:22:42 +02:00
ringabout
037f536e7e 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:49:49 +02:00
ringabout
287fbc5fb5 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:49:30 +02:00
metagn
f553288db3 block ambiguous type conversion dotcalls in generics (#22375)
fixes #22373

(cherry picked from commit 3aaef9e4cf)
2023-08-11 10:49:11 +02:00
norrath-hero-cn
e0e386314f 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:48:21 +02:00
Michal Maršálek
1de6a7a023 Fix the position of "Grey" in colors.nim (#22358)
Update the position of "Grey"

(cherry picked from commit da368885da)
2023-08-11 10:47:54 +02:00
narimiran
d1db4c29fa bump NimVersion to 2.0.1 2023-08-11 10:47:05 +02:00
narimiran
a488067a41 bump NimVersion to 2.0.0 2023-07-31 21:22:28 +02:00
131 changed files with 2121 additions and 432 deletions

View File

@@ -21,10 +21,10 @@ jobs:
with:
fetch-depth: 2
- name: 'Install node.js 16.x'
uses: actions/setup-node@v3
- name: 'Install node.js 20.x'
uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '20.x'
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'

View File

@@ -47,7 +47,7 @@ jobs:
- target: windows
os: windows-2019
- target: osx
os: macos-11
os: macos-12
name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}

View File

@@ -17,7 +17,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, macos-11]
os: [ubuntu-20.04, macos-12]
cpu: [amd64]
batch: ["allowed_failures", "0_3", "1_3", "2_3"] # list of `index_num`
name: '${{ matrix.os }} (batch: ${{ matrix.batch }})'
@@ -32,10 +32,10 @@ jobs:
with:
fetch-depth: 2
- name: 'Install node.js 16.x'
uses: actions/setup-node@v3
- name: 'Install node.js 20.x'
uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '20.x'
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'

View File

@@ -21,10 +21,10 @@ jobs:
with:
fetch-depth: 2
- name: 'Install node.js 16.x'
uses: actions/setup-node@v3
- name: 'Install node.js 20.x'
uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '20.x'
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'

View File

@@ -29,10 +29,10 @@ jobs:
# vmImage: 'ubuntu-18.04'
# CPU: i386
OSX_amd64:
vmImage: 'macOS-11'
vmImage: 'macOS-12'
CPU: amd64
OSX_amd64_cpp:
vmImage: 'macOS-11'
vmImage: 'macOS-12'
CPU: amd64
NIM_COMPILE_TO_CPP: true
Windows_amd64_batch0_3:

View File

@@ -898,6 +898,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

@@ -616,7 +616,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) =
@@ -1501,6 +1501,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),
@@ -1550,6 +1551,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
var tmp: TLoc
var r: Rope
let needsZeroMem = p.config.selectedGC notin {gcArc, gcAtomicArc, gcOrc} or nfAllFieldsSet notin e.flags
if useTemp:
getTemp(p, t, tmp)
r = rdLoc(tmp)
@@ -1558,10 +1560,13 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
t = t.lastSon.skipTypes(abstractInstOwned)
r = "(*$1)" % [r]
gcUsage(p.config, e)
else:
elif needsZeroMem:
constructLoc(p, tmp)
else:
genObjectInit(p, cpsStmts, t, tmp, constructObj)
else:
resetLoc(p, d)
if needsZeroMem: resetLoc(p, d)
else: genObjectInit(p, cpsStmts, d.t, d, if isRef: constructRefObj else: constructObj)
r = rdLoc(d)
discard getTypeDesc(p.module, t)
let ty = getUniqueType(t)
@@ -1876,9 +1881,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)")

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

@@ -54,13 +54,31 @@ proc mangleField(m: BModule; name: PIdent): string =
if isKeyword(name):
result.add "_0"
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 fillBackendName(m: BModule; s: PSym) =
if s.loc.r == "":
var result = s.name.s.mangle.rope
result.add "__"
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
result.add "_u"
result.addInt s.itemId.item # s.disamb #
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.addInt 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,8 @@ import
ast, types, hashes, strutils, msgs, wordrecg,
platform, trees, options, cgendata
import std/[hashes, strutils, formatfloat]
when defined(nimPreviewSlimSystem):
import std/assertions
@@ -121,10 +123,10 @@ proc mapSetType(conf: ConfigRef; typ: PType): TCTypeKind =
proc ccgIntroducedPtr*(conf: ConfigRef; s: PSym, retType: PType): bool =
var pt = skipTypes(s.typ, typedescInst)
assert skResult != s.kind
#note precedence: params override types
if optByRef in s.options: return true
elif sfByCopy in s.flags: return false
elif sfByCopy in s.flags: return false
elif tfByRef in pt.flags: return true
elif tfByCopy in pt.flags: return false
case pt.kind
@@ -148,3 +150,64 @@ proc ccgIntroducedPtr*(conf: ConfigRef; s: PSym, retType: PType): bool =
result = not (pt.kind in {tyVar, tyArray, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} or
pt.kind == tySet and mapSetType(conf, pt) == ctArray)
proc encodeName*(name: string): string =
result = mangle(name)
result = $result.len & result
proc makeUnique(m: BModule; s: PSym, name: string = ""): string =
result = if name == "": s.name.s else: name
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.owner.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

View File

@@ -311,10 +311,10 @@ proc genLineDir(p: BProc, t: PNode) =
(p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIdx:
if freshLine:
if lastFileIndex == t.info.fileIndex:
linefmt(p, cpsStmts, "nimln_($1);\n",
linefmt(p, cpsStmts, "nimln_($1);",
[line])
else:
linefmt(p, cpsStmts, "nimlf_($1, $2);\n",
linefmt(p, cpsStmts, "nimlf_($1, $2);",
[line, quotedFilename(p.config, t.info)])
proc accessThreadLocalVar(p: BProc, s: PSym)
@@ -986,11 +986,19 @@ proc closureSetup(p: BProc, prc: PSym) =
linefmt(p, cpsStmts, "$1 = ($2) ClE_0;$n",
[rdLoc(env.loc), getTypeDesc(p.module, env.typ)])
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef,
nkMacroDef, nkMixinStmt, nkBindStmt, nkFormalParams} +
declarativeDefs
proc containsResult(n: PNode): bool =
result = false
case n.kind
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkFormalParams:
of succ(nkEmpty)..pred(nkSym), succ(nkSym)..nkNilLit, harmless:
discard
of nkReturnStmt:
for i in 0..<n.len:
if containsResult(n[i]): return true
result = n.len > 0 and n[0].kind == nkEmpty
of nkSym:
if n.sym.kind == skResult:
result = true
@@ -998,10 +1006,6 @@ proc containsResult(n: PNode): bool =
for i in 0..<n.len:
if containsResult(n[i]): return true
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef,
nkMacroDef, nkMixinStmt, nkBindStmt, nkFormalParams} +
declarativeDefs
proc easyResultAsgn(n: PNode): PNode =
case n.kind
of nkStmtList, nkStmtListExpr:
@@ -1175,7 +1179,13 @@ proc genProcAux*(m: BModule, prc: PSym) =
# declare the result symbol:
assignLocalVar(p, resNode)
assert(res.loc.r != "")
initLocalVar(p, res, immediateAsgn=false)
if p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc} and
allPathsAsgnResult(procBody) == InitSkippable:
# In an ideal world the codegen could rely on injectdestructors doing its job properly
# and then the analysis step would not be required.
discard "result init optimized out"
else:
initLocalVar(p, res, immediateAsgn=false)
returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)])
elif sfConstructor in prc.flags:
fillLoc(resNode.sym.loc, locParam, resNode, "this", OnHeap)

View File

@@ -135,6 +135,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

@@ -158,3 +158,4 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimAllowNonVarDestructor")
defineSymbol("nimHasQuirky")
defineSymbol("nimHasEnsureMove")
defineSymbol("nimHasNoLineTooLong")

View File

@@ -1723,7 +1723,7 @@ proc genOutFile(d: PDoc, groupedToc = false): string =
"moduledesc", d.modDescFinal, "date", getDateStr(), "time", getClockStr(),
"content", content, "author", d.meta[metaAuthor],
"version", esc(d.target, d.meta[metaVersion]), "analytics", d.analytics,
"deprecationMsg", d.modDeprecationMsg]
"deprecationMsg", d.modDeprecationMsg, "nimVersion", $NimMajor & "." & $NimMinor & "." & $NimPatch]
else:
code = content
result = code
@@ -1907,7 +1907,7 @@ proc commandBuildIndex*(conf: ConfigRef, dir: string, outFile = RelativeFile"")
"title", "Index",
"subtitle", "", "tableofcontents", "", "moduledesc", "",
"date", getDateStr(), "time", getClockStr(),
"content", content, "author", "", "version", "", "analytics", ""]
"content", content, "author", "", "version", "", "analytics", "", "nimVersion", $NimMajor & "." & $NimMinor & "." & $NimPatch]
# no analytics because context is not available
try:

View File

@@ -19,7 +19,7 @@ import std/[os, osproc, streams, sequtils, times, strtabs, json, jsonutils, suga
import std / strutils except addf
when defined(nimPreviewSlimSystem):
import std/syncio
import std/[syncio, assertions]
import ../dist/checksums/src/checksums/sha1
@@ -992,7 +992,7 @@ type BuildCache = object
depfiles: seq[(string, string)]
nimexe: string
proc writeJsonBuildInstructions*(conf: ConfigRef) =
proc writeJsonBuildInstructions*(conf: ConfigRef; deps: StringTableRef) =
var linkFiles = collect(for it in conf.externalToLink:
var it = it
if conf.noAbsolutePaths: it = it.extractFilename
@@ -1013,10 +1013,14 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
currentDir: getCurrentDir())
if optRun in conf.globalOptions or isDefined(conf, "nimBetterRun"):
bcache.cmdline = conf.commandLine
bcache.depfiles = collect(for it in conf.m.fileInfos:
for it in conf.m.fileInfos:
let path = it.fullPath.string
if isAbsolute(path): # TODO: else?
(path, $secureHashFile(path)))
if path in deps:
bcache.depfiles.add (path, deps[path])
else: # backup for configs etc.
bcache.depfiles.add (path, $secureHashFile(path))
bcache.nimexe = hashNimExe()
conf.jsonBuildFile = conf.jsonBuildInstructionsFile
conf.jsonBuildFile.string.writeFile(bcache.toJson.pretty)

View File

@@ -10,9 +10,6 @@
# This include implements the high level optimization pass.
# included from sem.nim
when defined(nimPreviewSlimSystem):
import std/assertions
proc hlo(c: PContext, n: PNode): PNode
proc evalPattern(c: PContext, n, orig: PNode): PNode =

View File

@@ -344,9 +344,11 @@ proc evalImport*(c: PContext, n: PNode): PNode =
imp[lastPos] = x[1]
impAs[1] = imp
impAs[2] = x[2]
impAs.info = x[2].info
impMod(c, impAs, result)
else:
imp[lastPos] = x
imp.info = x.info
impMod(c, imp, result)
else:
impMod(c, it, result)

View File

@@ -185,7 +185,9 @@ proc isCursor(n: PNode): bool =
template isUnpackedTuple(n: PNode): bool =
## we move out all elements of unpacked tuples,
## hence unpacked tuples themselves don't need to be destroyed
(n.kind == nkSym and n.sym.kind == skTemp and n.sym.typ.kind == tyTuple)
## except it's already a cursor
(n.kind == nkSym and n.sym.kind == skTemp and
n.sym.typ.kind == tyTuple and sfCursor notin n.sym.flags)
proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string; inferredFromCopy = false) =
var m = "'" & opname & "' is not available for type <" & typeToString(t) & ">"
@@ -850,7 +852,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
result[i][1] = p(n[i][1], c, s, m)
else:
result[i] = p(n[i], c, s, m)
if mode == normal and isRefConstr:
if mode == normal and (isRefConstr or (hasDestructor(c, t) and
getAttachedOp(c.graph, t, attachedDestructor) != nil and
sfOverridden in getAttachedOp(c.graph, t, attachedDestructor).flags)):
result = ensureDestruction(result, n, c, s)
of nkCallKinds:
if n[0].kind == nkSym and n[0].sym.magic == mEnsureMove:

View File

@@ -162,8 +162,7 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool)
if c.filterDiscriminator != nil: return
let f = n.sym
let b = if c.kind == attachedTrace: y else: y.dotField(f)
if (sfCursor in f.flags and f.typ.skipTypes(abstractInst).kind in {tyRef, tyProc} and
c.g.config.selectedGC in {gcArc, gcAtomicArc, gcOrc, gcHooks}) or
if (sfCursor in f.flags and c.g.config.selectedGC in {gcArc, gcAtomicArc, gcOrc, gcHooks}) or
enforceDefaultOp:
defaultOp(c, f.typ, body, x.dotField(f), b)
else:

View File

@@ -237,6 +237,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

@@ -151,7 +151,7 @@ proc commandCompileToC(graph: ModuleGraph) =
extccomp.callCCompiler(conf)
# for now we do not support writing out a .json file with the build instructions when HCR is on
if not conf.hcrOn:
extccomp.writeJsonBuildInstructions(conf)
extccomp.writeJsonBuildInstructions(conf, graph.cachedFiles)
if optGenScript in graph.config.globalOptions:
writeDepsFile(graph)
if optGenCDeps in graph.config.globalOptions:

View File

@@ -11,7 +11,7 @@
## represents a complete Nim project. Single modules can either be kept in RAM
## or stored in a rod-file.
import intsets, tables, hashes
import std/[intsets, tables, hashes, strtabs]
import ../dist/checksums/src/checksums/md5
import ast, astalgo, options, lineinfos,idents, btrees, ropes, msgs, pathutils, packages
import ic / [packed_ast, ic]
@@ -57,6 +57,7 @@ type
SymInfoPair* = object
sym*: PSym
info*: TLineInfo
isDecl*: bool
PipelinePass* = enum
NonePass
@@ -128,6 +129,8 @@ type
idgen*: IdGenerator
operators*: Operators
cachedFiles*: StringTableRef
TPassContext* = object of RootObj # the pass's context
idgen*: IdGenerator
PPassContext* = ref TPassContext
@@ -479,6 +482,7 @@ proc initModuleGraphFields(result: ModuleGraph) =
result.symBodyHashes = initTable[int, SigHash]()
result.operators = initOperators(result)
result.emittedTypeInfo = initTable[string, FileIndex]()
result.cachedFiles = newStringTable()
proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
result = ModuleGraph()

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

@@ -14,6 +14,9 @@ import
idents, lexer, syntaxes, modulegraphs,
lineinfos, pathutils
import ../dist/checksums/src/checksums/sha1
import std/strtabs
proc resetSystemArtifacts*(g: ModuleGraph) =
magicsys.resetSysTypes(g)
@@ -42,6 +45,8 @@ proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PNode =
result = syntaxes.parseFile(fileIdx, graph.cache, graph.config)
graph.addDep(s, fileIdx)
graph.addIncludeDep(s.position.FileIndex, fileIdx)
let path = toFullPath(graph.config, fileIdx)
graph.cachedFiles[path] = $secureHashFile(path)
proc wantMainModule*(conf: ConfigRef) =
if conf.projectFull.isEmpty:

View File

@@ -429,7 +429,8 @@ 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)
@@ -437,7 +438,11 @@ proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string,
if conf.errorCounter >= conf.errorMax:
# only really quit when we're not in the new 'nim check --def' mode:
if conf.ideCmd == ideNone:
quit(conf, msg)
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)
elif eh == doRaise:

View File

@@ -195,7 +195,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!
dotOperators,
@@ -280,9 +280,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
@@ -417,6 +432,8 @@ type
expandNodeResult*: string
expandPosition*: TLineInfo
clientProcessId*: int
proc parseNimVersion*(a: string): NimVer =
# could be moved somewhere reusable
@@ -1057,6 +1074,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

@@ -1430,6 +1430,7 @@ proc parseTypeDesc(p: var Parser, fullExpr = false): PNode =
result = newNodeP(nkObjectTy, p)
getTok(p)
of tkConcept:
result = p.emptyNode
parMessage(p, "the 'concept' keyword is only valid in 'type' sections")
of tkVar: result = parseTypeDescKAux(p, nkVarTy, pmTypeDesc)
of tkOut: result = parseTypeDescKAux(p, nkOutTy, pmTypeDesc)

View File

@@ -5,10 +5,12 @@ import sem, cgen, modulegraphs, ast, llstream, parser, msgs,
import pipelineutils
import ../dist/checksums/src/checksums/sha1
when not defined(leanCompiler):
import jsgen, docgen2
import std/[syncio, objectdollar, assertions, tables, strutils]
import std/[syncio, objectdollar, assertions, tables, strutils, strtabs]
import renderer
import ic/replayer
@@ -225,7 +227,10 @@ proc compilePipelineModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymF
if result == nil:
var cachedModules: seq[FileIndex]
result = moduleFromRodFile(graph, fileIdx, cachedModules)
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
let path = toFullPath(graph.config, fileIdx)
let filename = AbsoluteFile path
if fileExists(filename): # it could be a stdinfile
graph.cachedFiles[path] = $secureHashFile(path)
if result == nil:
result = newModule(graph, fileIdx)
result.flags.incl flags

View File

@@ -14,7 +14,7 @@
{.used.}
import
lexer, options, idents, strutils, ast, msgs, lineinfos
lexer, options, idents, strutils, ast, msgs, lineinfos, wordrecg
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions, formatfloat]
@@ -848,7 +848,7 @@ proc gcase(g: var TSrcGen, n: PNode) =
gsub(g, n[^1], c)
proc genSymSuffix(result: var string, s: PSym) {.inline.} =
if sfGenSym in s.flags:
if sfGenSym in s.flags and s.name.id != ord(wUnderscore):
result.add '_'
result.addInt s.id
@@ -971,7 +971,9 @@ proc gident(g: var TSrcGen, n: PNode) =
s.addInt localId
if sfCursor in n.sym.flags:
s.add "_cursor"
elif n.kind == nkSym and (renderIds in g.flags or sfGenSym in n.sym.flags or n.sym.kind == skTemp):
elif n.kind == nkSym and (renderIds in g.flags or
(sfGenSym in n.sym.flags and n.sym.name.id != ord(wUnderscore)) or
n.sym.kind == skTemp):
s.add '_'
s.addInt n.sym.id
when defined(debugMagics):

View File

@@ -26,7 +26,10 @@ when not defined(leanCompiler):
import spawn
when defined(nimPreviewSlimSystem):
import std/formatfloat
import std/[
formatfloat,
assertions,
]
# implementation
@@ -206,12 +209,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
@@ -462,7 +511,13 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
# we now know the supplied arguments
var paramTypes = newIdTable()
for param, value in genericParamsInMacroCall(s, call):
idTablePut(paramTypes, param.typ, value.typ)
var givenType = value.typ
# the sym nodes used for the supplied generic arguments for
# templates and macros leave type nil so regular sem can handle it
# in this case, get the type directly from the sym
if givenType == nil and value.kind == nkSym and value.sym.typ != nil:
givenType = value.sym.typ
idTablePut(paramTypes, param.typ, givenType)
retType = generateTypeInstance(c, paramTypes,
macroResult.info, retType)

View File

@@ -236,44 +236,89 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
candidates.add("\n")
let nArg = if err.firstMismatch.arg < n.len: n[err.firstMismatch.arg] else: nil
let nameParam = if err.firstMismatch.formal != nil: err.firstMismatch.formal.name.s else: ""
if n.len > 1 and verboseTypeMismatch in c.config.legacyFeatures:
candidates.add(" first type mismatch at position: " & $err.firstMismatch.arg)
# candidates.add "\n reason: " & $err.firstMismatch.kind # for debugging
case err.firstMismatch.kind
of kUnknownNamedParam:
if nArg == nil:
candidates.add("\n unknown named parameter")
else:
candidates.add("\n unknown named parameter: " & $nArg[0])
of kAlreadyGiven: candidates.add("\n named param already provided: " & $nArg[0])
of kPositionalAlreadyGiven: candidates.add("\n positional param was already given as named param")
of kExtraArg: candidates.add("\n extra argument given")
of kMissingParam: candidates.add("\n missing parameter: " & nameParam)
of kTypeMismatch, kVarNeeded:
doAssert nArg != nil
let wanted = err.firstMismatch.formal.typ
doAssert err.firstMismatch.formal != nil
candidates.add("\n required type for " & nameParam & ": ")
candidates.addTypeDeclVerboseMaybe(c.config, wanted)
candidates.add "\n but expression '"
if err.firstMismatch.kind == kVarNeeded:
if n.len > 1:
if verboseTypeMismatch notin c.config.legacyFeatures:
case err.firstMismatch.kind
of kUnknownNamedParam:
if nArg == nil:
candidates.add(" unknown named parameter")
else:
candidates.add(" unknown named parameter: " & $nArg[0])
candidates.add "\n"
of kAlreadyGiven:
candidates.add(" named param already provided: " & $nArg[0])
candidates.add "\n"
of kPositionalAlreadyGiven:
candidates.add(" positional param was already given as named param")
candidates.add "\n"
of kExtraArg:
candidates.add(" extra argument given")
candidates.add "\n"
of kMissingParam:
candidates.add(" missing parameter: " & nameParam)
candidates.add "\n"
of kVarNeeded:
doAssert nArg != nil
doAssert err.firstMismatch.formal != nil
candidates.add " expression '"
candidates.add renderNotLValue(nArg)
candidates.add "' is immutable, not 'var'"
else:
candidates.add renderTree(nArg)
candidates.add "' is of type: "
let got = nArg.typ
candidates.addTypeDeclVerboseMaybe(c.config, got)
candidates.add "\n"
of kTypeMismatch:
doAssert nArg != nil
let wanted = err.firstMismatch.formal.typ
doAssert err.firstMismatch.formal != nil
doAssert wanted != nil
if got != nil:
if got.kind == tyProc and wanted.kind == tyProc:
# These are proc mismatches so,
# add the extra explict detail of the mismatch
candidates.addPragmaAndCallConvMismatch(wanted, got, c.config)
let got = nArg.typ
if got != nil and got.kind == tyProc and wanted.kind == tyProc:
# These are proc mismatches so,
# add the extra explict detail of the mismatch
candidates.add " expression '"
candidates.add renderTree(nArg)
candidates.add "' is of type: "
candidates.addTypeDeclVerboseMaybe(c.config, got)
candidates.addPragmaAndCallConvMismatch(wanted, got, c.config)
effectProblem(wanted, got, candidates, c)
candidates.add "\n"
of kUnknown: discard "do not break 'nim check'"
else:
candidates.add(" first type mismatch at position: " & $err.firstMismatch.arg)
# candidates.add "\n reason: " & $err.firstMismatch.kind # for debugging
case err.firstMismatch.kind
of kUnknownNamedParam:
if nArg == nil:
candidates.add("\n unknown named parameter")
else:
candidates.add("\n unknown named parameter: " & $nArg[0])
of kAlreadyGiven: candidates.add("\n named param already provided: " & $nArg[0])
of kPositionalAlreadyGiven: candidates.add("\n positional param was already given as named param")
of kExtraArg: candidates.add("\n extra argument given")
of kMissingParam: candidates.add("\n missing parameter: " & nameParam)
of kTypeMismatch, kVarNeeded:
doAssert nArg != nil
let wanted = err.firstMismatch.formal.typ
doAssert err.firstMismatch.formal != nil
candidates.add("\n required type for " & nameParam & ": ")
candidates.addTypeDeclVerboseMaybe(c.config, wanted)
candidates.add "\n but expression '"
if err.firstMismatch.kind == kVarNeeded:
candidates.add renderNotLValue(nArg)
candidates.add "' is immutable, not 'var'"
else:
candidates.add renderTree(nArg)
candidates.add "' is of type: "
let got = nArg.typ
candidates.addTypeDeclVerboseMaybe(c.config, got)
doAssert wanted != nil
if got != nil:
if got.kind == tyProc and wanted.kind == tyProc:
# These are proc mismatches so,
# add the extra explict detail of the mismatch
candidates.addPragmaAndCallConvMismatch(wanted, got, c.config)
effectProblem(wanted, got, candidates, c)
of kUnknown: discard "do not break 'nim check'"
candidates.add "\n"
of kUnknown: discard "do not break 'nim check'"
candidates.add "\n"
if err.firstMismatch.arg == 1 and nArg.kind == nkTupleConstr and
n.kind == nkCommand:
maybeWrongSpace = true
@@ -595,7 +640,12 @@ proc semResolvedCall(c: PContext, x: TCandidate,
else:
x.call.add c.graph.emptyNode
of skType:
x.call.add newSymNode(s, n.info)
var tn = newSymNode(s, n.info)
# this node will be used in template substitution,
# pretend this is an untyped node and let regular sem handle the type
# to prevent problems where a generic parameter is treated as a value
tn.typ = nil
x.call.add tn
else:
internalAssert c.config, false
@@ -665,14 +715,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

@@ -996,10 +996,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)
@@ -1106,7 +1102,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)
@@ -1845,7 +1840,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
@@ -2244,7 +2239,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
for i in 1..<ids.len:
let exp = semExprWithType(c, quotes[i+1], {})
let typ = exp.typ
if tfTriggersCompileTime notin typ.flags and exp.kind == nkSym and exp.sym.kind notin routineKinds + {skType}:
if tfTriggersCompileTime notin typ.flags and typ.kind != tyStatic and exp.kind == nkSym and exp.sym.kind notin routineKinds + {skType}:
dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[i], newNodeIT(nkType, n.info, typ), c.graph.emptyNode)
else:
dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[i], getSysSym(c.graph, n.info, "typed").newSymNode, c.graph.emptyNode)

View File

@@ -167,6 +167,17 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
elif s.isMixedIn:
result = newDot(result, symChoice(c, n, s, scForceOpen))
else:
if s.kind == skType and candidates.len > 1:
var ambig = false
let s2 = searchInScopes(c, ident, ambig)
if ambig:
# this is a type conversion like a.T where T is ambiguous with
# other types or routines
# in regular code, this never considers a type conversion and
# skips to routine overloading
# so symchoices are used which behave similarly with type symbols
result = newDot(result, symChoice(c, n, s, scForceOpen))
return
let syms = semGenericStmtSymbol(c, n, s, ctx, flags, fromDotExpr=true)
result = newDot(result, syms)

View File

@@ -66,7 +66,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``.
@@ -668,7 +668,8 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
result.typ = expectedType # type inference for empty sequence # bug #21377
of mEnsureMove:
result = n
if isAssignable(c, n[1]) notin {arLValue, arLocalLValue}:
localError(c.config, n.info, "'" & $n[1] & "'" & " is not a mutable location; it cannot be moved")
if n[1].kind in {nkStmtListExpr, nkBlockExpr,
nkIfExpr, nkCaseStmt, nkTryStmt}:
localError(c.config, n.info, "Nested expressions cannot be moved: '" & $n[1] & "'")
else:
result = n

View File

@@ -656,9 +656,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
addToVarSection(c, result, b)
continue
var hasUserSpecifiedType = false
var typ: PType = nil
if a[^2].kind != nkEmpty:
typ = semTypeNode(c, a[^2], nil)
hasUserSpecifiedType = true
var typFlags: TTypeAllowedFlags
@@ -730,6 +732,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:
@@ -803,9 +807,11 @@ proc semConst(c: PContext, n: PNode): PNode =
addToVarSection(c, result, b)
continue
var hasUserSpecifiedType = false
var typ: PType = nil
if a[^2].kind != nkEmpty:
typ = semTypeNode(c, a[^2], nil)
hasUserSpecifiedType = true
var typFlags: TTypeAllowedFlags
@@ -846,6 +852,8 @@ proc semConst(c: PContext, n: PNode): PNode =
else:
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)
@@ -2613,9 +2621,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

@@ -566,6 +566,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:
@@ -577,7 +578,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])
@@ -673,6 +676,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
if param.name.id != ord(wUnderscore):

View File

@@ -141,6 +141,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:
addInterfaceOverloadableSymAt(c, c.currentScope, e)
@@ -2113,6 +2114,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
else:
let symKind = if n.kind == nkIteratorTy: skIterator else: skProc
result = semProcTypeWithScope(c, n, prev, symKind)
if result == nil:
localError(c.config, n.info, "type expected, but got: " & renderTree(n))
result = newOrPrevType(tyError, prev, c)
if n.kind == nkIteratorTy and result.kind == tyProc:
result.flags.incl(tfIterator)
of nkEnumTy: result = semEnum(c, n, prev)

View File

@@ -46,7 +46,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
@@ -204,7 +205,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

@@ -1207,7 +1207,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])
@@ -1536,6 +1536,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

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 == 0 or suggest.version == 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 == 0 or suggest.version == 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):
@@ -507,7 +553,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
@@ -522,7 +568,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:
@@ -711,7 +757,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

@@ -11,7 +11,7 @@
import
intsets, ast, astalgo, trees, msgs, strutils, platform, renderer, options,
lineinfos, int128, modulegraphs, astmsgs
lineinfos, int128, modulegraphs, astmsgs, wordrecg
when defined(nimPreviewSlimSystem):
import std/[assertions, formatfloat]
@@ -28,6 +28,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,
@@ -508,7 +510,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
@@ -542,7 +544,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}:
@@ -558,7 +563,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:
@@ -577,8 +582,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:
@@ -751,12 +759,35 @@ 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")
if tfThread in t.flags:
addSep(prag)
prag.add("gcsafe")
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])
@@ -807,11 +838,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 =
@@ -895,11 +926,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 =

View File

@@ -811,6 +811,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
# a[b] = c
decodeBC(rkNode)
let idx = regs[rb].intVal.int
assert regs[ra].kind == rkNode
let arr = regs[ra].node
case arr.kind
of nkTupleConstr: # refer to `opcSlice`
@@ -824,7 +825,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of nkStrKinds:
src.strVal[int(realIndex)] = char(regs[rc].intVal)
of nkBracket:
src[int(realIndex)] = regs[rc].node
if regs[rc].kind == rkInt:
src[int(realIndex)] = newIntNode(nkIntLit, regs[rc].intVal)
else:
assert regs[rc].kind == rkNode
src[int(realIndex)] = regs[rc].node
else:
stackTrace(c, tos, pc, "opcWrArr internal error")
else:
@@ -1015,7 +1020,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
@@ -1213,6 +1221,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)
@@ -1496,7 +1510,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

@@ -406,13 +406,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)
@@ -506,17 +512,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)
@@ -532,7 +546,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)
@@ -550,7 +567,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))
@@ -882,6 +903,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)
@@ -898,8 +921,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:
@@ -908,8 +934,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:
@@ -1151,7 +1180,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)
@@ -1525,6 +1555,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:
@@ -1864,10 +1895,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:
@@ -2079,8 +2110,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.skipTypes({tyTypeDesc}), 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:

View File

@@ -237,10 +237,10 @@ doc.file = """<?xml version="1.0" encoding="utf-8" ?>
<link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4QQQEwksSS9ZWwAAAk1JREFUWMPtll2ITVEUx39nn/O7Y5qR8f05wtCUUr6ZIS++8pEnkZInPImneaCQ5METNdOkeFBKUhMPRIkHKfEuUZSUlGlKPN2TrgfncpvmnntnmlEyq1Z7t89/rf9a6+y99oZxGZf/XeIq61EdtgKXgdXA0xrYAvBjOIF1AI9zvjcC74BSpndrJPkBWDScTF8Aa4E3wDlgHbASaANmVqlcCnwHvgDvgVfAJ+AikAAvgfVZwLnSVZHZaOuKoQi3ZOMi4NkYkpe1p4J7A8BpYAD49hfIy/oqG0+hLomiKP2L5L+1ubn5115S+3OAn4EnwBlgMzCjyt6ZAnQCJ4A7wOs88iRJHvw50HoujuPBoCKwHWiosy8MdfZnAdcHk8dxXFJ3VQbQlCTJvRBCGdRbD4M6uc5glpY3eAihpN5S5w12diSEcCCEcKUO4ljdr15T76ur1FDDLIQQ3qv71EdDOe3Kxj3leRXyk+pxdWnFWod6Wt2bY3de3aSuUHcPBVimHs7mK9WrmeOF6lR1o9qnzskh2ar2qm1qizpfXaPeVGdlmGN5pb09qMxz1Xb1kLqgzn1RyH7JUXW52lr5e/Kqi9qpto7V1atuUzfnARrV7jEib1T76gG2qxdGmXyiekkt1GswPTtek0aBfJp6YySGBfWg2tPQ0FAYgf1stUfdmdcjarbYJEniKIq6gY/Aw+zWHAC+p2labGpqiorFYgGYCEzN7oQdQClN07O1/EfDyGgC0ALMBdYAi4FyK+4H3gLPsxfR1zRNi+NP7nH5J+QntnXe5B5mpfQAAAAASUVORK5CYII=">
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="$nimdoccss">
<link rel="stylesheet" type="text/css" href="${nimdoccss}?v=$nimVersion">
<!-- JS -->
<script type="text/javascript" src="$dochackjs"></script>
<script type="text/javascript" src="${dochackjs}?v=$nimVersion"></script>
</head>
<body>
<div class="document" id="documentId">

View File

@@ -217,9 +217,11 @@ type
## code.
proc destroyRegex(pattern: Regex) =
`=destroy`(pattern.pattern)
pcre.free_substring(cast[cstring](pattern.pcreObj))
if pattern.pcreExtra != nil:
pcre.free_study(pattern.pcreExtra)
`=destroy`(pattern.captureNameToId)
proc getinfo[T](pattern: Regex, opt: cint): T =
let retcode = pcre.fullinfo(pattern.pcreObj, pattern.pcreExtra, opt, addr result)

View File

@@ -465,6 +465,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

@@ -606,10 +606,10 @@ when not defined(lwip):
when defined(zephyr):
type
Tnfds* = distinct cint
Tnfds* = distinct culong
else:
type
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable

View File

@@ -482,6 +482,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

@@ -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
@@ -134,14 +130,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: byte|char](s: openArray[T], safe = false): string =
## Encodes `s` into base64 representation.

View File

@@ -165,28 +165,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 {.cursor.} = L.head
while it != nil:
@@ -993,3 +971,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

@@ -200,8 +200,8 @@ const
colGoldenRod* = Color(0xDAA520)
colGray* = Color(0x808080)
colGreen* = Color(0x008000)
colGrey* = Color(0x808080)
colGreenYellow* = Color(0xADFF2F)
colGrey* = Color(0x808080)
colHoneyDew* = Color(0xF0FFF0)
colHotPink* = Color(0xFF69B4)
colIndianRed* = Color(0xCD5C5C)
@@ -350,8 +350,8 @@ const
"goldenrod": colGoldenRod,
"gray": colGray,
"green": colGreen,
"grey": colGrey,
"greenyellow": colGreenYellow,
"grey": colGrey,
"honeydew": colHoneyDew,
"hotpink": colHotPink,
"indianred": colIndianRed,

View File

@@ -7,6 +7,8 @@
# distribution, for details about the copyright.
#
{.deprecated: "use the nimble packages `malebolgia`, `taskpools` or `weave` instead".}
## Implements Nim's `parallel & spawn statements <manual_experimental.html#parallel-amp-spawn>`_.
##
## Unstable API.

View File

@@ -319,16 +319,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(addr k1, addr x[i], 4)
else:
impl()
inc i, stepSize
k1 = imul(k1, c1)

View File

@@ -387,21 +387,37 @@ when not useNimNetLite:
proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
## This function will lookup the hostname of an IP Address.
var myaddr: InAddr
myaddr.s_addr = inet_addr(ip)
var
addrInfo = getAddrInfo(ip, Port(0), AF_UNSPEC)
myAddr: pointer
addrLen = 0
family = 0
defer: freeAddrInfo(addrInfo)
if addrInfo.ai_addr.sa_family.cint == nativeAfInet:
family = nativeAfInet
myAddr = addr cast[ptr Sockaddr_in](addrInfo.ai_addr).sin_addr
addrLen = 4
elif addrInfo.ai_addr.sa_family.cint == nativeAfInet6:
family = nativeAfInet6
myAddr = addr cast[ptr Sockaddr_in6](addrInfo.ai_addr).sin6_addr
addrLen = 16
else:
raise newException(IOError, "Unknown socket family in `getHostByAddr()`")
when useWinVersion:
var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
cint(AF_INET))
var s = winlean.gethostbyaddr(cast[ptr InAddr](myAddr), addrLen.cuint,
cint(family))
if s == nil: raiseOSError(osLastError())
else:
var s =
when defined(android4):
posix.gethostbyaddr(cast[cstring](addr(myaddr)), sizeof(myaddr).cint,
cint(posix.AF_INET))
posix.gethostbyaddr(cast[cstring](myAddr), addrLen.cint,
cint(family))
else:
posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).SockLen,
cint(posix.AF_INET))
posix.gethostbyaddr(myAddr, addrLen.SockLen,
cint(family))
if s == nil:
raiseOSError(osLastError(), $hstrerror(h_errno))
@@ -424,7 +440,20 @@ when not useNimNetLite:
result.addrList.add($inet_ntoa(inaddrPtr[]))
inc(i)
else:
result.addrList = cstringArrayToSeq(s.h_addr_list)
let strAddrLen = when not useWinVersion: posix.INET6_ADDRSTRLEN.int
else: 46
var i = 0
while not isNil(s.h_addr_list[i]):
var ipStr = newString(strAddrLen)
if inet_ntop(nativeAfInet6, cast[pointer](s.h_addr_list[i]),
cstring(ipStr), len(ipStr).int32) == nil:
raiseOSError(osLastError())
when not useWinVersion:
if posix.IN6_IS_ADDR_V4MAPPED(cast[ptr In6Addr](s.h_addr_list[i])) != 0:
ipStr.setSlice("::ffff:".len..<strAddrLen)
setLen(ipStr, len(cstring(ipStr)))
result.addrList.add(ipStr)
inc(i)
result.length = int(s.h_length)
proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} =

View File

@@ -638,14 +638,14 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noW
# /proc/<pid>/path/a.out (complete pathname)
when defined(windows):
var bufsize = int32(MAX_PATH)
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

@@ -562,7 +562,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 {.gcsafe.} =
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

@@ -457,10 +457,6 @@ when not defined(js) and not defined(nimSeqsV2):
data: UncheckedArray[char]
NimString = ptr NimStringDesc
when notJSnotNims and not defined(nimSeqsV2):
template space(s: PGenericSeq): int {.dirty.} =
s.reserved and not (seqShallowFlag or strlitFlag)
when notJSnotNims:
include "system/hti"
@@ -1068,6 +1064,10 @@ const
hasThreadSupport = compileOption("threads") and not defined(nimscript)
hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own
when notJSnotNims and not defined(nimSeqsV2):
template space(s: PGenericSeq): int =
s.reserved and not (seqShallowFlag or strlitFlag)
when hasThreadSupport and defined(tcc) and not compileOption("tlsEmulation"):
# tcc doesn't support TLS
{.error: "`--tlsEmulation:on` must be used when using threads with tcc backend".}

View File

@@ -1,16 +1,16 @@
const
NimMajor* {.intdefine.}: int = 1
NimMajor* {.intdefine.}: int = 2
## is the major number of Nim's version. Example:
## ```
## when (NimMajor, NimMinor, NimPatch) >= (1, 3, 1): discard
## ```
# see also std/private/since
NimMinor* {.intdefine.}: int = 9
NimMinor* {.intdefine.}: int = 0
## is the minor number of Nim's version.
## Odd for devel, even for releases.
NimPatch* {.intdefine.}: int = 5
NimPatch* {.intdefine.}: int = 4
## is the patch number of Nim's version.
## Odd for devel, even for releases.
@@ -144,16 +144,17 @@ template currentSourcePath*: string = instantiationInfo(-1, true).filename
## Returns the full file-system path of the current source.
##
## To get the directory containing the current source, use it with
## `os.parentDir() <os.html#parentDir%2Cstring>`_ as `currentSourcePath.parentDir()`.
## `ospaths2.parentDir() <ospaths2.html#parentDir%2Cstring>`_ as
## `currentSourcePath.parentDir()`.
##
## The path returned by this template is set at compile time.
##
## See the docstring of `macros.getProjectPath() <macros.html#getProjectPath>`_
## for an example to see the distinction between the `currentSourcePath`
## and `getProjectPath`.
## for an example to see the distinction between the `currentSourcePath()`
## and `getProjectPath()`.
##
## See also:
## * `getCurrentDir proc <os.html#getCurrentDir>`_
## * `ospaths2.getCurrentDir() proc <ospaths2.html#getCurrentDir>`_
proc slurp*(filename: string): string {.magic: "Slurp".}
## This is an alias for `staticRead <#staticRead,string>`_.

View File

@@ -278,7 +278,9 @@ proc toJSStr(s: string): cstring {.compilerproc.} =
proc mnewString(len: int): string {.asmNoStackFrame, compilerproc.} =
asm """
return new Array(`len`);
var result = new Array(`len`);
for (var i = 0; i < `len`; i++) {result[i] = 0;}
return result;
"""
proc SetCard(a: int): int {.compilerproc, asmNoStackFrame.} =

View File

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

@@ -140,8 +140,6 @@ proc newSeq[T](s: var seq[T], len: Natural) =
setLen(s, len)
template capacityImpl(sek: NimSeqV2): int =
if sek.p != nil: (xu.p.cap and not strlitFlag) else: 0
func capacity*[T](self: seq[T]): int {.inline.} =
## Returns the current capacity of the seq.
@@ -151,9 +149,8 @@ func capacity*[T](self: seq[T]): int {.inline.} =
lst.add "Nim"
assert lst.capacity == 42
{.cast(noSideEffect).}:
let sek = unsafeAddr self
result = capacityImpl(cast[ptr NimSeqV2](sek)[])
let sek = cast[ptr NimSeqV2[T]](unsafeAddr self)
result = if sek.p != nil: sek.p.cap and not strlitFlag else: 0
{.pop.} # See https://github.com/nim-lang/Nim/issues/21401

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 <= high(int16): 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, inl.} =
#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)
@@ -177,9 +202,6 @@ proc prepareMutation*(s: var string) {.inline.} =
nimPrepareStrMutationV2(cast[ptr NimStringV2](s)[])
template capacityImpl(str: NimStringV2): int =
if str.p != nil: str.p.cap else: 0
func capacity*(self: string): int {.inline.} =
## Returns the current capacity of the string.
# See https://github.com/nim-lang/RFCs/issues/460
@@ -188,6 +210,5 @@ func capacity*(self: string): int {.inline.} =
str.add "Nim"
assert str.capacity == 42
{.cast(noSideEffect).}:
let str = unsafeAddr self
result = capacityImpl(cast[ptr NimStringV2](str)[])
let str = cast[ptr NimStringV2](unsafeAddr self)
result = if str.p != nil: str.p.cap and not strlitFlag else: 0

View File

@@ -340,3 +340,25 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
result = s
zeroMem(dataPointer(result, elemAlign, elemSize, result.len), (newLen-%result.len) *% elemSize)
result.len = newLen
func capacity*(self: string): int {.inline.} =
## Returns the current capacity of the string.
# See https://github.com/nim-lang/RFCs/issues/460
runnableExamples:
var str = newStringOfCap(cap = 42)
str.add "Nim"
assert str.capacity == 42
let str = cast[NimString](self)
result = if str != nil: str.space else: 0
func capacity*[T](self: seq[T]): int {.inline.} =
## Returns the current capacity of the seq.
# See https://github.com/nim-lang/RFCs/issues/460
runnableExamples:
var lst = newSeqOfCap[string](cap = 42)
lst.add "Nim"
assert lst.capacity == 42
let sek = cast[PGenericSeq](self)
result = if sek != nil: sek.space else: 0

View File

@@ -24,11 +24,13 @@ proc testRst2Html(fixup = false) =
let sourceFile = expectedHtml.replace('\\', '/').replace("/expected/", "/source/").replace(".html", ".rst")
exec("$1 rst2html $2" % [nimExe, sourceFile])
let producedHtml = expectedHtml.replace('\\', '/').replace("/expected/", "/source/htmldocs/")
if readFile(expectedHtml) != readFile(producedHtml):
let versionCacheParam = "?v=" & $NimMajor & "." & $NimMinor & "." & $NimPatch
let producedFile = readFile(producedHtml).replace(versionCacheParam,"") #remove version cache param used for cache invalidation
if readFile(expectedHtml) != producedFile:
echo diffFiles(expectedHtml, producedHtml).output
inc failures
if fixup:
copyFile(producedHtml, expectedHtml)
writeFile(expectedHtml, producedFile)
else:
echo "SUCCESS: files identical: ", producedHtml
if failures == 0:

View File

@@ -59,16 +59,18 @@ proc testNimDoc(prjDir, docsDir: string; switches: NimSwitches; fixup = false) =
echo("$1 buildIndex $2" % [nimExe, nimBuildIndexSwitches])
for expected in walkDirRec(prjDir / "expected/", checkDir=true):
let versionCacheParam = "?v=" & $NimMajor & "." & $NimMinor & "." & $NimPatch
let produced = expected.replace('\\', '/').replace("/expected/", "/$1/" % [docsDir])
if not fileExists(produced):
echo "FAILURE: files not found: ", produced
inc failures
elif readFile(expected) != readFile(produced):
let producedFile = readFile(produced).replace(versionCacheParam,"") #remove version cache param used for cache invalidation
if readFile(expected) != producedFile:
echo "FAILURE: files differ: ", produced
echo diffFiles(expected, produced).output
inc failures
if fixup:
copyFile(produced, expected)
writeFile(expected, producedFile)
else:
echo "SUCCESS: files identical: ", produced

View File

@@ -12,6 +12,7 @@ import strformat
import algorithm
import tables
import times
import procmonitor
template tryImport(module) = import module
@@ -43,6 +44,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
@@ -55,12 +57,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
@@ -117,6 +125,10 @@ 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
]
proc parseQuoted(cmd: string; outp: var string; start: int): int =
var i = start
@@ -161,7 +173,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()
@@ -197,7 +209,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)
@@ -486,6 +498,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 = ""
@@ -550,7 +567,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
@@ -581,7 +598,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)
@@ -595,6 +612,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))
@@ -645,6 +665,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
@@ -659,6 +693,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)
@@ -756,6 +792,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
@@ -763,6 +811,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:
@@ -785,6 +841,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}
@@ -892,7 +965,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
@@ -901,10 +974,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:
@@ -950,6 +1023,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)
@@ -1048,6 +1124,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,12 @@
SomeNumber = concept
#[!]#
discard """
$nimsuggest --tester $file
>chk $1
chk;;skUnknown;;;;Hint;;???;;0;;-1;;">> (toplevel): import(dirty): tests/tconcept1.nim [Processing]";;0
chk;;skUnknown;;;;Error;;$file;;1;;13;;"the \'concept\' keyword is only valid in \'type\' sections";;0
chk;;skUnknown;;;;Error;;$file;;1;;13;;"invalid indentation";;0
chk;;skUnknown;;;;Error;;$file;;1;;13;;"expression expected, but found \'keyword concept\'";;0
chk;;skUnknown;;;;Error;;$file;;1;;0;;"\'SomeNumber\' cannot be assigned to";;0
"""

View File

@@ -0,0 +1,15 @@
SomeNumber = concept a, type T
a.int is int
int.to(T) is type(a)
#[!]#
discard """
$nimsuggest --tester $file
>chk $1
chk;;skUnknown;;;;Hint;;???;;0;;-1;;">> (toplevel): import(dirty): tests/tconcept2.nim [Processing]";;0
chk;;skUnknown;;;;Error;;$file;;1;;2;;"invalid indentation";;0
chk;;skUnknown;;;;Error;;$file;;1;;15;;"the \'concept\' keyword is only valid in \'type\' sections";;0
chk;;skUnknown;;;;Error;;$file;;1;;15;;"invalid indentation";;0
chk;;skUnknown;;;;Error;;$file;;1;;15;;"expression expected, but found \'keyword concept\'";;0
chk;;skUnknown;;;;Error;;$file;;1;;2;;"\'SomeNumber\' cannot be assigned to";;0
"""

View File

@@ -1,9 +1,9 @@
discard """
$nimsuggest --tester $file
>def $1
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe.};;$file;;9;;5;;"Return hello";;100
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, raises: <inferred> [].};;$file;;9;;5;;"Return hello";;100
>def $1
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe.};;$file;;9;;5;;"Return hello";;100
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, 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.};;*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, 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.};;*fixtures/minclude_include.nim;;3;;5;;"";;100
def;;skProc;;minclude_import.create;;proc (greeting: string, subject: string): Greet{.noSideEffect, gcsafe, 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.};;$file;;2;;6;;"";;100;;Prefix
sug;;skMacro;;tsug_template.tmpb;;macro (){.noSideEffect, gcsafe, 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.};;$file;;9;;5;;"";;100
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe.};;$file;;12;;0;;"";;100
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, raises: <inferred> [].};;$file;;9;;5;;"";;100
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, raises: <inferred> [].};;$file;;12;;0;;"";;100
>use $2
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe.};;$file;;9;;5;;"";;100
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe.};;$file;;12;;0;;"";;100
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, raises: <inferred> [].};;$file;;9;;5;;"";;100
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, 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.} $file 7 5 "" 100
def skProc tv3.test proc (f: Foo){.gcsafe, 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.} $file 1 5 "" 100
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 3 5 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 5 8 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 1 5 "" 100
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 3 5 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 5 8 "" 100
>use $2
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 1 5 "" 100
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 3 5 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 5 8 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 1 5 "" 100
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 3 5 "" 100
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 5 8 "" 100
>declaration $1
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 3 5 "" 100
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 3 5 "" 100
>declaration $2
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 1 5 "" 100
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 1 5 "" 100
>declaration $3
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 1 5 "" 100
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, 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.} $file 4 5 "" 100
def skProc tv3_globalSymbols.tokenA proc (): int{.noSideEffect, gcsafe.} $file 3 5 "" 100
def skProc tv3_globalSymbols.Btoken proc (): int{.noSideEffect, gcsafe.} $file 2 5 "" 100
def skProc tv3_globalSymbols.BBtokenA proc (): int{.noSideEffect, gcsafe.} $file 5 5 "" 100
def skProc tv3_globalSymbols.token proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 4 5 "" 100
def skProc tv3_globalSymbols.tokenA proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 3 5 "" 100
def skProc tv3_globalSymbols.Btoken proc (): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 2 5 "" 100
def skProc tv3_globalSymbols.BBtokenA proc (): int{.noSideEffect, gcsafe, 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.} $file 10 6 "" 100 10 40
outline skMacro tv3_outline.m macro (arg: untyped): untyped{.noSideEffect, gcsafe, 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.} $file 12 5 "" 100 12 24
outline skConverter tv3_outline.c converter (s: string): int{.noSideEffect, gcsafe.} $file 14 10 "" 100 14 37
outline skFunc tv3_outline.f proc (){.noSideEffect, gcsafe.} $file 16 5 "" 100 16 24
outline skProc tv3_outline.p proc (){.noSideEffect, gcsafe, raises: <inferred> [].} $file 12 5 "" 100 12 24
outline skConverter tv3_outline.c converter (s: string): int{.noSideEffect, gcsafe, raises: <inferred> [].} $file 14 10 "" 100 14 37
outline skFunc tv3_outline.f proc (){.noSideEffect, gcsafe, 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.} $file 22 5 "" 100 23 24
outline skProc tv3_outline.outer.inner proc (){.noSideEffect, gcsafe.} $file 23 7 "" 100 23 24
outline skProc tv3_outline.procWithLocal proc (){.noSideEffect, gcsafe.} $file 25 5 "" 100 26 16
outline skProc tv3_outline.outer proc (){.noSideEffect, gcsafe, raises: <inferred> [].} $file 22 5 "" 100 23 24
outline skProc tv3_outline.outer.inner proc (){.noSideEffect, gcsafe, raises: <inferred> [].} $file 23 7 "" 100 23 24
outline skProc tv3_outline.procWithLocal proc (){.noSideEffect, gcsafe, 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

@@ -46,7 +46,7 @@ pkg "BipBuffer"
pkg "blscurve", allowFailure = true
pkg "bncurve"
pkg "brainfuck", "nim c -d:release -r tests/compile.nim"
pkg "bump", "nim c --gc:arc --path:. -r tests/tbump.nim", "https://github.com/disruptek/bump", allowFailure = true
pkg "bump", "nim c --mm:arc --path:. -r tests/tbump.nim", "https://github.com/disruptek/bump", allowFailure = true
pkg "c2nim", "nim c testsuite/tester.nim"
pkg "cascade"
pkg "cello", url = "https://github.com/nim-lang/cello", useHead = true
@@ -55,7 +55,7 @@ pkg "chroma"
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"
pkg "combparser", "nimble test --mm:orc"
pkg "compactdict"
pkg "comprehension", "nimble test", "https://github.com/alehander92/comprehension"
pkg "cowstrings"
@@ -75,7 +75,7 @@ pkg "glob"
pkg "ggplotnim", "nim c -d:noCairo -r tests/tests.nim"
pkg "gittyup", "nimble test", "https://github.com/disruptek/gittyup", allowFailure = true
pkg "gnuplot", "nim c gnuplot.nim"
# pkg "gram", "nim c -r --gc:arc --define:danger tests/test.nim", "https://github.com/disruptek/gram"
# pkg "gram", "nim c -r --mm:arc --define:danger tests/test.nim", "https://github.com/disruptek/gram"
# pending https://github.com/nim-lang/Nim/issues/16509
pkg "hts", "nim c -o:htss src/hts.nim"
pkg "httpauth"
@@ -91,13 +91,12 @@ pkg "lockfreequeues"
pkg "macroutils"
pkg "manu"
pkg "markdown"
pkg "measuremancer", "nimble install -y unchained@#HEAD; nimble -y test"
pkg "measuremancer", "nimble testDeps; nimble -y test"
# when unchained is version 0.3.7 or higher, use `nimble testDeps;`
pkg "memo"
pkg "msgpack4nim", "nim c -r tests/test_spec.nim"
pkg "nake", "nim c nakefile.nim"
pkg "neo", "nim c -d:blas=openblas --mm:refc tests/all.nim", "https://github.com/metagn/neo"
# remove custom url when https://github.com/andreaferretti/neo/pull/53 is merged
pkg "neo", "nim c -d:blas=openblas --mm:refc tests/all.nim"
pkg "nesm", "nimble tests", "https://github.com/nim-lang/NESM", useHead = true
pkg "netty"
pkg "nico", allowFailure = true
@@ -121,7 +120,7 @@ pkg "nimsl"
pkg "nimsvg"
pkg "nimterop", "nimble minitest", url = "https://github.com/nim-lang/nimterop"
pkg "nimwc", "nim c nimwc.nim", allowFailure = true
pkg "nimx", "nim c --threads:on test/main.nim", allowFailure = true
pkg "nimx", "nim c test/main.nim", allowFailure = true
pkg "nitter", "nim c src/nitter.nim", "https://github.com/zedeus/nitter"
pkg "norm", "testament r tests/common/tmodel.nim"
pkg "npeg", "nimble testarc"
@@ -145,13 +144,13 @@ pkg "RollingHash", "nim c -r tests/test_cyclichash.nim"
pkg "rosencrantz", "nim c -o:rsncntz -r rosencrantz.nim"
pkg "sdl1", "nim c -r src/sdl.nim"
pkg "sdl2_nim", "nim c -r sdl2/sdl.nim"
pkg "sigv4", "nim c --gc:arc -r sigv4.nim", "https://github.com/disruptek/sigv4"
pkg "sigv4", "nim c --mm:arc -r sigv4.nim", "https://github.com/disruptek/sigv4"
pkg "sim"
pkg "smtp", "nimble compileExample"
pkg "snip", "nimble test", "https://github.com/genotrance/snip"
pkg "ssostrings"
pkg "stew"
pkg "stint", "nim r stint.nim"
pkg "stint", "nim c stint.nim"
pkg "strslice"
pkg "strunicode", "nim c -r --mm:refc src/strunicode.nim"
pkg "supersnappy"
@@ -168,12 +167,13 @@ pkg "timezones"
pkg "tiny_sqlite"
pkg "unicodedb", "nim c -d:release -r tests/tests.nim"
pkg "unicodeplus", "nim c -d:release -r tests/tests.nim"
pkg "union", "nim c -r tests/treadme.nim", url = "https://github.com/alaviss/union"
pkg "unpack"
pkg "weave", "nimble test_gc_arc", useHead = true
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"
pkg "zero_functional", "nim c -r 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()()

View File

@@ -1,16 +1,19 @@
discard """
cmd: '''nim c --gc:arc $file'''
output: '''2
2'''
cmd: '''nim c --mm:arc $file'''
output: '''
2
2
destroyed
'''
"""
type
ObjWithDestructor = object
a: int
proc `=destroy`(self: var ObjWithDestructor) =
proc `=destroy`(self: ObjWithDestructor) =
echo "destroyed"
proc `=`(self: var ObjWithDestructor, other: ObjWithDestructor) =
proc `=copy`(self: var ObjWithDestructor, other: ObjWithDestructor) =
echo "copied"
proc test(a: range[0..1], arg: ObjWithDestructor) =
@@ -38,4 +41,4 @@ proc test(a: range[0..1], arg: ObjWithDestructor) =
if iteration == 2:
break
test(1, ObjWithDestructor())
test(1, ObjWithDestructor())

View File

@@ -1,13 +1,16 @@
discard """
cmd: '''nim c --gc:arc $file'''
output: '''2
2'''
cmd: '''nim c --mm:arc $file'''
output: '''
2
2
destroyed
'''
"""
type
ObjWithDestructor = object
a: int
proc `=destroy`(self: var ObjWithDestructor) =
proc `=destroy`(self: ObjWithDestructor) =
echo "destroyed"
proc `=copy`(self: var ObjWithDestructor, other: ObjWithDestructor) =

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

@@ -0,0 +1,20 @@
discard """
action: "run"
output: '''
1
1
1
'''
matrix: "--mm:refc"
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

@@ -123,3 +123,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

@@ -0,0 +1,192 @@
discard """
targets: "c cpp"
matrix: "--debugger:native"
ccodecheck: "'_ZN14titaniummangle8testFuncE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE6stringN14titaniummangle3FooE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3int7varargsI6stringE'"
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle3BooE'"
ccodecheck: "'_ZN8testFunc8testFuncE8typeDescIN14titaniummangle17EnumAnotherSampleEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrI14uncheckedArrayI3intEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3setIN14titaniummangle10EnumSampleEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE4procI6string6stringE'"
ccodecheck: "'_ZN8testFunc8testFuncE3intN10Comparable10ComparableE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3int3int'"
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle10EnumSampleE'"
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle17EnumAnotherSampleE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3int3int'"
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle10EnumSampleE'"
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle17EnumAnotherSampleE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE5tupleI3int3intE7cstring'"
ccodecheck: "'_ZN14titaniummangle8testFuncE5tupleI5float5floatE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrI3intE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrIN14titaniummangle3FooEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrI3ptrI3intEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3refIN14titaniummangle3FooEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3varIN14titaniummangle3FooEE5int325int323refIN14titaniummangle3FooEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3varI3intE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE9openArrayI6stringE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE5arrayI7range013intE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE9ContainerI3intE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE10Container2I5int325int32E'"
ccodecheck: "'_ZN14titaniummangle8testFuncE9ContainerI10Container2I5int325int32EE'"
"""
#When debugging this notice that if one check fails, it can be due to any of the above.
type
Comparable = concept x, y
(x < y) is bool
type
Foo = object
a: int32
b: int32
FooTuple = tuple
a: int
b: int
Container[T] = object
data: T
Container2[T, T2] = object
data: T
data2: T2
Boo = distinct Foo
Coo = Foo
Doo = Boo | Foo
TestProc = proc(a:string): string
type EnumSample = enum
a, b, c
type EnumAnotherSample = enum
a, b, c
proc testFunc(a: set[EnumSample]) =
echo $a
proc testFunc(a: typedesc) =
echo $a
proc testFunc(a: ptr Foo) =
echo repr a
proc testFunc(s: string, a: Coo) =
echo repr a
proc testFunc(s: int, a: Comparable) =
echo repr a
proc testFunc(a: TestProc) =
let b = ""
echo repr a("")
proc testFunc(a: ref Foo) =
echo repr a
proc testFunc(b: Boo) =
echo repr b
proc testFunc(a: ptr UncheckedArray[int]) =
echo repr a
proc testFunc(a: ptr int) =
echo repr a
proc testFunc(a: ptr ptr int) =
echo repr a
proc testFunc(e: FooTuple, str: cstring) =
echo e
proc testFunc(e: (float, float)) =
echo e
proc testFunc(e: EnumSample) =
echo e
proc testFunc(e: var int) =
echo e
proc testFunc(e: var Foo, a, b: int32, refFoo: ref Foo) =
echo e
proc testFunc(xs: Container[int]) =
let a = 2
echo xs
proc testFunc(xs: Container2[int32, int32]) =
let a = 2
echo xs
proc testFunc(xs: Container[Container2[int32, int32]]) =
let a = 2
echo xs
proc testFunc(xs: seq[int]) =
let a = 2
echo xs
proc testFunc(xs: openArray[string]) =
let a = 2
echo xs
proc testFunc(xs: array[2, int]) =
let a = 2
echo xs
proc testFunc(e: EnumAnotherSample) =
echo e
proc testFunc(a, b: int) =
echo "hola"
discard
proc testFunc(a: int, xs: varargs[string]) =
let a = 10
for x in xs:
echo x
proc testFunc() =
var a = 2
var aPtr = a.addr
var foo = Foo()
let refFoo : ref Foo = new(Foo)
let b = Foo().Boo()
let d: Doo = Foo()
testFunc("", Coo())
testFunc(1, )
testFunc(b)
testFunc(EnumAnotherSample)
var t = [1, 2]
let uArr = cast[ptr UncheckedArray[int]](t.addr)
testFunc(uArr)
testFunc({})
testFunc(proc(s:string): string = "test")
testFunc(20, a.int32)
testFunc(20, 2)
testFunc(EnumSample.c)
testFunc(EnumAnotherSample.c)
testFunc((2, 1), "adios")
testFunc((22.1, 1.2))
testFunc(a.addr)
testFunc(foo.addr)
testFunc(aPtr.addr)
testFunc(refFoo)
testFunc(foo, 2, 1, refFoo)
testFunc(a)
testFunc(@[2, 1, 2])
testFunc(@["hola"])
testFunc(2, "hola", "adios")
let arr: array[2, int] = [2, 1]
testFunc(arr)
testFunc(Container[int](data: 10))
let c2 = Container2[int32, int32](data: 10, data2: 20)
testFunc(c2)
testFunc(Container[Container2[int32, int32]](data: c2))
testFunc()

View File

@@ -223,3 +223,20 @@ for i in 0..100:
var test = newSeqOfCap[uint32](1)
test.setLen(1)
doAssert test[0] == 0, $(test[0], i)
# bug #22560
doAssert len(newSeqOfCap[int](42)) == 0
block: # bug #17197
type Matrix = seq[seq[int]]
proc needlemanWunsch(sequence1: string, sequence2: string, gap_penal: int8, match: int8, indel_penal: int8): bool =
let seq2_len = sequence2.len
var grid: Matrix
for i in sequence1:
grid.add(newSeqOfCap[seq[int]](seq2_len))
result = true
doAssert needlemanWunsch("ABC", "DEFG", 1, 2, 3)

View File

@@ -2,8 +2,9 @@ discard """
cmd: "nim check --warningAsError:UnreachableCode $file"
action: "reject"
nimout: '''
tunreachable.nim(23, 3) Error: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode]
tunreachable.nim(30, 3) Error: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode]
tunreachable.nim(24, 3) Error: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode]
tunreachable.nim(31, 3) Error: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode]
tunreachable.nim(40, 3) Error: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode]
'''
"""
@@ -30,3 +31,12 @@ proc main2() =
echo "after"
main2()
proc main3() =
if true:
return
else:
return
echo "after"
main3()

View File

@@ -39,7 +39,7 @@ proc foo(x: int): string {.nimcall, raises: [ValueError].} =
var p: MyProcType = foo #[tt.Error
^
type mismatch: got <proc (x: int): string{.nimcall, noSideEffect, gcsafe.}> but expected 'MyProcType = proc (x: int): string{.closure.}'
type mismatch: got <proc (x: int): string{.nimcall, raises: [ValueError], noSideEffect, gcsafe.}> but expected 'MyProcType = proc (x: int): string{.closure.}'
Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
.raise effects differ
]#

View File

@@ -1,10 +1,12 @@
discard """
cmd: "nim check $file"
errormsg: "selector must be of an ordinal type, float or string"
errormsg: "illformed AST: case buf[pos]"
nimout: '''
t10735.nim(38, 5) Error: 'let' symbol requires an initialization
t10735.nim(39, 10) Error: undeclared identifier: 'pos'
t10735.nim(39, 9) Error: type mismatch: got <cstring, >
t10735.nim(43, 5) Error: 'let' symbol requires an initialization
t10735.nim(44, 10) Error: undeclared identifier: 'pos'
t10735.nim(44, 10) Error: expression 'pos' has no type (or is ambiguous)
t10735.nim(44, 10) Error: expression 'pos' has no type (or is ambiguous)
t10735.nim(44, 9) Error: type mismatch: got <cstring, >
but expected one of:
proc `[]`(s: string; i: BackwardsIndex): char
first type mismatch at position: 0
@@ -26,11 +28,14 @@ proc `[]`[T](s: openArray[T]; i: BackwardsIndex): T
first type mismatch at position: 0
proc `[]`[T](s: var openArray[T]; i: BackwardsIndex): var T
first type mismatch at position: 0
template `[]`(a: WideCStringObj; idx: int): Utf16Char
first type mismatch at position: 0
template `[]`(s: string; i: int): char
first type mismatch at position: 0
expression: `[]`(buf, pos)
t10735.nim(39, 9) Error: selector must be of an ordinal type, float or string
t10735.nim(44, 9) Error: expression '' has no type (or is ambiguous)
t10735.nim(46, 3) Error: illformed AST: case buf[pos]
'''
joinable: false
"""

35
tests/errmsgs/t22753.nim Normal file
View File

@@ -0,0 +1,35 @@
discard """
cmd: "nim check --hints:off $file"
errormsg: "type mismatch"
nimoutFull: true
nimout: '''
t22753.nim(34, 13) Error: array expects two type parameters
t22753.nim(35, 1) Error: expression 'x' has no type (or is ambiguous)
t22753.nim(35, 1) Error: expression 'x' has no type (or is ambiguous)
t22753.nim(35, 2) Error: type mismatch: got <>
but expected one of:
proc `[]=`(s: var string; i: BackwardsIndex; x: char)
first type mismatch at position: 0
proc `[]=`[I: Ordinal; T, S](a: T; i: I; x: sink S)
first type mismatch at position: 0
proc `[]=`[Idx, T; U, V: Ordinal](a: var array[Idx, T]; x: HSlice[U, V];
b: openArray[T])
first type mismatch at position: 0
proc `[]=`[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T)
first type mismatch at position: 0
proc `[]=`[T, U: Ordinal](s: var string; x: HSlice[T, U]; b: string)
first type mismatch at position: 0
proc `[]=`[T; U, V: Ordinal](s: var seq[T]; x: HSlice[U, V]; b: openArray[T])
first type mismatch at position: 0
proc `[]=`[T](s: var openArray[T]; i: BackwardsIndex; x: T)
first type mismatch at position: 0
template `[]=`(a: WideCStringObj; idx: int; val: Utf16Char)
first type mismatch at position: 0
template `[]=`(s: string; i: int; val: char)
first type mismatch at position: 0
expression: `[]=`(x, 0, 9)
'''
"""
var x: array[3] # bug #22753
x[0] = 9

36
tests/exprs/t22604.nim Normal file
View File

@@ -0,0 +1,36 @@
# if
for i in 0..<1:
let x =
case false
of true:
42
of false:
if true:
continue
else:
raiseAssert "Won't get here"
# nested case
for i in 0..<1:
let x =
case false
of true:
42
of false:
case true
of true:
continue
of false:
raiseAssert "Won't get here"
# try except
for i in 0..<1:
let x =
case false
of true:
42
of false:
try:
continue
except:
raiseAssert "Won't get here"

View File

@@ -0,0 +1,7 @@
# module a for t22373
# original:
type LightClientHeader* = object
# simplified:
type TypeOrTemplate* = object

View File

@@ -0,0 +1,18 @@
# module b for t22373
import m22373a
# original:
type
LightClientDataFork* {.pure.} = enum
None = 0,
Altair = 1
template LightClientHeader*(kind: static LightClientDataFork): auto =
when kind == LightClientDataFork.Altair:
typedesc[m22373a.LightClientHeader]
else:
static: raiseAssert "Unreachable"
# simplified:
template TypeOrTemplate*(num: int): untyped =
typedesc[m22373a.TypeOrTemplate]

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