Compare commits

..

41 Commits

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

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

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

(cherry picked from commit b1a8d6976f)

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

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

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

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

(cherry picked from commit 642ac0c1c3)

---------

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

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

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

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

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

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

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

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

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

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

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

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

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

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

`--info:nimVer` will return just:

```
2.1.1
```

(cherry picked from commit d0cc02dfc4)
2023-11-17 17:29:14 +08:00
Nikolay Nikolov
a77ca1a4bf Inlay hints backport to Nim v1.6.x (#22920) 2023-11-08 00:22:40 +01:00
narimiran
0779a5e11b bump NimVersion to 1.6.17 2023-11-01 19:43:25 +01:00
ringabout
a17c077f78 fixes chronicles (#22899) 2023-11-01 17:03:19 +08:00
ringabout
47010a3919 fixes #22874; backport #22088 to version-1-6 2023-11-01 00:51:48 +00:00
50 changed files with 858 additions and 196 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -600,7 +600,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
if t.kind == tyInt64: prc64[m] else: prc[m])
putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res])
else:
let res = "($1)($2 $3 $4)" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
let res = "($1)(($2) $3 ($4))" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
putIntoDest(p, d, e, res)
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
@@ -1806,9 +1806,9 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
if optBoundsCheck in p.options:
genBoundsCheck(p, m, b, c)
if op == mHigh:
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)", [rdLoc(b), rdLoc(c)]))
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1))", [rdLoc(b), rdLoc(c)]))
else:
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)+1", [rdLoc(b), rdLoc(c)]))
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1)+1)", [rdLoc(b), rdLoc(c)]))
else:
if not reifiedOpenArray(a):
if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)")

View File

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

View File

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

View File

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

View File

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

View File

@@ -706,6 +706,11 @@ template handleNestedTempl(n, processCall: untyped, willProduceStmt = false) =
of nkWhen: # This should be a "when nimvm" node.
result = copyTree(n)
result[1][0] = processCall(n[1][0], s)
of nkPragmaBlock:
result = shallowCopy(n)
for i in 0 ..< n.len-1:
result[i] = p(n[i], c, s, normal)
result[^1] = maybeVoid(n[^1], s)
else: assert(false)
proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
@@ -735,7 +740,7 @@ proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
if n.kind in {nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt,
nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkParForStmt, nkTryStmt}:
nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkParForStmt, nkTryStmt, nkPragmaBlock}:
template process(child, s): untyped = p(child, c, s, mode)
handleNestedTempl(n, process)
elif mode == sinkArg:
@@ -915,7 +920,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
result = n
of nkStringToCString, nkCStringToString, nkChckRangeF, nkChckRange64, nkChckRange, nkPragmaBlock:
of nkStringToCString, nkCStringToString, nkChckRangeF, nkChckRange64, nkChckRange:
result = shallowCopy(n)
for i in 0 ..< n.len:
result[i] = p(n[i], c, s, normal)

View File

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

View File

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

View File

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

View File

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

View File

@@ -1803,7 +1803,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
result.add(n[1])
if mode == noOverloadedSubscript:
bracketNotFoundError(c, result)
return n
return errorNode(c, n)
else:
result = semExprNoType(c, result)
return result

View File

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

View File

@@ -569,9 +569,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
if a.kind notin {nkIdentDefs, nkVarTuple}: illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var hasUserSpecifiedType = false
var typ: PType = nil
if a[^2].kind != nkEmpty:
typ = semTypeNode(c, a[^2], nil)
hasUserSpecifiedType = true
var typFlags: TTypeAllowedFlags
@@ -644,6 +646,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
addToVarSection(c, result, n, a)
continue
var v = semIdentDef(c, a[j], symkind, false)
when defined(nimsuggest):
v.hasUserSpecifiedType = hasUserSpecifiedType
styleCheckDef(c, v)
onDef(a[j].info, v)
if sfGenSym notin v.flags:
@@ -724,9 +728,11 @@ proc semConst(c: PContext, n: PNode): PNode =
if a.kind notin {nkConstDef, nkVarTuple}: illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var hasUserSpecifiedType = false
var typ: PType = nil
if a[^2].kind != nkEmpty:
typ = semTypeNode(c, a[^2], nil)
hasUserSpecifiedType = true
var typFlags: TTypeAllowedFlags
@@ -771,6 +777,8 @@ proc semConst(c: PContext, n: PNode): PNode =
for j in 0..<a.len-2:
var v = semIdentDef(c, a[j], skConst)
when defined(nimsuggest):
v.hasUserSpecifiedType = hasUserSpecifiedType
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
styleCheckDef(c, v)

