Compare commits

...

64 Commits

Author SHA1 Message Date
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
95 changed files with 1480 additions and 314 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

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

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

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

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

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

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

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

@@ -57,6 +57,7 @@ type
SymInfoPair* = object
sym*: PSym
info*: TLineInfo
isDecl*: bool
PipelinePass* = enum
NonePass

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

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

@@ -595,7 +595,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 +670,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)
@@ -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

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

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)
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,7 @@ type
preferMixed,
# most useful, shows: symbol + resolved symbols if it differs, e.g.:
# tuple[a: MyInt{int}, b: float]
preferInlayHint,
TTypeRelation* = enum # order is important!
isNone, isConvertible,
@@ -508,7 +509,7 @@ const
"void", "iterable"]
const preferToResolveSymbols = {preferName, preferTypeName, preferModuleInfo,
preferGenericArg, preferResolved, preferMixed}
preferGenericArg, preferResolved, preferMixed, preferInlayHint}
template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
tc.add concrete
@@ -542,7 +543,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 +562,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} 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 +581,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,6 +758,14 @@ 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
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)
if tfNoSideEffect in t.flags:
addSep(prag)
prag.add("noSideEffect")

View File

@@ -1015,7 +1015,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 +1216,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 +1505,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, 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 = 2
## is the patch number of Nim's version.
## Odd for devel, even for releases.

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,17 @@ 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
--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
@@ -161,7 +168,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 +204,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 +493,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 +562,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 +593,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 +607,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 +660,17 @@ 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
else:
processSwitch(pass, p, conf)
of "tester":
gMode = mstdin
gEmitEof = true
@@ -659,6 +685,8 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; conf: ConfigRef) =
conf.suggestMaxResults = parseInt(p.val)
of "find":
findProject = true
of "clientprocessid":
conf.clientProcessId = parseInt(p.val)
else: processSwitch(pass, p, conf)
of cmdArgument:
let a = unixToNativePath(p.key)
@@ -756,6 +784,18 @@ proc findSymData(graph: ModuleGraph, trackPos: TLineInfo):
result[] = s
break
func isInRange*(current, startPos, endPos: TLineInfo, tokenLen: int): bool =
result = current.fileIndex == startPos.fileIndex and
(current.line > startPos.line or (current.line == startPos.line and current.col>=startPos.col)) and
(current.line < endPos.line or (current.line == endPos.line and current.col <= endPos.col))
proc findSymDataInRange(graph: ModuleGraph, startPos, endPos: TLineInfo):
seq[SymInfoPair] =
result = newSeq[SymInfoPair]()
for s in graph.fileSymbols(startPos.fileIndex).deduplicateSymInfoPair:
if isInRange(s.info, startPos, endPos, s.sym.name.s.len):
result.add(s)
proc findSymData(graph: ModuleGraph, file: AbsoluteFile; line, col: int):
ref SymInfoPair =
let
@@ -763,6 +803,14 @@ proc findSymData(graph: ModuleGraph, file: AbsoluteFile; line, col: int):
trackPos = newLineInfo(fileIdx, line, col)
result = findSymData(graph, trackPos)
proc findSymDataInRange(graph: ModuleGraph, file: AbsoluteFile; startLine, startCol, endLine, endCol: int):
seq[SymInfoPair] =
let
fileIdx = fileInfoIdx(graph.config, file)
startPos = newLineInfo(fileIdx, startLine, startCol)
endPos = newLineInfo(fileIdx, endLine, endCol)
result = findSymDataInRange(graph, startPos, endPos)
proc markDirtyIfNeeded(graph: ModuleGraph, file: string, originalFileIdx: FileIndex) =
let sha = $sha1.secureHashFile(file)
if graph.config.m.fileInfos[originalFileIdx.int32].hash != sha or graph.config.ideCmd == ideSug:
@@ -785,6 +833,23 @@ proc suggestResult(graph: ModuleGraph, sym: PSym, info: TLineInfo,
endLine = endLine, endCol = endCol)
suggestResult(graph.config, suggest)
proc suggestInlayHintResult(graph: ModuleGraph, sym: PSym, info: TLineInfo,
defaultSection = ideNone, endLine: uint16 = 0, endCol = 0) =
let section = if defaultSection != ideNone:
defaultSection
elif sym.info.exactEquals(info):
ideDef
else:
ideUse
var suggestDef = symToSuggest(graph, sym, isLocal=false, section,
info, 100, PrefixMatch.None, false, 0, true,
endLine = endLine, endCol = endCol)
suggestDef.inlayHintInfo = suggestToSuggestInlayHint(suggestDef)
suggestDef.section = ideInlayHints
if sym.kind == skForVar:
suggestDef.inlayHintInfo.allowInsert = false
suggestResult(graph.config, suggestDef)
const
# kinds for ideOutline and ideGlobalSymbols
searchableSymKinds = {skField, skEnumField, skIterator, skMethod, skFunc, skProc, skConverter, skTemplate}
@@ -892,7 +957,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
@@ -1048,6 +1113,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,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

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

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
]#

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]