View File

@@ -142,6 +142,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
result.n.add symNode
styleCheckDef(c, e)
onDef(e.info, e)
suggestSym(c.graph, e.info, e, c.graph.usageSym)
if sfGenSym notin e.flags:
if not isPure:
if overloadableEnums in c.features:

View File

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

View File

@@ -11,7 +11,7 @@
import
intsets, ast, astalgo, trees, msgs, strutils, platform, renderer, options,
lineinfos, int128, modulegraphs, astmsgs
lineinfos, int128, modulegraphs, astmsgs, wordrecg
type
TPreferedDesc* = enum
@@ -25,6 +25,8 @@ type
preferMixed,
# most useful, shows: symbol + resolved symbols if it differs, e.g.:
# tuple[a: MyInt{int}, b: float]
preferInlayHint,
preferInferredEffects,
TTypeRelation* = enum # order is important!
isNone, isConvertible,
@@ -503,7 +505,7 @@ const
"void", "iterable"]
const preferToResolveSymbols = {preferName, preferTypeName, preferModuleInfo,
preferGenericArg, preferResolved, preferMixed}
preferGenericArg, preferResolved, preferMixed, preferInlayHint, preferInferredEffects}
template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
tc.add concrete
@@ -537,7 +539,10 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
if prefer in preferToResolveSymbols and t.sym != nil and
sfAnon notin t.sym.flags and t.kind != tySequence:
if t.kind == tyInt and isIntLit(t):
result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
if prefer == preferInlayHint:
result = t.sym.name.s
else:
result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
elif t.kind == tyAlias and t[0].kind != tyAlias:
result = typeToString(t[0])
elif prefer in {preferResolved, preferMixed}:
@@ -553,7 +558,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
result = t.sym.name.s
if prefer == preferMixed and result != t.sym.name.s:
result = t.sym.name.s & "{" & result & "}"
elif prefer in {preferName, preferTypeName} or t.sym.owner.isNil:
elif prefer in {preferName, preferTypeName, preferInlayHint, preferInferredEffects} or t.sym.owner.isNil:
# note: should probably be: {preferName, preferTypeName, preferGenericArg}
result = t.sym.name.s
if t.kind == tyGenericParam and t.len > 0:
@@ -572,8 +577,11 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
if not isIntLit(t) or prefer == preferExported:
result = typeToStr[t.kind]
else:
if prefer == preferGenericArg:
case prefer:
of preferGenericArg:
result = $t.n.intVal
of preferInlayHint:
result = "int"
else:
result = "int literal(" & $t.n.intVal & ")"
of tyGenericInst, tyGenericInvocation:
@@ -746,6 +754,15 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
result.add(')')
if t.len > 0 and t[0] != nil: result.add(": " & typeToString(t[0]))
var prag = if t.callConv == ccNimCall and tfExplicitCallConv notin t.flags: "" else: $t.callConv
var hasImplicitRaises = false
if not isNil(t.owner) and not isNil(t.owner.ast) and (t.owner.ast.len - 1) >= pragmasPos:
let pragmasNode = t.owner.ast[pragmasPos]
let raisesSpec = effectSpec(pragmasNode, wRaises)
if not isNil(raisesSpec):
addSep(prag)
prag.add("raises: ")
prag.add($raisesSpec)
hasImplicitRaises = true
if tfNoSideEffect in t.flags:
addSep(prag)
prag.add("noSideEffect")
@@ -755,6 +772,20 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
if t.lockLevel.ord != UnspecifiedLockLevel.ord:
addSep(prag)
prag.add("locks: " & $t.lockLevel)
if not hasImplicitRaises and prefer == preferInferredEffects and not isNil(t.owner) and not isNil(t.owner.typ) and not isNil(t.owner.typ.n) and (t.owner.typ.n.len > 0):
let effects = t.owner.typ.n[0]
if effects.kind == nkEffectList and effects.len == effectListLen:
var inferredRaisesStr = ""
let effs = effects[exceptionEffects]
if not isNil(effs):
for eff in items(effs):
if not isNil(eff):
addSep(inferredRaisesStr)
inferredRaisesStr.add($eff.typ)
addSep(prag)
prag.add("raises: <inferred> [")
prag.add(inferredRaisesStr)
prag.add("]")
if prag.len != 0: result.add("{." & prag & ".}")
of tyVarargs:
result = typeToStr[t.kind] % typeToString(t[0])
@@ -800,11 +831,11 @@ proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
result = firstOrd(conf, lastSon(t))
of tyOrdinal:
if t.len > 0: result = firstOrd(conf, lastSon(t))
else: internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
else: fatal(conf, unknownLineInfo, "invalid kind for firstOrd(" & $t.kind & ')')
of tyUncheckedArray, tyCstring:
result = Zero
else:
internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
fatal(conf, unknownLineInfo, "invalid kind for firstOrd(" & $t.kind & ')')
result = Zero
proc firstFloat*(t: PType): BiggestFloat =
@@ -859,11 +890,11 @@ proc lastOrd*(conf: ConfigRef; t: PType): Int128 =
of tyProxy: result = Zero
of tyOrdinal:
if t.len > 0: result = lastOrd(conf, lastSon(t))
else: internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
else: fatal(conf, unknownLineInfo, "invalid kind for lastOrd(" & $t.kind & ')')
of tyUncheckedArray:
result = Zero
else:
internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
fatal(conf, unknownLineInfo, "invalid kind for lastOrd(" & $t.kind & ')')
result = Zero
proc lastFloat*(t: PType): BiggestFloat =

View File

@@ -1825,7 +1825,6 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags
let setLit = c.genx(checkExpr[1])
var rs = c.getTemp(getSysType(c.graph, n.info, tyBool))
c.gABC(n, opcContainsSet, rs, setLit, discVal)
c.freeTemp(discVal)
c.freeTemp(setLit)
# If the check fails let the user know
let lab1 = c.xjmp(n, if negCheck: opcFJmp else: opcTJmp, rs)
@@ -1838,6 +1837,7 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags
strLit.typ = strType
c.genLit(strLit, msgReg)
c.gABC(n, opcInvalidField, msgReg, discVal)
c.freeTemp(discVal)
c.freeTemp(msgReg)
c.patch(lab1)

View File

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

View File

@@ -149,7 +149,7 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] =
protocol)
result.orig = protocol
i.inc protocol.parseSaturatedNatural(result.major, i)
i.inc # Skip .
if i < protocol.len: inc i # Skip .
i.inc protocol.parseSaturatedNatural(result.minor, i)
proc sendStatus(client: AsyncSocket, status: string): Future[void] =

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -50,7 +50,7 @@ pkg "c2nim", "nim c testsuite/tester.nim"
pkg "cascade"
pkg "cello"
pkg "chroma"
pkg "chronicles", "nim c -o:chr -r chronicles.nim", url = "https://github.com/nim-lang/nim-chronicles"
pkg "chronicles", "nim c -o:chr -r chronicles.nim"
pkg "chronos", "nim c -r -d:release tests/testall"
pkg "cligen", "nim c --path:. -r cligen.nim"
pkg "combparser", "nimble test --gc:orc"
@@ -112,7 +112,6 @@ pkg "nimquery"
pkg "nimsl"
pkg "nimsvg"
pkg "nimterop", "nimble minitest"
pkg "nimwc", "nim c nimwc.nim"
pkg "nimx", "nim c --threads:on test/main.nim", allowFailure = true
pkg "nitter", "nim c src/nitter.nim", "https://github.com/zedeus/nitter"
# pkg "norm", "testament r tests/sqlite/trows.nim"
@@ -128,7 +127,7 @@ pkg "pnm"
pkg "polypbren"
pkg "prologue", "nimble tcompile"
pkg "protobuf", "nim c -o:protobuff -r src/protobuf.nim"
pkg "pylib"
# pkg "pylib"
pkg "rbtree"
pkg "react", "nimble example"
pkg "regex", "nim c src/regex"

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

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