25
tests/generics/t17509.nim Normal file
View File

@@ -0,0 +1,25 @@
type List[O] = object
next: ptr List[O]
proc initList[O](l: ptr List[O]) =
l[].next = l
type
PolytopeVertex[R] = object
list: List[PolytopeVertex[R]]
PolytopeEdge[R] = object
list: List[PolytopeEdge[R]]
Polytope[R] = object
vertices: List[PolytopeVertex[R]]
edges: List[PolytopeEdge[R]]
var pt: Polytope[float]
static:
doAssert pt.vertices.next is (ptr List[PolytopeVertex[float]])
doAssert pt.edges.next is (ptr List[PolytopeEdge[float]])
initList(addr pt.vertices)
initList(addr pt.edges)

16
tests/generics/t22373.nim Normal file
View File

@@ -0,0 +1,16 @@
# issue #22373
import m22373a
import m22373b
# original:
template lazy_header(name: untyped): untyped {.dirty.} =
var `name _ ptr`: ptr[data_fork.LightClientHeader] # this data_fork.Foo part seems required to reproduce
proc createLightClientUpdates(data_fork: static LightClientDataFork) =
lazy_header(attested_header)
createLightClientUpdates(LightClientDataFork.Altair)
# simplified:
proc generic[T](abc: T) =
var x: abc.TypeOrTemplate
generic(123)

View File

@@ -42,4 +42,23 @@ block: #4688
block: #4164
proc printStr[T](s: static[string]): T = discard
discard printStr[int]("hello static")
discard printStr[int]("hello static")
import macros
block: # issue #9040, statics with template, macro, symchoice explicit generics
block: # macro
macro fun[N: static int](): untyped =
newLit 1
const a = fun[2]()
doAssert a == 1
block: # template
template fun[N: static int](): untyped =
1
const a = fun[2]()
doAssert a == 1
block: # symchoice
proc newSeq[x: static int](): int = 1
template foo: int =
newSeq[2]()
doAssert foo() == 1

View File

@@ -46,6 +46,11 @@ block tdotlookup:
x.set("hello", "world")
result = x
doAssert abc(5) == 10
block: # ensure normal call is consistent with dot call
proc T(x: int): float = x.float
proc foo[T](x: int) =
doAssert typeof(T(x)) is typeof(x.T)
foo[uint](123)
block tmodule_same_as_proc:
# bug #1965

View File

@@ -101,3 +101,14 @@ echo @(b.arr[0].arr), @(b.arr[1].arr)
let y = b
echo @(y.arr[0].arr), @(y.arr[1].arr)
import macros
block: # issue #5121
type
A = object
AConst[X] = A
macro dumpType(t: typedesc): untyped =
result = newTree(nnkTupleConstr, newLit $t.getType[1].typeKind, newLit t.getType[1].treeRepr)
doAssert dumpType(A) == ("ntyObject", "Sym \"A\"")

View File