View File

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

View File

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

View File

@@ -42,7 +42,7 @@ proc foo(x: int): string {.raises: [ValueError].} =
var p: MyProcType = foo #[tt.Error
^
type mismatch: got <proc (x: int): string{.noSideEffect, gcsafe, locks: 0.}> but expected 'MyProcType = proc (x: int): string{.closure.}'
type mismatch: got <proc (x: int): string{.raises: [ValueError], noSideEffect, gcsafe, locks: 0.}> but expected 'MyProcType = proc (x: int): string{.closure.}'
]#
{.pop.}

View File

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

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

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

View File

@@ -11,6 +11,6 @@ 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
# Should give an error since Something isn't a valid Test
b[0].name = "Test" #[tt.Error
^ type mismatch]#
^ expression '' has no type (or is ambiguous)]#

View File

@@ -17,6 +17,8 @@ template main() =
doAssert encode("") == ""
doAssert decode("") == ""
doAssert decode(" ") == ""
const testInputExpandsTo76 = "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
const testInputExpands = "++++++++++++++++++++++++++++++"
const longText = """Man is distinguished, not only by his reason, but by this
@@ -52,5 +54,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

@@ -16,6 +16,7 @@ endif
target := ?{"$(binDir)/" & toLowerAscii(c.name)}
ucpu := $(shell sh -c 'uname -m | tr "[:upper:]" "[:lower:]"')
ifeq ($(OS),Windows_NT)
uos := windows
@@ -44,6 +45,7 @@ endif
ifeq ($(uos),netbsd)
myos = netbsd
LDFLAGS += -lm
ucpu = $(shell sh -c 'uname -p')
endif
ifeq ($(uos),darwin)
myos = macosx
@@ -103,9 +105,18 @@ endif
ifeq ($(ucpu),x86_64)
mycpu = amd64
endif
ifeq ($(ucpu),parisc64)
mycpu = hppa
endif
ifeq ($(ucpu),s390x)
mycpu = s390x
endif
ifeq ($(ucpu),sparc)
mycpu = sparc
endif
ifeq ($(ucpu),sparc64)
mycpu = sparc64
endif
ifeq ($(ucpu),sun)
mycpu = sparc
endif
@@ -131,7 +142,7 @@ ifeq ($(ucpu),powerpc)
endif
endif
ifeq ($(ucpu),ppc)
mycpu = ppc
mycpu = powerpc
endif
ifneq (,$(filter $(ucpu), mips mips64))
mycpu = $(shell /bin/sh -c '"$(CC)" -dumpmachine | sed "s/-.*//"')
@@ -163,9 +174,18 @@ endif
ifeq ($(ucpu),aarch64)
mycpu = arm64
endif
ifeq ($(ucpu),arm64)
mycpu = arm64
endif
ifeq ($(ucpu),riscv64)
mycpu = riscv64
endif
ifeq ($(ucpu),e2k)
mycpu = e2k
endif
ifeq ($(ucpu),loongarch64)
mycpu = loongarch64
endif
ifndef mycpu
$(error unknown CPU architecture: $(ucpu) See makefile.nimf)
endif