@@ -0,0 +1,16 @@
discard """
cmd: "nim check $file"
"""
type
Test[T, K] = object
name: string
Something = Test[int]
func `[]`[T, K](x: var Test[T, K], idx: int): var Test[T, K] =
x
var b: Something
# Should give a type-mismatch since Something isn't a valid Test
b[0].name = "Test" #[tt.Error
^ type mismatch]#

View File

@@ -78,3 +78,65 @@ block:
doAssert x.data.len == 5
var y: Leb128Buf[uint16]
doAssert y.data.len == 3
import macros
block: # issue #12415
macro isSomePointerImpl(t: typedesc): bool =
var impl = t.getTypeInst[1].getTypeImpl
if impl.kind == nnkDistinctTy:
impl = impl[0].getTypeImpl
if impl.kind in {nnkPtrTy,nnkRefTy}:
result = newLit(true)
elif impl.kind == nnkSym and impl.eqIdent("pointer"):
result = newLit(true)
else:
result = newLit(false)
proc isSomePointer[T](t: typedesc[T]): bool {.compileTime.} =
isSomePointerImpl(t)
type
Option[T] = object
## An optional type that stores its value and state separately in a boolean.
when isSomePointer(typedesc(T)):
val: T
else:
val: T
has: bool
var x: Option[ref int]
doAssert not compiles(x.has)
var y: Option[int]
doAssert compiles(y.has)
block: # issue #2002
proc isNillable(T: typedesc): bool =
when compiles((let v: T = nil)):
return true
else:
return false
type
Foo[T] = object
when isNillable(T):
nillable: float
else:
notnillable: int
var val1: Foo[ref int]
doAssert compiles(val1.nillable)
doAssert not compiles(val1.notnillable)
var val2: Foo[int]
doAssert not compiles(val2.nillable)
doAssert compiles(val2.notnillable)
block: # issue #1771
type
Foo[X, T] = object
bar: array[X.low..X.high, T]
proc test[X, T](f: Foo[X, T]): T =
f.bar[X.low]
var a: Foo[range[0..2], float]
doAssert test(a) == 0.0

79
tests/iter/t22619.nim Normal file
View File

@@ -0,0 +1,79 @@
# bug #22619
when false: # todo fixme
block:
type
Resource = object
value: int
Object = object
r {.cursor.}: Resource
s {.cursor.}: seq[Resource]
var numDestroy = 0
proc `=copy`(x: var Resource, y: Resource) {.error.} # disallow full copies
proc `=destroy`(x: Resource) =
inc numDestroy
proc test() =
# perform the test in procedure so that globals aren't used (their different
# semantics with regards to destruction would interfere)
var
r = Resource(value: 1) # initialize a resource
s = @[Resource(value: 2)]
# make sure no copy is required in the initializer expression:
var o = Object(r: r, s: s)
# copying the object doesn't perform a full copy of the cursor fields:
var o2 = o
discard addr(o2) # prevent `o2` from being turned into a cursor
# check that the fields were shallow-copied:
doAssert o2.r.value == 1
doAssert o2.s[0].value == 2
# make sure no copy is required with normal field assignments:
o.r = r
o.s = s
# when `o` and `o2` are destroyed, their destructor must not be called on
# their fields
test()
# one call for the `r` local and one for the object in `s`
doAssert numDestroy == 2
block:
type Value = distinct int
var numDestroy = 0
proc `=destroy`(x: Value) =
inc numDestroy
iterator iter(s: seq[Value]): int {.closure.} =
# because it is used across yields, `s2` is lifted into the iterator's
# environment. Since non-ref cursors in object didn't have their hooks
# disabled inside the environments lifted hooks, this led to double
# frees
var s2 {.cursor.} = s
var i = 0
let L = s2.len
while i < L:
yield s2[i].int
inc i
proc test() =
var s = @[Value(1), Value(2)]
let cl = iter
# make sure resuming the iterator works:
doAssert cl(s) == 1
doAssert cl(s) == 2
doAssert cl(s) == 0
test()
doAssert numDestroy == 2

View File

@@ -268,6 +268,37 @@ xbenchmark:
discard inputtest
fastSHA("hey")
block: # issue #4547
macro lazy(stmtList : typed) : untyped =
let decl = stmtList[0]
decl.expectKind nnkLetSection
let name = decl[0][0].strVal
let call = decl[0][2].copy
call.expectKind nnkCall
let ident = newIdentNode("get" & name)
result = quote do:
var value : type(`call`)
proc `ident`() : type(`call`) =
if value.isNil:
value = `call`
value
type MyObject = object
a,b: int
# this part, the macro call and it's result (written in the comment below) is important
lazy:
let y = new(MyObject)
#[
var value: type(new(MyObject))
proc gety(): type(new(MyObject)) =
if value.isNil:
value = new(MyObject)
value
]#
doAssert gety().a == 0 # works and should work
doAssert gety().b == 0 # works and should work
doAssert not declared(y)
doAssert not compiles(y.a) # identifier y should not exist anymore
doAssert not compiles(y.b) # identifier y should not exist anymore
block: # bug #13511
type

View File

@@ -271,10 +271,13 @@ sub/mmain.idx""", context
check execCmdEx(cmd) == ("12\n", 0)
block: # bug #15316
let file = testsDir / "misc/m15316.nim"
let cmd = fmt"{nim} check --hints:off --nimcache:{nimcache} {file}"
check execCmdEx(cmd) == ("m15316.nim(1, 15) Error: expression expected, but found \')\'\nm15316.nim(2, 1) Error: expected: \':\', but got: \'[EOF]\'\nm15316.nim(2, 1) Error: expression expected, but found \'[EOF]\'\nm15316.nim(2, 1) " &
"Error: expected: \')\', but got: \'[EOF]\'\nError: illformed AST: \n", 1)
when not defined(windows):
# This never worked reliably on Windows. Needs further investigation but it is hard to reproduce.
# Looks like a mild stack corruption when bailing out of nested exception handling.
let file = testsDir / "misc/m15316.nim"
let cmd = fmt"{nim} check --hints:off --nimcache:{nimcache} {file}"
check execCmdEx(cmd) == ("m15316.nim(1, 15) Error: expression expected, but found \')\'\nm15316.nim(2, 1) Error: expected: \':\', but got: \'[EOF]\'\nm15316.nim(2, 1) Error: expression expected, but found \'[EOF]\'\nm15316.nim(2, 1) " &
"Error: expected: \')\', but got: \'[EOF]\'\nError: illformed AST: \n", 1)
block: # config.nims, nim.cfg, hintConf, bug #16557

View File

@@ -55,3 +55,35 @@ type
x: int
when (NimMajor, NimMinor) >= (1, 1):
y: int
discard MyObject(x: 100, y: 200)
block: # Ensure when evaluates properly in objects
type X[bits: static int] = object #22474
when bits >= 256:
data32: byte
else:
data16: byte
static:
discard X[255]().data16
discard X[256]().data32
type ComplexExprObject[S: static string, I: static int, Y: static auto] = object
when 'h' in S and I < 10 and Y isnot float:
a: int
elif I > 30:
b: int
elif typeof(Y) is float:
c: int
else:
d: int
static:
discard ComplexExprObject["hello", 9, 300i32]().a
discard ComplexExprObject["", 40, 30f]().b
discard ComplexExprObject["", 20, float 30]().c
discard ComplexExprObject["", 20, ""]().d

View File

@@ -0,0 +1,3 @@
type StringArray[N:int] = array[N, string]
let a = ["one", "two"]
doAssert a is StringArray

View File

@@ -53,5 +53,9 @@ template main() =
doAssert encode("", safe = true) == ""
doAssert encode("the quick brown dog jumps over the lazy fox", safe = true) == "dGhlIHF1aWNrIGJyb3duIGRvZyBqdW1wcyBvdmVyIHRoZSBsYXp5IGZveA=="
func mainNoSideEffects() = main()
static: main()
main()
static: mainNoSideEffects()
mainNoSideEffects()

View File

@@ -334,3 +334,16 @@ block:
`hello`(12, type(x))
main()
block: # bug #22947
macro bar[N: static int](a: var array[N, int]) =
result = quote do:
for i in 0 ..< `N`:
`a`[i] = i
func foo[N: static int](a: var array[N, int]) =
bar(a)
var a: array[4, int]
foo(a)

View File

@@ -20,7 +20,8 @@ block:
discard x.s
proc main =
var x = X(s: "abcdefg")
let m = "abcdefg"
var x = X(s: ensureMove m)
consume(ensureMove x)
static: main()

View File

@@ -1,5 +1,5 @@
discard """
errormsg: "'if true: s else: String()' is not a mutable location; it cannot be moved"
errormsg: "Nested expressions cannot be moved: 'if true: s else: String()'"
"""
type

View File

@@ -1,6 +1,7 @@
discard """
matrix: "--gc:none -d:useMalloc --threads:off"
matrix: "--mm:none -d:useMalloc"
"""
# bug #15617
# bug #22262
let x = 4
doAssert x == 4

View File

@@ -48,3 +48,35 @@ template publicTemplateObjSyntax*(o: var ObjA, arg: Natural, doStuff: untyped) =
o.foo2()
doStuff
o.bar2(arg)
# issue #15246
import os
template sourceBaseName*(): string =
bind splitFile
instantiationInfo().filename.splitFile().name
# issue #12683
import unicode
template toRune(s: string): Rune = s.runeAt(0)
proc heh*[T](x: Slice[T], chars: string) = discard chars.toRune
# issue #7889
from streams import newStringStream, readData, writeData
template bindmeTemplate*(): untyped =
var tst = "sometext"
var ss = newStringStream("anothertext")
ss.writeData(tst[0].addr, 2)
discard ss.readData(tst[0].addr, 2) # <= comment this out to make compilation successful
from macros import quote, newIdentNode
macro bindmeQuote*(): untyped =
quote do:
var tst = "sometext"
var ss = newStringStream("anothertext")
ss.writeData(tst[0].addr, 2)
discard ss.readData(tst[0].addr, 2) # <= comment this out to make compilation successful

View File

@@ -0,0 +1,8 @@
template elementType(a: untyped): typedesc =
typeof(block: (for ai in a: ai))
func fn[T](a: T) =
doAssert elementType(a) is int
@[1,2,3].fn

View File

@@ -18,3 +18,15 @@ block: # issue #11733
var evaluated = false
a.publicTemplateObjSyntax(42): evaluated = true
doAssert evaluated
block: # issue #15246
doAssert sourceBaseName() == "tdotcall"
block: # issue #12683
heh(0..40, "|")
block: # issue #7889
if false:
bindmeQuote()
if false:
bindmeTemplate()

View File

@@ -302,3 +302,7 @@ block: # bug #21920
discard
t[void]() # Error: expression has no type: discard
block: # issue #19865
template f() = discard default(system.int)
f()

View File

@@ -354,6 +354,23 @@ block gensym3:
echo a ! b ! c ! d ! e
echo x,y,z
block: # issue #2465
template t() =
template declX(str: string) {.gensym.} =
var x {.inject.} : string = str
t()
doAssert not declared(declX)
doAssert not compiles(declX("a string"))
template t2() =
template fooGensym() {.gensym.} =
echo 42
t2()
doAssert not declared(fooGensym)
doAssert not compiles(fooGensym())
block identifier_construction_with_overridden_symbol:
# could use add, but wanna make sure it's an override no matter what
@@ -368,3 +385,22 @@ block identifier_construction_with_overridden_symbol:
`examplefn n`()
exampletempl(1)
import typetraits
block: # issue #4596
type
T0 = object
T1 = object
template printFuncsT() =
proc getV[A](a: typedesc[A]): string =
var s {. global .} = name(A)
return s
printFuncsT()
doAssert getV(T1) == "T1"
doAssert getV(T0) == "T0"
doAssert getV(T0) == "T0"
doAssert getV(T1) == "T1"

View File

@@ -0,0 +1,80 @@
block: # basic template generic parameter substitution
block: # issue #13527
template typeNameTempl[T](a: T): string = $T
proc typeNameProc[T](a: T): string = $T
doAssert typeNameTempl(1) == typeNameProc(1)
doAssert typeNameTempl(true) == typeNameProc(true)
doAssert typeNameTempl(1.0) == typeNameProc(1.0)
doAssert typeNameTempl(1u8) == typeNameProc(1u8)
template isDefault[T](a: T): bool = a == default(T)
doAssert isDefault(0.0)
block: # issue #17240
func to(c: int, t: typedesc[float]): t = discard
template converted[I, T](i: seq[I], t: typedesc[T]): seq[T] =
var result = newSeq[T](2)
result[0] = i[0].to(T)
result
doAssert newSeq[int](3).converted(float) == @[0.0, 0.0]
block: # issue #6340
type A[T] = object
v: T
proc foo(x: int): string = "int"
proc foo(x: typedesc[int]): string = "typedesc[int]"
template fooT(x: int): string = "int"
template fooT(x: typedesc[int]): string = "typedesc[int]"
proc foo[T](x: A[T]): (string, string) =
(foo(T), fooT(T))
template fooT[T](x: A[T]): (string, string) =
(foo(T), fooT(T))
var x: A[int]
doAssert foo(x) == fooT(x)
block: # issue #20033
template run[T](): T = default(T)
doAssert run[int]() == 0
import options, tables
block: # complex cases of above with imports
block: # issue #19576, complex case
type RegistryKey = object
key, val: string
var regKey = @[RegistryKey(key: "abc", val: "def")]
template findFirst[T](s: seq[T], pred: proc(x: T): bool): Option[T] =
var res = none(T) # important line
for x in s:
if pred(x):
res = some(x)
break
res
proc getval(searchKey: string): Option[string] =
let found = regKey.findFirst(proc (rk: RegistryKey): bool = rk.key == searchKey)
if found.isNone: none(string)
else: some(found.get().val)
doAssert getval("strange") == none(string)
doAssert getval("abc") == some("def")
block: # issue #19076
block: # case 1
var tested: Table[string,int]
template `[]`[V](t:Table[string,V],key:string):untyped =
$V
doAssert tested["abc"] == "int"
template `{}`[V](t:Table[string,V],key:string):untyped =
($V, tables.`[]`(t, key))
doAssert (try: tested{"abc"} except KeyError: ("not there", 123)) == ("not there", 123)
tables.`[]=`(tested, "abc", 456)
doAssert tested["abc"] == "int"
doAssert tested{"abc"} == ("int", 456)
block: # case 2
type Foo[A,T] = object
t:T
proc init[A,T](f:type Foo,a:typedesc[A],t:T):Foo[A,T] = Foo[A,T](t:t)
template fromOption[A](o:Option[A]):auto =
when o.isSome:
Foo.init(A,35)
else:
Foo.init(A,"hi")
let op = fromOption(some(5))

View File

@@ -1,12 +1,21 @@
var x = 0
block: # issue #16005
var x = 0
block:
type Foo = object
x: float # ok
template main() =
block:
type Foo = object
x: float # Error: cannot use symbol of kind 'var' as a 'field'
x: float # ok
main()
template main() =
block:
type Foo = object
x: float # Error: cannot use symbol of kind 'var' as a 'field'
main()
block: # issue #19552
template test =
type
test2 = ref object
reset: int
test()

32
tests/types/t5648.nim Normal file
View File

@@ -0,0 +1,32 @@
discard """
output: '''
ptr Foo
'''
joinable: false
"""
# not joinable because it causes out of memory with --gc:boehm
# issue #5648
import typetraits
type Foo = object
bar: int
proc main() =
var f = create(Foo)
f.bar = 3
echo f.type.name
discard realloc(f, 0)
var g = Foo()
g.bar = 3
var
mainPtr = cast[pointer](main)
mainFromPtr = cast[typeof(main)](mainPtr)
doAssert main == mainFromPtr
main()

View File

@@ -3,7 +3,6 @@ discard """
true
true
true
ptr Foo
(member: "hello world")
(member: 123.456)
(member: "hello world", x: ...)
@@ -11,10 +10,7 @@ ptr Foo
0
false
'''
joinable: false
"""
# not joinable because it causes out of memory with --gc:boehm
import typetraits
block t1252:
echo float32 isnot float64
@@ -29,28 +25,6 @@ block t5640:
var v = vec2([0.0'f32, 0.0'f32])
block t5648:
type Foo = object
bar: int
proc main() =
var f = create(Foo)
f.bar = 3
echo f.type.name
discard realloc(f, 0)
var g = Foo()
g.bar = 3
var
mainPtr = cast[pointer](main)
mainFromPtr = cast[typeof(main)](mainPtr)
doAssert main == mainFromPtr
main()
block t7581:
discard int -1
@@ -107,3 +81,18 @@ block:
var f1: Foo
echo f1.bar
import macros
block: # issue #12582
macro foo(T: type): type =
nnkBracketExpr.newTree(bindSym "array", newLit 1, T)
var
_: foo(int) # fine
type
Foo = object
x: foo(int) # fine
Bar = ref object
x: foo(int) # error
let b = Bar()
let b2 = Bar(x: [123])

32
tests/vm/tnoreturn.nim Normal file
View File

@@ -0,0 +1,32 @@
block: # issue #22216
type
Result[T, E] = object
case oVal: bool
of false:
eVal: E
of true:
vVal: T
func raiseResultDefect(m: string) {.noreturn, noinline.} =
raise (ref Defect)(msg: m)
template withAssertOk(self: Result, body: untyped): untyped =
case self.oVal
of false:
raiseResultDefect("Trying to access value with err Result")
else:
body
func value[T, E](self: Result[T, E]): T {.inline.} =
withAssertOk(self):
self.vVal
const
x = Result[int, string](oVal: true, vVal: 123)
z = x.value()
let
xx = Result[int, string](oVal: true, vVal: 123)
zz = x.value()
doAssert z == zz

18
tests/vm/ttypedesc.nim Normal file
View File

@@ -0,0 +1,18 @@
block: # issue #15760
type
Banana = object
SpecialBanana = object
proc getName(_: type Banana): string = "Banana"
proc getName(_: type SpecialBanana): string = "SpecialBanana"
proc x[T](): string =
const n = getName(T) # this one works
result = n
proc y(T: type): string =
const n = getName(T) # this one failed to compile
result = n
doAssert x[SpecialBanana]() == "SpecialBanana"
doAssert y(SpecialBanana) == "SpecialBanana"

View File

@@ -0,0 +1,3 @@
static:
echo cast[int32](12.0) #[tt.Error
^ VM does not support 'cast' from tyFloat with size 8 to tyInt32 with size 4 due to different sizes]#

View File

@@ -1,10 +1,11 @@
# bug #4462
import macros
import os
# bug #4462
block:
proc foo(t: typedesc) {.compileTime.} =
assert sameType(getType(t), getType(int))
assert sameType(getType(t), getType(typedesc[int]))
assert sameType(getType(t), getType(type int))
static:
foo(int)
@@ -733,3 +734,34 @@ block: # bug #22190
tab = mkOpTable(Berlin)
doAssert not tab
block: # issue #22524
const cnst = cstring(nil)
doAssert cnst.isNil
doAssert cnst == nil
let b = cnst
doAssert b.isNil
doAssert b == nil
let a = static: cstring(nil)
doAssert a.isNil
static:
var x: cstring
doAssert x.isNil
doAssert x == nil
doAssert x != ""
block: # issue #15730
const s: cstring = ""
doAssert s != nil
static:
let s: cstring = ""
doAssert not s.isNil
doAssert s != nil
doAssert s == ""
static: # more nil cstring issues
let x = cstring(nil)
doAssert x.len == 0

View File

@@ -630,6 +630,7 @@ v("MSG_EOR")
v("MSG_OOB")
v("SCM_RIGHTS")
v("SO_ACCEPTCONN")
v("SO_BINDTODEVICE")
v("SO_BROADCAST")
v("SO_DEBUG")
v("SO_DONTROUTE")