mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 02:43:41 +00:00
Compare commits
319 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44e653a931 | ||
|
|
0250c4710d | ||
|
|
8001c7be98 | ||
|
|
94f80f5bcb | ||
|
|
1281d8dfb8 | ||
|
|
7a8817e87f | ||
|
|
a63d434180 | ||
|
|
9fc0955587 | ||
|
|
cb22a99584 | ||
|
|
ad5c784d22 | ||
|
|
a6d84179fc | ||
|
|
e4d5139de0 | ||
|
|
9d23c14dd2 | ||
|
|
daad1cd9d9 | ||
|
|
61ac87a2b8 | ||
|
|
f825c8f691 | ||
|
|
4b4ef2b4b3 | ||
|
|
431eb05708 | ||
|
|
3e154e7740 | ||
|
|
e70044fb28 | ||
|
|
5618a34d61 | ||
|
|
f48daa29f6 | ||
|
|
2640dc2637 | ||
|
|
2b6b080323 | ||
|
|
ab1ae92587 | ||
|
|
5dd88ca1a4 | ||
|
|
598d9f8402 | ||
|
|
f7f7a02915 | ||
|
|
28b301cbaa | ||
|
|
69c2c05463 | ||
|
|
cc6bc8960d | ||
|
|
05991805fb | ||
|
|
82561f31eb | ||
|
|
e5027dc3da | ||
|
|
f97d840f96 | ||
|
|
560800246e | ||
|
|
cf1ecee794 | ||
|
|
6b00463074 | ||
|
|
e996d98a8a | ||
|
|
5c88067953 | ||
|
|
061d106671 | ||
|
|
c2e2f50d35 | ||
|
|
2ff517462b | ||
|
|
29a064e275 | ||
|
|
bfc0d64825 | ||
|
|
540d16540b | ||
|
|
7705948d52 | ||
|
|
a154acda85 | ||
|
|
8f9ea358b6 | ||
|
|
8d7e1c4649 | ||
|
|
87dc838370 | ||
|
|
c04214f8cb | ||
|
|
132a694c6e | ||
|
|
c55506006f | ||
|
|
a263e9aae0 | ||
|
|
94560a9faa | ||
|
|
5f46474555 | ||
|
|
21e1fa6217 | ||
|
|
bf06fb7053 | ||
|
|
ccbdb95539 | ||
|
|
de98648caa | ||
|
|
3f1f26a7e2 | ||
|
|
8f38f3e34d | ||
|
|
c7d090c418 | ||
|
|
9b31b12ca5 | ||
|
|
3c74ec0a0f | ||
|
|
4da6577c97 | ||
|
|
93ee832d3c | ||
|
|
5e49d3b68a | ||
|
|
5e5803f28f | ||
|
|
d9e14414a4 | ||
|
|
c346c0b91b | ||
|
|
822c7acd3c | ||
|
|
71bbbdbf96 | ||
|
|
1d8b7aa07c | ||
|
|
db5ce7ed48 | ||
|
|
939702a001 | ||
|
|
753aed9d63 | ||
|
|
c9d7c67acb | ||
|
|
265499ee57 | ||
|
|
2f13f5bb56 | ||
|
|
9a86afc8fd | ||
|
|
553c2e5cff | ||
|
|
bf0ad3acab | ||
|
|
4c918515fd | ||
|
|
6e45429ab1 | ||
|
|
8a528979e8 | ||
|
|
3fb5157ab1 | ||
|
|
74c687e395 | ||
|
|
204369845a | ||
|
|
150fc44bb3 | ||
|
|
1a92a4b0bd | ||
|
|
498ac30f9a | ||
|
|
2d63592619 | ||
|
|
160436c8b3 | ||
|
|
c576c1cb76 | ||
|
|
32e0542ca0 | ||
|
|
72f4a0d3e9 | ||
|
|
cf30401f02 | ||
|
|
4f89307180 | ||
|
|
6494b95f3c | ||
|
|
ef0776380c | ||
|
|
cfb38c2383 | ||
|
|
99032ca07b | ||
|
|
e2f1fab458 | ||
|
|
03f07f8b5e | ||
|
|
3597824c00 | ||
|
|
c55c49052f | ||
|
|
47ebaa4200 | ||
|
|
4b27458cfc | ||
|
|
1eda325177 | ||
|
|
62d497237a | ||
|
|
29f9cc0e3d | ||
|
|
976b5bf7c5 | ||
|
|
74fa24ce45 | ||
|
|
fbb58343d9 | ||
|
|
e6ea779b06 | ||
|
|
cb138fc304 | ||
|
|
c6f7337c77 | ||
|
|
6c070452e4 | ||
|
|
475b7e1444 | ||
|
|
64692b185f | ||
|
|
da3948ae32 | ||
|
|
f052e251be | ||
|
|
577b4f795c | ||
|
|
e99c248106 | ||
|
|
9c6444c192 | ||
|
|
e94f9cdb4f | ||
|
|
4ddb8feb93 | ||
|
|
ff8fbb3001 | ||
|
|
63296fb983 | ||
|
|
80068f7dfc | ||
|
|
8e181cbd3f | ||
|
|
80c33b187d | ||
|
|
817a16c027 | ||
|
|
63ae6308c2 | ||
|
|
f0b19e8ef2 | ||
|
|
41569f9693 | ||
|
|
5977f553fc | ||
|
|
462209f4b0 | ||
|
|
55abacc514 | ||
|
|
ce1570a6fb | ||
|
|
cc6497406f | ||
|
|
00c9dafd5f | ||
|
|
9560efafc2 | ||
|
|
b92666745e | ||
|
|
d08c2f195c | ||
|
|
c225d0182a | ||
|
|
e0e8762e6b | ||
|
|
fffb0dbea5 | ||
|
|
f02b359968 | ||
|
|
7c4fbde78e | ||
|
|
2f08a1e390 | ||
|
|
6cc39b5a57 | ||
|
|
2bfabfde49 | ||
|
|
d4ce6acfed | ||
|
|
11f6fd88ea | ||
|
|
452203a28e | ||
|
|
b47a98f7f2 | ||
|
|
95efe6d3ca | ||
|
|
a2c51867f2 | ||
|
|
0848a816b2 | ||
|
|
1be3caf7c3 | ||
|
|
4095cae94c | ||
|
|
3e9df7da45 | ||
|
|
abe178b602 | ||
|
|
42a3e31826 | ||
|
|
b9260514fe | ||
|
|
5d88e6c5f5 | ||
|
|
36429cabda | ||
|
|
a983c6a843 | ||
|
|
561902ca2b | ||
|
|
b3b7a1e73f | ||
|
|
efaa55d429 | ||
|
|
afedd5ee24 | ||
|
|
9b51f9b7e1 | ||
|
|
71583cd2e9 | ||
|
|
53421be985 | ||
|
|
37229707ed | ||
|
|
30362cde20 | ||
|
|
9fb713cf23 | ||
|
|
23ea176cb2 | ||
|
|
48e5520894 | ||
|
|
23b0b10886 | ||
|
|
04254fe9d6 | ||
|
|
272bc81f51 | ||
|
|
d10f841b60 | ||
|
|
1781848122 | ||
|
|
916c4bb484 | ||
|
|
2e6cfe3a0d | ||
|
|
04f810c2ec | ||
|
|
192cb9ff90 | ||
|
|
127d63b343 | ||
|
|
a27ed88688 | ||
|
|
7724cd534f | ||
|
|
4e89dffc15 | ||
|
|
19a11bc8a6 | ||
|
|
244f3f62ce | ||
|
|
b6f8ed7193 | ||
|
|
18289607eb | ||
|
|
d57418ab9e | ||
|
|
e7e33b14b5 | ||
|
|
cd97e3ef98 | ||
|
|
283698b1ec | ||
|
|
8f35bca839 | ||
|
|
12145adecd | ||
|
|
5ea4dea4ea | ||
|
|
e7d14ce6f2 | ||
|
|
839ec1395d | ||
|
|
ac32cf129b | ||
|
|
992912e21d | ||
|
|
ca53629c42 | ||
|
|
554a9ad156 | ||
|
|
1c027d591c | ||
|
|
0ed4c2bc4f | ||
|
|
ac25f63f82 | ||
|
|
e5a04f8914 | ||
|
|
8c31c210ee | ||
|
|
64ded4a51f | ||
|
|
5da17acfce | ||
|
|
5bc573cf1e | ||
|
|
b100c67515 | ||
|
|
c2263c685f | ||
|
|
01403f8cfa | ||
|
|
2443b40623 | ||
|
|
3565d14cc4 | ||
|
|
6d9961c898 | ||
|
|
740112c1e0 | ||
|
|
bf446e8cec | ||
|
|
bb3cdcad99 | ||
|
|
9954b7f046 | ||
|
|
dd36bfffa1 | ||
|
|
9d9bf12e1c | ||
|
|
45e87ade15 | ||
|
|
b238c077a1 | ||
|
|
29cd083e12 | ||
|
|
2e35621af0 | ||
|
|
e0aa7cf09b | ||
|
|
98bd81b4a3 | ||
|
|
5e7c6b7f7e | ||
|
|
0699b57402 | ||
|
|
f235eb48a0 | ||
|
|
975a5b64ad | ||
|
|
5d2b1a8943 | ||
|
|
b14958caa0 | ||
|
|
208ed6e816 | ||
|
|
e085010e59 | ||
|
|
f6f1594cef | ||
|
|
c657af440a | ||
|
|
df069c8ddb | ||
|
|
e524df8746 | ||
|
|
81a302b197 | ||
|
|
e301285d4c | ||
|
|
daba6d935f | ||
|
|
1d06c70c18 | ||
|
|
a480cbddcc | ||
|
|
eb2ed782c6 | ||
|
|
dc6073b0b8 | ||
|
|
3d939dd863 | ||
|
|
d426f75593 | ||
|
|
051c201068 | ||
|
|
b0291b88fc | ||
|
|
1b5b98c943 | ||
|
|
645200aa3d | ||
|
|
a7bd58ed07 | ||
|
|
4a95d45b28 | ||
|
|
60403c9e6b | ||
|
|
e39b01e126 | ||
|
|
a4f9bc55c7 | ||
|
|
e27f595aee | ||
|
|
96bd6426c2 | ||
|
|
afb5212fe0 | ||
|
|
5c48058c86 | ||
|
|
33375aff15 | ||
|
|
1fbfd77580 | ||
|
|
3326f1df1d | ||
|
|
a156484553 | ||
|
|
c8f6eb6c14 | ||
|
|
513ced8966 | ||
|
|
75d76c28c8 | ||
|
|
2351b66e08 | ||
|
|
a2367d4bd2 | ||
|
|
4e91c11eff | ||
|
|
9d81415603 | ||
|
|
60ddbf1e45 | ||
|
|
a48c16b155 | ||
|
|
796785abf6 | ||
|
|
e89592787b | ||
|
|
9b37fc98a2 | ||
|
|
9e8ad86d6a | ||
|
|
d1924f2852 | ||
|
|
7a9db0e5c5 | ||
|
|
e7b7356bd1 | ||
|
|
ce94ce40c7 | ||
|
|
6d99de7c2c | ||
|
|
06846d23ad | ||
|
|
bc5c6c812b | ||
|
|
eb04535b53 | ||
|
|
11ef97d57f | ||
|
|
5874bce91c | ||
|
|
38ebd767db | ||
|
|
293ef09b49 | ||
|
|
8fb501b52c | ||
|
|
c087e2d8de | ||
|
|
45977c2d70 | ||
|
|
1d63995896 | ||
|
|
893dab429e | ||
|
|
1e9746aade | ||
|
|
35f5a3e48f | ||
|
|
642807de18 | ||
|
|
8a9da2fa0d | ||
|
|
a222aa14e1 | ||
|
|
d86d7c9fe1 | ||
|
|
b3c77bb982 | ||
|
|
1dffa67b6e | ||
|
|
bdcd87afca | ||
|
|
018ae963ba | ||
|
|
cffbf5e778 | ||
|
|
cac0e01725 |
@@ -1,27 +1,21 @@
|
||||
# see https://man.sr.ht/builds.sr.ht/compatibility.md#freebsd
|
||||
image: freebsd/latest
|
||||
|
||||
# packages:
|
||||
# - databases/sqlite3
|
||||
# - devel/boehm-gc-threaded
|
||||
# - devel/pcre
|
||||
# - devel/sdl20
|
||||
# - devel/sfml
|
||||
# - www/node
|
||||
# - devel/gmake
|
||||
# - devel/git
|
||||
packages:
|
||||
- databases/sqlite3
|
||||
- devel/boehm-gc-threaded
|
||||
- devel/pcre
|
||||
- devel/sdl20
|
||||
- devel/sfml
|
||||
- www/node
|
||||
- devel/gmake
|
||||
sources:
|
||||
- https://github.com/nim-lang/Nim
|
||||
environment:
|
||||
CC: /usr/bin/clang
|
||||
tasks:
|
||||
- setup: |
|
||||
# workaround https://github.com/timotheecour/Nim/issues/76
|
||||
sudo pkg update -q -f
|
||||
sudo pkg install -y -q databases/sqlite3 devel/boehm-gc-threaded devel/pcre \
|
||||
devel/sdl20 devel/sfml www/node devel/gmake devel/git
|
||||
cd Nim
|
||||
git clone --depth 1 -q https://github.com/nim-lang/csources.git
|
||||
git clone --depth 1 -q https://github.com/nim-lang/csources_v1.git csources
|
||||
gmake -C csources -j $(sysctl -n hw.ncpu)
|
||||
bin/nim c --skipUserCfg --skipParentCfg koch
|
||||
echo 'export PATH=$HOME/Nim/bin:$PATH' >> $HOME/.buildenv
|
||||
|
||||
@@ -18,7 +18,7 @@ environment:
|
||||
tasks:
|
||||
- setup: |
|
||||
cd Nim
|
||||
git clone --depth 1 -q https://github.com/nim-lang/csources.git
|
||||
git clone --depth 1 -q https://github.com/nim-lang/csources_v1.git csources
|
||||
gmake -C csources -j $(sysctl -n hw.ncpuonline)
|
||||
bin/nim c koch
|
||||
echo 'export PATH=$HOME/Nim/bin:$PATH' >> $HOME/.buildenv
|
||||
|
||||
@@ -18,7 +18,7 @@ environment:
|
||||
tasks:
|
||||
- setup: |
|
||||
cd Nim
|
||||
git clone --depth 1 -q https://github.com/nim-lang/csources.git
|
||||
git clone --depth 1 -q https://github.com/nim-lang/csources_v1.git csources
|
||||
gmake -C csources -j $(sysctl -n hw.ncpuonline)
|
||||
bin/nim c koch
|
||||
echo 'export PATH=$HOME/Nim/bin:$PATH' >> $HOME/.buildenv
|
||||
|
||||
@@ -18,7 +18,7 @@ environment:
|
||||
tasks:
|
||||
- setup: |
|
||||
cd Nim
|
||||
git clone --depth 1 -q https://github.com/nim-lang/csources.git
|
||||
git clone --depth 1 -q https://github.com/nim-lang/csources_v1.git csources
|
||||
gmake -C csources -j $(sysctl -n hw.ncpuonline)
|
||||
bin/nim c koch
|
||||
echo 'export PATH=$HOME/Nim/bin:$PATH' >> $HOME/.buildenv
|
||||
|
||||
4
.github/workflows/ci.yml.disabled
vendored
4
.github/workflows/ci.yml.disabled
vendored
@@ -85,11 +85,11 @@ jobs:
|
||||
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
|
||||
7z x dist/mingw64.7z -odist
|
||||
7z x dist/dlls.zip -obin
|
||||
echo "::add-path::${{ github.workspace }}/dist/mingw64/bin"
|
||||
echo "${{ github.workspace }}/dist/mingw64/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'Add build binaries to PATH'
|
||||
shell: bash
|
||||
run: echo "::add-path::${{ github.workspace }}/bin"
|
||||
run: echo "${{ github.workspace }}/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'Build csources'
|
||||
shell: bash
|
||||
|
||||
8
.github/workflows/ci_docs.yml
vendored
8
.github/workflows/ci_docs.yml
vendored
@@ -64,17 +64,17 @@ jobs:
|
||||
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
|
||||
7z x dist/mingw64.7z -odist
|
||||
7z x dist/dlls.zip -obin
|
||||
echo "::add-path::${{ github.workspace }}/dist/mingw64/bin"
|
||||
echo "${{ github.workspace }}/dist/mingw64/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'Add build binaries to PATH'
|
||||
shell: bash
|
||||
run: echo "::add-path::${{ github.workspace }}/bin"
|
||||
run: echo "${{ github.workspace }}/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'Get current csources version'
|
||||
id: csources-version
|
||||
shell: bash
|
||||
run: |
|
||||
sha=$(git ls-remote https://github.com/nim-lang/csources master | cut -f 1)
|
||||
sha=$(git ls-remote https://github.com/nim-lang/csources_v1 master | cut -f 1)
|
||||
echo "::set-output name=sha::$sha"
|
||||
|
||||
- name: 'Get prebuilt csources from cache'
|
||||
@@ -88,7 +88,7 @@ jobs:
|
||||
if: steps.csources-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: nim-lang/csources
|
||||
repository: nim-lang/csources_v1
|
||||
path: csources
|
||||
|
||||
- name: 'Build 1-stage compiler from csources'
|
||||
|
||||
4
.github/workflows/ci_packages.yml
vendored
4
.github/workflows/ci_packages.yml
vendored
@@ -48,11 +48,11 @@ jobs:
|
||||
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
|
||||
7z x dist/mingw64.7z -odist
|
||||
7z x dist/dlls.zip -obin
|
||||
echo "::add-path::${{ github.workspace }}/dist/mingw64/bin"
|
||||
echo "${{ github.workspace }}/dist/mingw64/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'Add build binaries to PATH'
|
||||
shell: bash
|
||||
run: echo "::add-path::${{ github.workspace }}/bin"
|
||||
run: echo "${{ github.workspace }}/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'Build csources'
|
||||
shell: bash
|
||||
|
||||
4
.github/workflows/ci_ssl.yml
vendored
4
.github/workflows/ci_ssl.yml
vendored
@@ -49,11 +49,11 @@ jobs:
|
||||
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
|
||||
7z x dist/mingw64.7z -odist
|
||||
7z x dist/dlls.zip -obin
|
||||
echo "::add-path::${{ github.workspace }}/dist/mingw64/bin"
|
||||
echo "${{ github.workspace }}/dist/mingw64/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'Add build binaries to PATH'
|
||||
shell: bash
|
||||
run: echo "::add-path::${{ github.workspace }}/bin"
|
||||
run: echo "${{ github.workspace }}/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'Build 1-stage compiler from csources'
|
||||
shell: bash
|
||||
|
||||
@@ -22,7 +22,7 @@ addons:
|
||||
- valgrind
|
||||
|
||||
before_script:
|
||||
- git clone --depth 1 https://github.com/nim-lang/csources.git
|
||||
- git clone --depth 1 https://github.com/nim-lang/csources_v1.git csources
|
||||
- export PATH="$PWD/bin${PATH:+:$PATH}"
|
||||
- make -C csources -j 2 LD=$CC ucpu=$CPU
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
- checkout: self
|
||||
fetchDepth: 1
|
||||
|
||||
- bash: git clone --depth 1 https://github.com/nim-lang/csources
|
||||
- bash: git clone --depth 1 https://github.com/nim-lang/csources_v1 csources
|
||||
displayName: 'Checkout Nim csources'
|
||||
|
||||
- task: NodeTool@0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@echo off
|
||||
rem build development version of the compiler; can be rerun safely
|
||||
if not exist csources (
|
||||
git clone --depth 1 https://github.com/nim-lang/csources.git
|
||||
git clone --depth 1 https://github.com/nim-lang/csources_v1.git csources
|
||||
)
|
||||
if not exist bin\nim.exe (
|
||||
cd csources
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#! /bin/sh
|
||||
|
||||
# build development version of the compiler; can be rerun safely.
|
||||
# arguments can be passed, eg `--os freebsd`
|
||||
# arguments can be passed, e.g. `--os freebsd`
|
||||
|
||||
set -u # error on undefined variables
|
||||
set -e # exit on first error
|
||||
@@ -11,7 +11,7 @@ echo_run(){
|
||||
"$@"
|
||||
}
|
||||
|
||||
[ -d csources ] || echo_run git clone -q --depth 1 https://github.com/nim-lang/csources.git
|
||||
[ -d csources ] || echo_run git clone -q --depth 1 https://github.com/nim-lang/csources_v1.git csources
|
||||
|
||||
nim_csources=bin/nim_csources
|
||||
|
||||
@@ -24,7 +24,7 @@ build_nim_csources(){
|
||||
# avoid changing dir in case of failure
|
||||
(
|
||||
if [ $# -ne 0 ]; then
|
||||
# some args were passed (eg: `--cpu i386`), need to call build.sh
|
||||
# some args were passed (e.g.: `--cpu i386`), need to call build.sh
|
||||
build_nim_csources_via_script "$@"
|
||||
else
|
||||
# no args, use multiple Make jobs (5X faster on 16 cores: 10s instead of 50s)
|
||||
|
||||
394
changelog.md
394
changelog.md
@@ -1,371 +1,83 @@
|
||||
# v1.4.0 - yyyy-mm-dd
|
||||
# v1.6.x - yyyy-mm-dd
|
||||
|
||||
|
||||
|
||||
## Changes affecting backward compatibility
|
||||
|
||||
- The configuration subsystem now allows for `-d:release` and `-d:danger` to work as expected.
|
||||
The downside is that these defines now have custom logic that doesn't apply for
|
||||
other defines.
|
||||
|
||||
|
||||
## Standard library additions and changes
|
||||
- Added support for parenthesized expressions in `strformat`
|
||||
|
||||
- Added some enhancements to `std/jsonutils` module.
|
||||
* Added a possibility to deserialize JSON arrays directly to `HashSet` and
|
||||
`OrderedSet` types and respectively to serialize those types to JSON arrays
|
||||
via `jsonutils.fromJson` and `jsonutils.toJson` procedures.
|
||||
* Added a possibility to deserialize JSON `null` objects to Nim option objects
|
||||
and respectively to serialize Nim option object to JSON object if `isSome`
|
||||
or to JSON null object if `isNone` via `jsonutils.fromJson` and
|
||||
`jsonutils.toJson` procedures.
|
||||
* Added `Joptions` parameter to `jsonutils.fromJson` procedure currently
|
||||
containing two boolean options `allowExtraKeys` and `allowMissingKeys`.
|
||||
- If `allowExtraKeys` is `true` Nim's object to which the JSON is parsed is
|
||||
not required to have a field for every JSON key.
|
||||
- If `allowMissingKeys` is `true` Nim's object to which JSON is parsed is
|
||||
allowed to have fields without corresponding JSON keys.
|
||||
- Added `bindParams`, `bindParam` to `db_sqlite` for binding parameters into a `SqlPrepared` statement.
|
||||
- Added `tryInsert`,`insert` procs to `db_*` libs accept primary key column name.
|
||||
- Added `xmltree.newVerbatimText` support create `style`'s,`script`'s text.
|
||||
- `uri` adds Data URI Base64, implements RFC-2397.
|
||||
- Added [DOM Parser](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser)
|
||||
to the `dom` module for the JavaScript target.
|
||||
- The default hash for `Ordinal` has changed to something more bit-scrambling.
|
||||
`import hashes; proc hash(x: myInt): Hash = hashIdentity(x)` recovers the old
|
||||
one in an instantiation context while `-d:nimIntHash1` recovers it globally.
|
||||
- `deques.peekFirst` and `deques.peekLast` now have `var Deque[T] -> var T` overloads.
|
||||
- File handles created from high-level abstractions in the stdlib will no longer
|
||||
be inherited by child processes. In particular, these modules are affected:
|
||||
`asyncdispatch`, `asyncnet`, `system`, `nativesockets`, `net` and `selectors`.
|
||||
- Fixed buffer overflow bugs in `net`
|
||||
|
||||
For `asyncdispatch`, `asyncnet`, `net` and `nativesockets`, an `inheritable`
|
||||
flag has been added to all `proc`s that create sockets, allowing the user to
|
||||
control whether the resulting socket is inheritable. This flag is provided to
|
||||
ease the writing of multi-process servers, where sockets inheritance is
|
||||
desired.
|
||||
- Added `sections` iterator in `parsecfg`.
|
||||
|
||||
For a transition period, define `nimInheritHandles` to enable file handle
|
||||
inheritance by default. This flag does **not** affect the `selectors` module
|
||||
due to the differing semantics between operating systems.
|
||||
- Make custom op in macros.quote work for all statements.
|
||||
|
||||
`asyncdispatch.setInheritable`, `system.setInheritable` and
|
||||
`nativesockets.setInheritable` is also introduced for setting file handle or
|
||||
socket inheritance. Not all platform have these `proc`s defined.
|
||||
- On Windows the SSL library now checks for valid certificates.
|
||||
It uses the `cacert.pem` file for this purpose which was extracted
|
||||
from `https://curl.se/ca/cacert.pem`. Besides
|
||||
the OpenSSL DLLs (e.g. libssl-1_1-x64.dll, libcrypto-1_1-x64.dll) you
|
||||
now also need to ship `cacert.pem` with your `.exe` file.
|
||||
|
||||
- The file descriptors created for internal bookkeeping by `ioselector_kqueue`
|
||||
and `ioselector_epoll` will no longer be leaked to child processes.
|
||||
|
||||
- `strutils.formatFloat` with `precision = 0` has been restored to the version
|
||||
1 behaviour that produces a trailing dot, e.g. `formatFloat(3.14159, precision = 0)`
|
||||
is now `3.`, not `3`.
|
||||
- `critbits` adds `commonPrefixLen`.
|
||||
- Make `{.requiresInit.}` pragma to work for `distinct` types.
|
||||
|
||||
- `relativePath(rel, abs)` and `relativePath(abs, rel)` used to silently give wrong results
|
||||
(see #13222); instead they now use `getCurrentDir` to resolve those cases,
|
||||
and this can now throw in edge cases where `getCurrentDir` throws.
|
||||
`relativePath` also now works for js with `-d:nodejs`.
|
||||
- Added a macros `enumLen` for returning the number of items in an enum to the
|
||||
`typetraits.nim` module.
|
||||
|
||||
- JavaScript and NimScript standard library changes: `streams.StringStream` is
|
||||
now supported in JavaScript, with the limitation that any buffer `pointer`s
|
||||
used must be castable to `ptr string`, any incompatible pointer type will not
|
||||
work. The `lexbase` and `streams` modules used to fail to compile on
|
||||
NimScript due to a bug, but this has been fixed.
|
||||
- `prelude` now works with the JavaScript target.
|
||||
|
||||
The following modules now compile on both JS and NimScript: `parsecsv`,
|
||||
`parsecfg`, `parsesql`, `xmlparser`, `htmlparser` and `ropes`. Additionally
|
||||
supported for JS is `cstrutils.startsWith` and `cstrutils.endsWith`, for
|
||||
NimScript: `json`, `parsejson`, `strtabs` and `unidecode`.
|
||||
- Added `ioutils` module containing `duplicate` and `duplicateTo` to duplicate `FileHandle` using C function `dup` and `dup2`.
|
||||
|
||||
- Added `streams.readStr` and `streams.peekStr` overloads to
|
||||
accept an existing string to modify, which avoids memory
|
||||
allocations, similar to `streams.readLine` (#13857).
|
||||
- The JSON module can now handle integer literals and floating point literals of arbitrary length and precision.
|
||||
Numbers that do not fit the underlying `BiggestInt` or `BiggestFloat` fields are kept as string literals and
|
||||
one can use external BigNum libraries to handle these. The `parseFloat` family of functions also has now optional
|
||||
`rawIntegers` and `rawFloats` parameters that can be used to enforce that all integer or float literals remain
|
||||
in the "raw" string form so that client code can easily treat small and large numbers uniformly.
|
||||
|
||||
- Added high-level `asyncnet.sendTo` and `asyncnet.recvFrom` UDP functionality.
|
||||
- Added `randState` template that exposes the default random number generator. Useful for library authors.
|
||||
|
||||
- `dollars.$` now works for unsigned ints with `nim js`
|
||||
- Added `asyncdispatch.activeDescriptors` that returns the number of currently
|
||||
active async event handles/file descriptors
|
||||
|
||||
- Improvements to the `bitops` module, including bitslices, non-mutating versions
|
||||
of the original masking functions, `mask`/`masked`, and varargs support for
|
||||
`bitand`, `bitor`, and `bitxor`.
|
||||
|
||||
- `sugar.=>` and `sugar.->` changes: Previously `(x, y: int)` was transformed
|
||||
into `(x: auto, y: int)`, it now becomes `(x: int, y: int)` in consistency
|
||||
with regular proc definitions (although you cannot use semicolons).
|
||||
|
||||
Pragmas and using a name are now allowed on the lefthand side of `=>`. Here
|
||||
is an aggregate example of these changes:
|
||||
```nim
|
||||
import sugar
|
||||
|
||||
foo(x, y: int) {.noSideEffect.} => x + y
|
||||
|
||||
# is transformed into
|
||||
|
||||
proc foo(x: int, y: int): auto {.noSideEffect.} = x + y
|
||||
```
|
||||
|
||||
- The fields of `times.DateTime` are now private, and are accessed with getters and deprecated setters.
|
||||
|
||||
- The `times` module now handles the default value for `DateTime` more consistently.
|
||||
Most procs raise an assertion error when given
|
||||
an uninitialized `DateTime`, the exceptions are `==` and `$` (which returns `"Uninitialized DateTime"`).
|
||||
The proc `times.isInitialized` has been added which can be used to check if
|
||||
a `DateTime` has been initialized.
|
||||
|
||||
- Fix a bug where calling `close` on io streams in osproc.startProcess was a noop and led to
|
||||
hangs if a process had both reads from stdin and writes (eg to stdout).
|
||||
|
||||
- The callback that is passed to `system.onThreadDestruction` must now be `.raises: []`.
|
||||
- The callback that is assigned to `system.onUnhandledException` must now be `.gcsafe`.
|
||||
|
||||
- `osproc.execCmdEx` now takes an optional `input` for stdin, `workingDir` and `env`
|
||||
parameters.
|
||||
|
||||
- Added a `ssl_config` module containing lists of secure ciphers as recommended by
|
||||
[Mozilla OpSec](https://wiki.mozilla.org/Security/Server_Side_TLS)
|
||||
|
||||
- `net.newContext` now defaults to the list of ciphers targeting
|
||||
["Intermediate compatibility"](https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29)
|
||||
per Mozilla's recommendation instead of `ALL`. This change should protect
|
||||
users from the use of weak and insecure ciphers while still provides
|
||||
adequate compatibility with the majority of the Internet.
|
||||
|
||||
- A new module `std/jsonutils` with hookable `jsonTo,toJson,fromJson` operations for json
|
||||
serialization/deserialization of custom types was added.
|
||||
|
||||
- A new proc `heapqueue.find[T](heap: HeapQueue[T], x: T): int` to get index of element ``x``
|
||||
was added.
|
||||
- Added `rstgen.rstToLatex` convenience proc for `renderRstToOut` and `initRstGenerator`
|
||||
with `outLatex` output.
|
||||
- Added `os.normalizeExe`, e.g.: `koch` => `./koch`.
|
||||
- `macros.newLit` now preserves named vs unnamed tuples; use `-d:nimHasWorkaround14720`
|
||||
to keep old behavior.
|
||||
- Added `random.gauss`, that uses the ratio of uniforms method of sampling from a Gaussian distribution.
|
||||
- Added `typetraits.elementType` to get element type of an iterable.
|
||||
- `typetraits.$` changes: `$(int,)` is now `"(int,)"` instead of `"(int)"`;
|
||||
`$tuple[]` is now `"tuple[]"` instead of `"tuple"`;
|
||||
`$((int, float), int)` is now `"((int, float), int)"` instead of `"(tuple of (int, float), int)"`
|
||||
- Added `macros.extractDocCommentsAndRunnables` helper
|
||||
|
||||
- `strformat.fmt` and `strformat.&` support `= specifier`. `fmt"{expr=}"` now
|
||||
expands to `fmt"expr={expr}"`.
|
||||
- deprecations: `os.existsDir` => `dirExists`, `os.existsFile` => `fileExists`
|
||||
|
||||
- Added `jsre` module, [Regular Expressions for the JavaScript target.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
|
||||
- Made `maxLines` argument `Positive` in `logging.newRollingFileLogger`,
|
||||
because negative values will result in a new file being created for each logged
|
||||
line which doesn't make sense.
|
||||
- Changed `log` in `logging` to use proper log level on JavaScript target,
|
||||
e.g. `debug` uses `console.debug`, `info` uses `console.info`, `warn` uses `console.warn`, etc.
|
||||
- Tables, HashSets, SharedTables and deques don't require anymore that the passed
|
||||
initial size must be a power of two - this is done internally.
|
||||
Proc `rightSize` for Tables and HashSets is deprecated, as it is not needed anymore.
|
||||
`CountTable.inc` takes `val: int` again not `val: Positive`; I.e. it can "count down" again.
|
||||
- Removed deprecated symbols from `macros` module, deprecated as far back as `0.15`.
|
||||
- Removed `sugar.distinctBase`, deprecated since `0.19`.
|
||||
- Export `asyncdispatch.PDispatcher.handles` so that an external library can register them.
|
||||
|
||||
- `std/with`, `sugar.dup` now support object field assignment expression:
|
||||
```nim
|
||||
import std/with
|
||||
|
||||
type Foo = object
|
||||
x, y: int
|
||||
|
||||
var foo = Foo()
|
||||
with foo:
|
||||
x = 10
|
||||
y = 20
|
||||
|
||||
echo foo
|
||||
```
|
||||
|
||||
- Proc `math.round` is no longer deprecated. The advice to use `strformat` instead
|
||||
cannot be applied to every use case. The limitations and the (lack of) reliability
|
||||
of `round` are well documented.
|
||||
|
||||
- Added `getprotobyname` to `winlean`. Added `getProtoByname` to `nativesockets` which returns a protocol code
|
||||
from the database that matches the protocol `name`.
|
||||
|
||||
- Added missing attributes and methods to `dom.Navigator` like `deviceMemory`, `onLine`, `vibrate()`, etc.
|
||||
|
||||
- Added `strutils.indentation` and `strutils.dedent` which enable indented string literals:
|
||||
```nim
|
||||
import strutils
|
||||
echo dedent """
|
||||
This
|
||||
is
|
||||
cool!
|
||||
"""
|
||||
```
|
||||
|
||||
- Added `initUri(isIpv6: bool)` to `uri` module, now `uri` supports parsing ipv6 hostname.
|
||||
|
||||
- Added `readLines(p: Process)` to `osproc` module for `startProcess` convenience.
|
||||
|
||||
- Added the below `to` procs for collections. The usage is similar to procs such as
|
||||
`sets.toHashSet` and `tables.toTable`. Previously, it was necessary to create the
|
||||
respective empty collection and add items manually.
|
||||
* `critbits.toCritBitTree`, which creates a `CritBitTree` from an `openArray` of
|
||||
items or an `openArray` of pairs.
|
||||
* `deques.toDeque`, which creates a `Deque` from an `openArray`.
|
||||
* `heapqueue.toHeapQueue`, which creates a `HeapQueue` from an `openArray`.
|
||||
* `intsets.toIntSet`, which creates an `IntSet` from an `openArray`.
|
||||
|
||||
- Added `progressInterval` argument to `asyncftpclient.newAsyncFtpClient` to control the interval
|
||||
at which progress callbacks are called.
|
||||
|
||||
- Added `os.copyFileToDir`
|
||||
- Fixed premature garbage collection in asyncdispatch, when a stack trace override is in place.
|
||||
|
||||
## Language changes
|
||||
|
||||
- The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts
|
||||
`wasMoved` calls where needed.
|
||||
- The `=` hook is now called `=copy` for clarity. The old name `=` is still available so there
|
||||
is no need to update your code. This change was backported to 1.2 too so you can use the
|
||||
more readability `=copy` without loss of compatibility.
|
||||
- `nimscript` now handles `except Exception as e`
|
||||
|
||||
- In the newruntime it is now allowed to assign to the discriminator field
|
||||
without restrictions as long as case object doesn't have custom destructor.
|
||||
The discriminator value doesn't have to be a constant either. If you have a
|
||||
custom destructor for a case object and you do want to freely assign discriminator
|
||||
fields, it is recommended to refactor object into 2 objects like this:
|
||||
- The `cstring` doesn't support `[]=` operator in JS backend.
|
||||
|
||||
```nim
|
||||
type
|
||||
MyObj = object
|
||||
case kind: bool
|
||||
of true: y: ptr UncheckedArray[float]
|
||||
of false: z: seq[int]
|
||||
|
||||
proc `=destroy`(x: MyObj) =
|
||||
if x.kind and x.y != nil:
|
||||
deallocShared(x.y)
|
||||
```
|
||||
Refactor into:
|
||||
```nim
|
||||
type
|
||||
MySubObj = object
|
||||
val: ptr UncheckedArray[float]
|
||||
MyObj = object
|
||||
case kind: bool
|
||||
of true: y: MySubObj
|
||||
of false: z: seq[int]
|
||||
|
||||
proc `=destroy`(x: MySubObj) =
|
||||
if x.val != nil:
|
||||
deallocShared(x.val)
|
||||
```
|
||||
- `getImpl` on enum type symbols now returns field syms instead of idents. This helps
|
||||
with writing typed macros. Old behavior for backwards compatibility can be restored
|
||||
with `--useVersion:1.0`.
|
||||
- The typed AST for proc headers will now have the arguments be syms instead of idents.
|
||||
This helps with writing typed macros. Old behaviour for backwards compatibility can
|
||||
be restored with `--useVersion:1.0`.
|
||||
- ``let`` statements can now be used without a value if declared with
|
||||
``importc``/``importcpp``/``importjs``/``importobjc``.
|
||||
- The keyword `from` is now usable as an operator.
|
||||
- Exceptions inheriting from `system.Defect` are no longer tracked with
|
||||
the `.raises: []` exception tracking mechanism. This is more consistent with the
|
||||
built-in operations. The following always used to compile (and still does):
|
||||
|
||||
```nim
|
||||
|
||||
proc mydiv(a, b): int {.raises: [].} =
|
||||
a div b # can raise an DivByZeroDefect
|
||||
|
||||
```
|
||||
|
||||
Now also this compiles:
|
||||
|
||||
```nim
|
||||
|
||||
proc mydiv(a, b): int {.raises: [].} =
|
||||
if b == 0: raise newException(DivByZeroDefect, "division by zero")
|
||||
else: result = a div b
|
||||
|
||||
```
|
||||
|
||||
The reason for this is that `DivByZeroDefect` inherits from `Defect` and
|
||||
with `--panics:on` `Defects` become unrecoverable errors.
|
||||
|
||||
- Added the `thiscall` calling convention as specified by Microsoft, mostly for hooking purposes.
|
||||
- Deprecated `{.unroll.}` pragma, was ignored by the compiler anyways, was a nop.
|
||||
- Removed `strutils.isNilOrWhitespace`, was deprecated.
|
||||
- Removed `sharedtables.initSharedTable`, was deprecated and produces undefined behavior.
|
||||
- Removed `asyncdispatch.newAsyncNativeSocket`, was deprecated since `0.18`.
|
||||
- Removed `dom.releaseEvents` and `dom.captureEvents`, was deprecated.
|
||||
|
||||
- Removed `sharedlists.initSharedList`, was deprecated and produces undefined behaviour.
|
||||
|
||||
- There is a new experimental feature called "strictFuncs" which makes the definition of
|
||||
`.noSideEffect` stricter. [See](manual_experimental.html#stricts-funcs)
|
||||
for more information.
|
||||
|
||||
- "for-loop macros" (see [the manual](manual.html#macros-for-loop-macros)) are no longer
|
||||
an experimental feature. In other words, you don't have to write pragma
|
||||
`{.experimental: "forLoopMacros".}` if you want to use them.
|
||||
|
||||
- Added a ``.noalias`` pragma. It is mapped to C's ``restrict`` keyword for the increased
|
||||
performance this keyword can enable.
|
||||
|
||||
- `items` no longer compiles with enum with holes as its behavior was error prone, see #14004
|
||||
- `system.deepcopy` has to be enabled explicitly for `--gc:arc` and `--gc:orc` via
|
||||
`--deepcopy:on`.
|
||||
|
||||
- Added a `std/effecttraits` module for introspection of the inferred effects.
|
||||
We hope this enables `async` macros that are precise about the possible exceptions that
|
||||
can be raised.
|
||||
- The pragma blocks `{.gcsafe.}: ...` and `{.noSideEffect.}: ...` can now also be
|
||||
written as `{.cast(gcsafe).}: ...` and `{.cast(noSideEffect).}: ...`. This is the new
|
||||
preferred way of writing these, emphasizing their unsafe nature.
|
||||
|
||||
|
||||
## Compiler changes
|
||||
|
||||
- Specific warnings can now be turned into errors via `--warningAsError[X]:on|off`.
|
||||
- The `define` and `undef` pragmas have been de-deprecated.
|
||||
- New command: `nim r main.nim [args...]` which compiles and runs main.nim, and implies `--usenimcache`
|
||||
so that output is saved to $nimcache/main$exeExt, using the same logic as `nim c -r` to
|
||||
avoid recompiling when sources don't change. This is now the preferred way to
|
||||
run tests, avoiding the usual pain of clobbering your repo with binaries or
|
||||
using tricky gitignore rules on posix. Example:
|
||||
```nim
|
||||
nim r compiler/nim.nim --help # only compiled the first time
|
||||
echo 'import os; echo getCurrentCompilerExe()' | nim r - # this works too
|
||||
nim r compiler/nim.nim --fullhelp # no recompilation
|
||||
nim r --nimcache:/tmp main # binary saved to /tmp/main
|
||||
```
|
||||
- `--hint:processing` is now supported and means `--hint:processing:on`
|
||||
(likewise with other hints and warnings), which is consistent with all other bool flags.
|
||||
(since 1.3.3).
|
||||
- `nim doc -r main` and `nim rst2html -r main` now call `openDefaultBrowser`.
|
||||
- new hint: `--hint:msgOrigin` will show where a compiler msg (hint|warning|error)
|
||||
was generated; this helps in particular when it's non obvious where it came from
|
||||
either because multiple locations generate the same message, or because the
|
||||
message involves runtime formatting.
|
||||
- new flag `--backend:js|c|cpp|objc` (or -b:js etc), to change backend; can be
|
||||
used with any command (eg nim r, doc, check etc); safe to re-assign.
|
||||
- new flag `--doccmd:cmd` to pass additional flags for runnableExamples,
|
||||
e.g.: `--doccmd:-d:foo --threads`
|
||||
use `--doccmd:skip` to skip runnableExamples and rst test snippets.
|
||||
- new flag `--usenimcache` to output to nimcache (whatever it resolves to after
|
||||
all commands are processed)
|
||||
and avoids polluting both $pwd and $projectdir. It can be used with any command.
|
||||
- `runnableExamples "-b:cpp -r:off": code` is now supported, allowing to override
|
||||
how an example is compiled and run, for example to change backend or compile only.
|
||||
- `nim doc` now outputs under `$projectPath/htmldocs` when `--outdir` is unspecified
|
||||
(with or without `--project`); passing `--project` now automatically generates
|
||||
an index and enables search.
|
||||
See [docgen](docgen.html#introduction-quick-start) for details.
|
||||
- Removed the `--oldNewlines` switch.
|
||||
- Removed the `--laxStrings` switch for mutating the internal zero terminator on strings.
|
||||
- Removed the `--oldast` switch.
|
||||
- Removed the `--oldgensym` switch
|
||||
- `$getType(untyped)` is now "untyped" instead of "expr", `$getType(typed)` is
|
||||
now "typed" instead of "stmt".
|
||||
- Sink inference is now disabled per default and has to enabled explicitly via
|
||||
`--sinkInference:on`. *Note*: For the standard library sink inference remains
|
||||
enabled. This change is most relevant for the `--gc:arc`, `--gc:orc` memory
|
||||
management modes.
|
||||
|
||||
|
||||
- Added `unsafeIsolate` and `extract` to `std/isolation`.
|
||||
|
||||
- `--hint:CC` now goes to stderr (like all other hints) instead of stdout.
|
||||
|
||||
- json build instructions are now generated in `$nimcache/outFileBasename.json`
|
||||
instead of `$nimcache/projectName.json`. This allows avoiding recompiling a given project
|
||||
compiled with different options if the output file differs.
|
||||
|
||||
- `--usenimcache` (implied by `nim r main`) now generates an output file that includes a hash of
|
||||
some of the compilation options, which allows caching generated binaries:
|
||||
nim r main # recompiles
|
||||
nim r -d:foo main # recompiles
|
||||
nim r main # uses cached binary
|
||||
nim r main arg1 arg2 # ditto (runtime arguments are irrelevant)
|
||||
|
||||
- The style checking of the compiler now supports a `--styleCheck:usages` switch. This switch
|
||||
enforces that every symbol is written as it was declared, not enforcing
|
||||
the official Nim style guide. To be enabled, this has to be combined either
|
||||
with `--styleCheck:error` or `--styleCheck:hint`.
|
||||
|
||||
## Tool changes
|
||||
|
||||
- `nimsuggest` will now return both the forward declaration and the
|
||||
implementation location upon a `def` query. Previously the behavior was
|
||||
just to return the forward declaration.
|
||||
|
||||
874
changelogs/changelog_1_4_0.md
Normal file
874
changelogs/changelog_1_4_0.md
Normal file
@@ -0,0 +1,874 @@
|
||||
# v1.4.0 - 2020-10-16
|
||||
|
||||
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
- Added some enhancements to `std/jsonutils` module.
|
||||
* Added a possibility to deserialize JSON arrays directly to `HashSet` and
|
||||
`OrderedSet` types and respectively to serialize those types to JSON arrays
|
||||
via `jsonutils.fromJson` and `jsonutils.toJson` procedures.
|
||||
* Added a possibility to deserialize JSON `null` objects to Nim option objects
|
||||
and respectively to serialize Nim option object to JSON object if `isSome`
|
||||
or to JSON null object if `isNone` via `jsonutils.fromJson` and
|
||||
`jsonutils.toJson` procedures.
|
||||
* Added a `Joptions` parameter to `jsonutils.fromJson` currently
|
||||
containing two boolean options `allowExtraKeys` and `allowMissingKeys`.
|
||||
- If `allowExtraKeys` is `true` Nim's object to which the JSON is parsed is
|
||||
not required to have a field for every JSON key.
|
||||
- If `allowMissingKeys` is `true` Nim's object to which JSON is parsed is
|
||||
allowed to have fields without corresponding JSON keys.
|
||||
- Added `bindParams`, `bindParam` to `db_sqlite` for binding parameters into a `SqlPrepared` statement.
|
||||
- Added `tryInsert`,`insert` procs to `db_*` libs which accept primary key column name.
|
||||
- Added `xmltree.newVerbatimText` support create `style`'s,`script`'s text.
|
||||
- `uri` module now implements RFC-2397.
|
||||
- Added [DOM Parser](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser)
|
||||
to the `dom` module for the JavaScript target.
|
||||
- The default hash for `Ordinal` has changed to something more bit-scrambling.
|
||||
`import hashes; proc hash(x: myInt): Hash = hashIdentity(x)` recovers the old
|
||||
one in an instantiation context while `-d:nimIntHash1` recovers it globally.
|
||||
- `deques.peekFirst` and `deques.peekLast` now have `var Deque[T] -> var T` overloads.
|
||||
- File handles created from high-level abstractions in the stdlib will no longer
|
||||
be inherited by child processes. In particular, these modules are affected:
|
||||
`asyncdispatch`, `asyncnet`, `system`, `nativesockets`, `net` and `selectors`.
|
||||
|
||||
For `asyncdispatch`, `asyncnet`, `net` and `nativesockets`, an `inheritable`
|
||||
flag has been added to all `proc`s that create sockets, allowing the user to
|
||||
control whether the resulting socket is inheritable. This flag is provided to
|
||||
ease the writing of multi-process servers, where sockets inheritance is
|
||||
desired.
|
||||
|
||||
For a transition period, define `nimInheritHandles` to enable file handle
|
||||
inheritance by default. This flag does **not** affect the `selectors` module
|
||||
due to the differing semantics between operating systems.
|
||||
|
||||
`asyncdispatch.setInheritable`, `system.setInheritable` and
|
||||
`nativesockets.setInheritable` are also introduced for setting file handle or
|
||||
socket inheritance. Not all platforms have these `proc`s defined.
|
||||
|
||||
- The file descriptors created for internal bookkeeping by `ioselector_kqueue`
|
||||
and `ioselector_epoll` will no longer be leaked to child processes.
|
||||
|
||||
- `strutils.formatFloat` with `precision = 0` has been restored to the version
|
||||
1 behaviour that produces a trailing dot, e.g. `formatFloat(3.14159, precision = 0)`
|
||||
is now `3.`, not `3`.
|
||||
- Added `commonPrefixLen` to `critbits`.
|
||||
|
||||
- `relativePath(rel, abs)` and `relativePath(abs, rel)` used to silently give wrong results
|
||||
(see #13222); instead they now use `getCurrentDir` to resolve those cases,
|
||||
and this can now throw in edge cases where `getCurrentDir` throws.
|
||||
`relativePath` also now works for js with `-d:nodejs`.
|
||||
|
||||
- JavaScript and NimScript standard library changes: `streams.StringStream` is
|
||||
now supported in JavaScript, with the limitation that any buffer `pointer`s
|
||||
used must be castable to `ptr string`, any incompatible pointer type will not
|
||||
work. The `lexbase` and `streams` modules used to fail to compile on
|
||||
NimScript due to a bug, but this has been fixed.
|
||||
|
||||
The following modules now compile on both JS and NimScript: `parsecsv`,
|
||||
`parsecfg`, `parsesql`, `xmlparser`, `htmlparser` and `ropes`. Additionally
|
||||
supported for JS is `cstrutils.startsWith` and `cstrutils.endsWith`, for
|
||||
NimScript: `json`, `parsejson`, `strtabs` and `unidecode`.
|
||||
|
||||
- Added `streams.readStr` and `streams.peekStr` overloads to
|
||||
accept an existing string to modify, which avoids memory
|
||||
allocations, similar to `streams.readLine` (#13857).
|
||||
|
||||
- Added high-level `asyncnet.sendTo` and `asyncnet.recvFrom` UDP functionality.
|
||||
|
||||
- `dollars.$` now works for unsigned ints with `nim js`.
|
||||
|
||||
- Improvements to the `bitops` module, including bitslices, non-mutating versions
|
||||
of the original masking functions, `mask`/`masked`, and varargs support for
|
||||
`bitand`, `bitor`, and `bitxor`.
|
||||
|
||||
- `sugar.=>` and `sugar.->` changes: Previously `(x, y: int)` was transformed
|
||||
into `(x: auto, y: int)`, it now becomes `(x: int, y: int)` for consistency
|
||||
with regular proc definitions (although you cannot use semicolons).
|
||||
|
||||
Pragmas and using a name are now allowed on the lefthand side of `=>`. Here
|
||||
is an example of these changes:
|
||||
```nim
|
||||
import sugar
|
||||
|
||||
foo(x, y: int) {.noSideEffect.} => x + y
|
||||
|
||||
# is transformed into
|
||||
|
||||
proc foo(x: int, y: int): auto {.noSideEffect.} = x + y
|
||||
```
|
||||
|
||||
- The fields of `times.DateTime` are now private, and are accessed with getters and deprecated setters.
|
||||
|
||||
- The `times` module now handles the default value for `DateTime` more consistently.
|
||||
Most procs raise an assertion error when given
|
||||
an uninitialized `DateTime`, the exceptions are `==` and `$` (which returns `"Uninitialized DateTime"`).
|
||||
The proc `times.isInitialized` has been added which can be used to check if
|
||||
a `DateTime` has been initialized.
|
||||
|
||||
- Fix a bug where calling `close` on io streams in `osproc.startProcess` was a noop and led to
|
||||
hangs if a process had both reads from stdin and writes (e.g. to stdout).
|
||||
|
||||
- The callback that is passed to `system.onThreadDestruction` must now be `.raises: []`.
|
||||
- The callback that is assigned to `system.onUnhandledException` must now be `.gcsafe`.
|
||||
|
||||
- `osproc.execCmdEx` now takes an optional `input` for stdin, `workingDir` and `env`
|
||||
parameters.
|
||||
|
||||
- Added a `ssl_config` module containing lists of secure ciphers as recommended by
|
||||
[Mozilla OpSec](https://wiki.mozilla.org/Security/Server_Side_TLS)
|
||||
|
||||
- `net.newContext` now defaults to the list of ciphers targeting
|
||||
["Intermediate compatibility"](https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29)
|
||||
per Mozilla's recommendation instead of `ALL`. This change should protect
|
||||
users from the use of weak and insecure ciphers while still provides
|
||||
adequate compatibility with the majority of the Internet.
|
||||
|
||||
- A new module `std/jsonutils` with hookable `jsonTo,toJson,fromJson` operations for json
|
||||
serialization/deserialization of custom types was added.
|
||||
|
||||
- A new proc `heapqueue.find[T](heap: HeapQueue[T], x: T): int` to get index of element ``x``
|
||||
was added.
|
||||
- Added `rstgen.rstToLatex` a convenience proc for `renderRstToOut` and `initRstGenerator`.
|
||||
- Added `os.normalizeExe`.
|
||||
- `macros.newLit` now preserves named vs unnamed tuples.
|
||||
- Added `random.gauss`, that uses the ratio of uniforms method of sampling from a Gaussian distribution.
|
||||
- Added `typetraits.elementType` to get the element type of an iterable.
|
||||
- `typetraits.$` changes: `$(int,)` is now `"(int,)"` instead of `"(int)"`;
|
||||
`$tuple[]` is now `"tuple[]"` instead of `"tuple"`;
|
||||
`$((int, float), int)` is now `"((int, float), int)"` instead of `"(tuple of (int, float), int)"`
|
||||
- Added `macros.extractDocCommentsAndRunnables` helper.
|
||||
|
||||
- `strformat.fmt` and `strformat.&` support `specifier =`. `fmt"{expr=}"` now
|
||||
expands to `fmt"expr={expr}"`.
|
||||
- Deprecations: instead of `os.existsDir` use `dirExists`, instead of `os.existsFile` use `fileExists`.
|
||||
|
||||
- Added the `jsre` module, [Regular Expressions for the JavaScript target.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions).
|
||||
- Made `maxLines` argument `Positive` in `logging.newRollingFileLogger`,
|
||||
because negative values will result in a new file being created for each logged
|
||||
line which doesn't make sense.
|
||||
- Changed `log` in `logging` to use proper log level for JavaScript,
|
||||
e.g. `debug` uses `console.debug`, `info` uses `console.info`, `warn` uses `console.warn`, etc.
|
||||
- Tables, HashSets, SharedTables and deques don't require anymore that the passed
|
||||
initial size must be a power of two - this is done internally.
|
||||
Proc `rightSize` for Tables and HashSets is deprecated, as it is not needed anymore.
|
||||
`CountTable.inc` takes `val: int` again not `val: Positive`; i.e. it can "count down" again.
|
||||
- Removed deprecated symbols from `macros` module, some of which were deprecated already in `0.15`.
|
||||
- Removed `sugar.distinctBase`, deprecated since `0.19`. Use `typetraits.distinctBase`.
|
||||
- `asyncdispatch.PDispatcher.handles` is exported so that an external low-level libraries can access it.
|
||||
|
||||
- `std/with`, `sugar.dup` now support object field assignment expressions:
|
||||
```nim
|
||||
import std/with
|
||||
|
||||
type Foo = object
|
||||
x, y: int
|
||||
|
||||
var foo = Foo()
|
||||
with foo:
|
||||
x = 10
|
||||
y = 20
|
||||
|
||||
echo foo
|
||||
```
|
||||
|
||||
- Proc `math.round` is no longer deprecated. The advice to use `strformat` instead
|
||||
cannot be applied to every use case. The limitations and the (lack of) reliability
|
||||
of `round` are well documented.
|
||||
|
||||
- Added `getprotobyname` to `winlean`. Added `getProtoByname` to `nativesockets` which returns a protocol code
|
||||
from the database that matches the protocol `name`.
|
||||
|
||||
- Added missing attributes and methods to `dom.Navigator` like `deviceMemory`, `onLine`, `vibrate()`, etc.
|
||||
|
||||
- Added `strutils.indentation` and `strutils.dedent` which enable indented string literals:
|
||||
```nim
|
||||
import strutils
|
||||
echo dedent """
|
||||
This
|
||||
is
|
||||
cool!
|
||||
"""
|
||||
```
|
||||
|
||||
- Added `initUri(isIpv6: bool)` to `uri` module, now `uri` supports parsing ipv6 hostname.
|
||||
|
||||
- Added `readLines(p: Process)` to `osproc`.
|
||||
|
||||
- Added the below `toX` procs for collections. The usage is similar to procs such as
|
||||
`sets.toHashSet` and `tables.toTable`. Previously, it was necessary to create the
|
||||
respective empty collection and add items manually.
|
||||
* `critbits.toCritBitTree`, which creates a `CritBitTree` from an `openArray` of
|
||||
items or an `openArray` of pairs.
|
||||
* `deques.toDeque`, which creates a `Deque` from an `openArray`.
|
||||
* `heapqueue.toHeapQueue`, which creates a `HeapQueue` from an `openArray`.
|
||||
* `intsets.toIntSet`, which creates an `IntSet` from an `openArray`.
|
||||
|
||||
- Added `progressInterval` argument to `asyncftpclient.newAsyncFtpClient` to control the interval
|
||||
at which progress callbacks are called.
|
||||
|
||||
- Added `os.copyFileToDir`.
|
||||
|
||||
## Language changes
|
||||
|
||||
- The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts
|
||||
`wasMoved` calls where needed.
|
||||
- The `=` hook is now called `=copy` for clarity. The old name `=` is still available so there
|
||||
is no need to update your code. This change was backported to 1.2 too so you can use the
|
||||
more readable `=copy` without loss of compatibility.
|
||||
|
||||
- In the newruntime it is now allowed to assign to the discriminator field
|
||||
without restrictions as long as the case object doesn't have a custom destructor.
|
||||
The discriminator value doesn't have to be a constant either. If you have a
|
||||
custom destructor for a case object and you do want to freely assign discriminator
|
||||
fields, it is recommended to refactor the object into 2 objects like this:
|
||||
|
||||
```nim
|
||||
type
|
||||
MyObj = object
|
||||
case kind: bool
|
||||
of true: y: ptr UncheckedArray[float]
|
||||
of false: z: seq[int]
|
||||
|
||||
proc `=destroy`(x: MyObj) =
|
||||
if x.kind and x.y != nil:
|
||||
deallocShared(x.y)
|
||||
```
|
||||
Refactor into:
|
||||
```nim
|
||||
type
|
||||
MySubObj = object
|
||||
val: ptr UncheckedArray[float]
|
||||
MyObj = object
|
||||
case kind: bool
|
||||
of true: y: MySubObj
|
||||
of false: z: seq[int]
|
||||
|
||||
proc `=destroy`(x: MySubObj) =
|
||||
if x.val != nil:
|
||||
deallocShared(x.val)
|
||||
```
|
||||
- `getImpl` on enum type symbols now returns field syms instead of idents. This helps
|
||||
with writing typed macros. The old behavior for backwards compatibility can be restored
|
||||
with `--useVersion:1.0`.
|
||||
- The typed AST for proc headers will now have the arguments be syms instead of idents.
|
||||
This helps with writing typed macros. The old behaviour for backwards compatibility can
|
||||
be restored with `--useVersion:1.0`.
|
||||
- ``let`` statements can now be used without a value if declared with
|
||||
``importc``/``importcpp``/``importjs``/``importobjc``.
|
||||
- The keyword `from` is now usable as an operator.
|
||||
- Exceptions inheriting from `system.Defect` are no longer tracked with
|
||||
the `.raises: []` exception tracking mechanism. This is more consistent with the
|
||||
built-in operations. The following always used to compile (and still does):
|
||||
```nim
|
||||
proc mydiv(a, b): int {.raises: [].} =
|
||||
a div b # can raise an DivByZeroDefect
|
||||
```
|
||||
|
||||
Now also this compiles:
|
||||
```nim
|
||||
proc mydiv(a, b): int {.raises: [].} =
|
||||
if b == 0: raise newException(DivByZeroDefect, "division by zero")
|
||||
else: result = a div b
|
||||
```
|
||||
|
||||
The reason for this is that `DivByZeroDefect` inherits from `Defect` and
|
||||
with `--panics:on` `Defects` become unrecoverable errors.
|
||||
|
||||
- Added the `thiscall` calling convention as specified by Microsoft, mostly for hooking purposes.
|
||||
- Deprecated the `{.unroll.}` pragma, because it was always ignored by the compiler anyway.
|
||||
- Removed the deprecated `strutils.isNilOrWhitespace`.
|
||||
- Removed the deprecated `sharedtables.initSharedTable`.
|
||||
- Removed the deprecated `asyncdispatch.newAsyncNativeSocket`.
|
||||
- Removed the deprecated `dom.releaseEvents` and `dom.captureEvents`.
|
||||
|
||||
- Removed `sharedlists.initSharedList`, was deprecated and produces undefined behaviour.
|
||||
|
||||
- There is a new experimental feature called "strictFuncs" which makes the definition of
|
||||
`.noSideEffect` stricter. [See here](manual_experimental.html#stricts-funcs)
|
||||
for more information.
|
||||
|
||||
- "for-loop macros" (see [the manual](manual.html#macros-for-loop-macros)) are no longer
|
||||
an experimental feature. In other words, you don't have to write pragma
|
||||
`{.experimental: "forLoopMacros".}` if you want to use them.
|
||||
|
||||
- Added the ``.noalias`` pragma. It is mapped to C's ``restrict`` keyword for the increased
|
||||
performance this keyword can enable.
|
||||
|
||||
- `items` no longer compiles with enums with holes as its behavior was error prone, see #14004.
|
||||
- `system.deepcopy` has to be enabled explicitly for `--gc:arc` and `--gc:orc` via
|
||||
`--deepcopy:on`.
|
||||
|
||||
- Added the `std/effecttraits` module for introspection of the inferred effects.
|
||||
We hope this enables `async` macros that are precise about the possible exceptions that
|
||||
can be raised.
|
||||
- The pragma blocks `{.gcsafe.}: ...` and `{.noSideEffect.}: ...` can now also be
|
||||
written as `{.cast(gcsafe).}: ...` and `{.cast(noSideEffect).}: ...`. This is the new
|
||||
preferred way of writing these, emphasizing their unsafe nature.
|
||||
|
||||
|
||||
## Compiler changes
|
||||
|
||||
- Specific warnings can now be turned into errors via `--warningAsError[X]:on|off`.
|
||||
- The `define` and `undef` pragmas have been de-deprecated.
|
||||
- New command: `nim r main.nim [args...]` which compiles and runs main.nim, and implies `--usenimcache`
|
||||
so that the output is saved to $nimcache/main$exeExt, using the same logic as `nim c -r` to
|
||||
avoid recompilations when sources don't change.
|
||||
Example:
|
||||
```bash
|
||||
nim r compiler/nim.nim --help # only compiled the first time
|
||||
echo 'import os; echo getCurrentCompilerExe()' | nim r - # this works too
|
||||
nim r compiler/nim.nim --fullhelp # no recompilation
|
||||
nim r --nimcache:/tmp main # binary saved to /tmp/main
|
||||
```
|
||||
- `--hint:processing` is now supported and means `--hint:processing:on`
|
||||
(likewise with other hints and warnings), which is consistent with all other bool flags.
|
||||
(since 1.3.3).
|
||||
- `nim doc -r main` and `nim rst2html -r main` now call `openDefaultBrowser`.
|
||||
- Added the new hint `--hint:msgOrigin` will show where a compiler msg (hint|warning|error)
|
||||
was generated; this helps in particular when it's non obvious where it came from
|
||||
either because multiple locations generate the same message, or because the
|
||||
message involves runtime formatting.
|
||||
- Added the new flag `--backend:js|c|cpp|objc` (or -b:js etc), to change the backend; can be
|
||||
used with any command (e.g. nim r, doc, check etc); safe to re-assign.
|
||||
- Added the new flag `--doccmd:cmd` to pass additional flags for runnableExamples,
|
||||
e.g.: `--doccmd:-d:foo --threads`
|
||||
use `--doccmd:skip` to skip runnableExamples and rst test snippets.
|
||||
- Added the new flag `--usenimcache` to output binary files to nimcache.
|
||||
- `runnableExamples "-b:cpp -r:off": code` is now supported, allowing to override
|
||||
how an example is compiled and run, for example to change the backend.
|
||||
- `nim doc` now outputs under `$projectPath/htmldocs` when `--outdir` is unspecified
|
||||
(with or without `--project`); passing `--project` now automatically generates
|
||||
an index and enables search.
|
||||
See [docgen](docgen.html#introduction-quick-start) for details.
|
||||
- Removed the `--oldNewlines` switch.
|
||||
- Removed the `--laxStrings` switch for mutating the internal zero terminator on strings.
|
||||
- Removed the `--oldast` switch.
|
||||
- Removed the `--oldgensym` switch.
|
||||
- `$getType(untyped)` is now "untyped" instead of "expr", `$getType(typed)` is
|
||||
now "typed" instead of "stmt".
|
||||
- Sink inference is now disabled per default and has to enabled explicitly via
|
||||
`--sinkInference:on`. *Note*: For the standard library sink inference remains
|
||||
enabled. This change is most relevant for the `--gc:arc`, `--gc:orc` memory
|
||||
management modes.
|
||||
|
||||
|
||||
## Tool changes
|
||||
|
||||
- `nimsuggest` now returns both the forward declaration and the
|
||||
implementation location upon a `def` query. Previously the behavior was
|
||||
to return the forward declaration only.
|
||||
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Fixed "repr() not available for uint{,8,16,32,64} under --gc:arc"
|
||||
([#13872](https://github.com/nim-lang/Nim/issues/13872))
|
||||
- Fixed "Critical: 1 completed Future, multiple await: Only 1 await will be awakened (the last one)"
|
||||
([#13889](https://github.com/nim-lang/Nim/issues/13889))
|
||||
- Fixed "crash on openarray interator with argument in stmtListExpr"
|
||||
([#13739](https://github.com/nim-lang/Nim/issues/13739))
|
||||
- Fixed "Some compilers on Windows don't work"
|
||||
([#13910](https://github.com/nim-lang/Nim/issues/13910))
|
||||
- Fixed "httpclient hangs if it recieves an HTTP 204 (No Content)"
|
||||
([#13894](https://github.com/nim-lang/Nim/issues/13894))
|
||||
- Fixed ""distinct uint64" type corruption on 32-bit, when using {.borrow.} operators"
|
||||
([#13902](https://github.com/nim-lang/Nim/issues/13902))
|
||||
- Fixed "Regression: impossible to use typed pragmas with proc types"
|
||||
([#13909](https://github.com/nim-lang/Nim/issues/13909))
|
||||
- Fixed "openssl wrapper corrupts stack on OpenSSL 1.1.1f + Android"
|
||||
([#13903](https://github.com/nim-lang/Nim/issues/13903))
|
||||
- Fixed "C compile error with --gc:arc on version 1.2.0 "unknown type name 'TGenericSeq'"
|
||||
([#13863](https://github.com/nim-lang/Nim/issues/13863))
|
||||
- Fixed "var return type for proc doesn't work at c++ backend"
|
||||
([#13848](https://github.com/nim-lang/Nim/issues/13848))
|
||||
- Fixed "TimeFormat() should raise an error but craches at compilation time"
|
||||
([#12864](https://github.com/nim-lang/Nim/issues/12864))
|
||||
- Fixed "gc:arc cannot fully support threadpool with FlowVar"
|
||||
([#13781](https://github.com/nim-lang/Nim/issues/13781))
|
||||
- Fixed "simple 'var openarray[char]' assignment crash when the openarray source is a local string and using gc:arc"
|
||||
([#14003](https://github.com/nim-lang/Nim/issues/14003))
|
||||
- Fixed "Cant use expressions with `when` in `type` sections."
|
||||
([#14007](https://github.com/nim-lang/Nim/issues/14007))
|
||||
- Fixed "`for a in MyEnum` gives incorrect results with enum with holes"
|
||||
([#14001](https://github.com/nim-lang/Nim/issues/14001))
|
||||
- Fixed "Trivial crash"
|
||||
([#12741](https://github.com/nim-lang/Nim/issues/12741))
|
||||
- Fixed "Enum with holes cannot be used as Table index"
|
||||
([#12834](https://github.com/nim-lang/Nim/issues/12834))
|
||||
- Fixed "spawn proc that uses typedesc crashes the compiler"
|
||||
([#14014](https://github.com/nim-lang/Nim/issues/14014))
|
||||
- Fixed "Docs Search `Results` box styling is not Dark Mode Friendly"
|
||||
([#13972](https://github.com/nim-lang/Nim/issues/13972))
|
||||
- Fixed "--gc:arc -d:useSysAssert undeclared identifier `cstderr` with newSeq"
|
||||
([#14038](https://github.com/nim-lang/Nim/issues/14038))
|
||||
- Fixed "issues in the manual"
|
||||
([#12486](https://github.com/nim-lang/Nim/issues/12486))
|
||||
- Fixed "Annoying warning: inherit from a more precise exception type like ValueError, IOError or OSError [InheritFromException]"
|
||||
([#14052](https://github.com/nim-lang/Nim/issues/14052))
|
||||
- Fixed "relativePath("foo", "/") and relativePath("/", "foo") is wrong"
|
||||
([#13222](https://github.com/nim-lang/Nim/issues/13222))
|
||||
- Fixed "[regression] `parseEnum` does not work anymore for enums with holes"
|
||||
([#14030](https://github.com/nim-lang/Nim/issues/14030))
|
||||
- Fixed "Exception types in the stdlib should inherit from `CatchableError` or `Defect`, not `Exception`"
|
||||
([#10288](https://github.com/nim-lang/Nim/issues/10288))
|
||||
- Fixed "Make debugSend and debugRecv procs public in smtp.nim"
|
||||
([#12189](https://github.com/nim-lang/Nim/issues/12189))
|
||||
- Fixed "xmltree need add raw text, when add style element"
|
||||
([#14064](https://github.com/nim-lang/Nim/issues/14064))
|
||||
- Fixed "raises requirement does not propagate to derived methods"
|
||||
([#8481](https://github.com/nim-lang/Nim/issues/8481))
|
||||
- Fixed "tests/stdlib/tgetaddrinfo.nim fails on NetBSD"
|
||||
([#14091](https://github.com/nim-lang/Nim/issues/14091))
|
||||
- Fixed "tests/niminaction/Chapter8/sdl/sdl_test.nim fails on NetBSD"
|
||||
([#14088](https://github.com/nim-lang/Nim/issues/14088))
|
||||
- Fixed "Incorrect escape sequence for example in jsffi library documentation"
|
||||
([#14110](https://github.com/nim-lang/Nim/issues/14110))
|
||||
- Fixed "HCR: Can not link exported const, in external library"
|
||||
([#13915](https://github.com/nim-lang/Nim/issues/13915))
|
||||
- Fixed "Cannot import std/unidecode"
|
||||
([#14112](https://github.com/nim-lang/Nim/issues/14112))
|
||||
- Fixed "macOS: dsymutil should not be called on static libraries"
|
||||
([#14132](https://github.com/nim-lang/Nim/issues/14132))
|
||||
- Fixed "nim jsondoc -o:doc.json filename.nim fails when sequences without a type are used"
|
||||
([#14066](https://github.com/nim-lang/Nim/issues/14066))
|
||||
- Fixed "algorithm.sortedByIt template corrupts tuple input under --gc:arc"
|
||||
([#14079](https://github.com/nim-lang/Nim/issues/14079))
|
||||
- Fixed "Invalid C code with lvalue conversion"
|
||||
([#14160](https://github.com/nim-lang/Nim/issues/14160))
|
||||
- Fixed "strformat: doc example fails"
|
||||
([#14054](https://github.com/nim-lang/Nim/issues/14054))
|
||||
- Fixed "Nim doc fail to run for nim 1.2.0 (nim 1.0.4 is ok)"
|
||||
([#13986](https://github.com/nim-lang/Nim/issues/13986))
|
||||
- Fixed "Exception when converting csize to clong"
|
||||
([#13698](https://github.com/nim-lang/Nim/issues/13698))
|
||||
- Fixed "[Documentation] overloading using named arguments works but is not documented"
|
||||
([#11932](https://github.com/nim-lang/Nim/issues/11932))
|
||||
- Fixed "import os + use of existsDir/dirExists/existsFile/fileExists/findExe in config.nims causes "ambiguous call' error"
|
||||
([#14142](https://github.com/nim-lang/Nim/issues/14142))
|
||||
- Fixed "import os + use of existsDir/dirExists/existsFile/fileExists/findExe in config.nims causes "ambiguous call' error"
|
||||
([#14142](https://github.com/nim-lang/Nim/issues/14142))
|
||||
- Fixed "runnableExamples doc gen crashes compiler with `except Exception as e` syntax"
|
||||
([#14177](https://github.com/nim-lang/Nim/issues/14177))
|
||||
- Fixed "[ARC] Segfault with cyclic references (?)"
|
||||
([#14159](https://github.com/nim-lang/Nim/issues/14159))
|
||||
- Fixed "Semcheck regression when accessing a static parameter in proc"
|
||||
([#14136](https://github.com/nim-lang/Nim/issues/14136))
|
||||
- Fixed "iterator walkDir doesn't work with -d:useWinAnsi"
|
||||
([#14201](https://github.com/nim-lang/Nim/issues/14201))
|
||||
- Fixed "cas is wrong for tcc"
|
||||
([#14151](https://github.com/nim-lang/Nim/issues/14151))
|
||||
- Fixed "proc execCmdEx doesn't work with -d:useWinAnsi"
|
||||
([#14203](https://github.com/nim-lang/Nim/issues/14203))
|
||||
- Fixed "Use -d:nimEmulateOverflowChecks by default?"
|
||||
([#14209](https://github.com/nim-lang/Nim/issues/14209))
|
||||
- Fixed "Old sequences with destructor objects bug"
|
||||
([#14217](https://github.com/nim-lang/Nim/issues/14217))
|
||||
- Fixed "[ARC] ICE when changing the discriminant of a return value"
|
||||
([#14244](https://github.com/nim-lang/Nim/issues/14244))
|
||||
- Fixed "[ARC] ICE with static objects"
|
||||
([#14236](https://github.com/nim-lang/Nim/issues/14236))
|
||||
- Fixed "[ARC] "internal error: environment misses: a" in a finalizer"
|
||||
([#14243](https://github.com/nim-lang/Nim/issues/14243))
|
||||
- Fixed "[ARC] compile failure using repr with object containing `ref seq[string]`"
|
||||
([#14270](https://github.com/nim-lang/Nim/issues/14270))
|
||||
- Fixed "[ARC] implicit move on last use happening on non-last use"
|
||||
([#14269](https://github.com/nim-lang/Nim/issues/14269))
|
||||
- Fixed "[ARC] Compiler crash with a recursive non-ref object variant"
|
||||
([#14294](https://github.com/nim-lang/Nim/issues/14294))
|
||||
- Fixed "htmlparser.parseHtml behaves differently using --gc:arc or --gc:orc"
|
||||
([#13946](https://github.com/nim-lang/Nim/issues/13946))
|
||||
- Fixed "Invalid return value of openProcess is NULL rather than INVALID_HANDLE_VALUE(-1) in windows"
|
||||
([#14289](https://github.com/nim-lang/Nim/issues/14289))
|
||||
- Fixed "ARC codegen bug with inline iterators"
|
||||
([#14219](https://github.com/nim-lang/Nim/issues/14219))
|
||||
- Fixed "Building koch on OpenBSD fails unless the Nim directory is in `$PATH`"
|
||||
([#13758](https://github.com/nim-lang/Nim/issues/13758))
|
||||
- Fixed "[gc:arc] case object assignment SIGSEGV: destroy not called for primitive type "
|
||||
([#14312](https://github.com/nim-lang/Nim/issues/14312))
|
||||
- Fixed "Crash when using thread and --gc:arc "
|
||||
([#13881](https://github.com/nim-lang/Nim/issues/13881))
|
||||
- Fixed "Getting "Warning: Cannot prove that 'result' is initialized" for an importcpp'd proc with `var T` return type"
|
||||
([#14314](https://github.com/nim-lang/Nim/issues/14314))
|
||||
- Fixed "`nim cpp -r --gc:arc` segfaults on caught AssertionError"
|
||||
([#13071](https://github.com/nim-lang/Nim/issues/13071))
|
||||
- Fixed "tests/async/tasyncawait.nim is recently very flaky"
|
||||
([#14320](https://github.com/nim-lang/Nim/issues/14320))
|
||||
- Fixed "Documentation nonexistent quitprocs module"
|
||||
([#14331](https://github.com/nim-lang/Nim/issues/14331))
|
||||
- Fixed "SIGSEV encountered when creating threads in a loop w/ --gc:arc"
|
||||
([#13935](https://github.com/nim-lang/Nim/issues/13935))
|
||||
- Fixed "nim-gdb is missing from all released packages"
|
||||
([#13104](https://github.com/nim-lang/Nim/issues/13104))
|
||||
- Fixed "sysAssert error with gc:arc on 3 line program"
|
||||
([#13862](https://github.com/nim-lang/Nim/issues/13862))
|
||||
- Fixed "compiler error with inline async proc and pragma"
|
||||
([#13998](https://github.com/nim-lang/Nim/issues/13998))
|
||||
- Fixed "[ARC] Compiler crash when adding to a seq[ref Object]"
|
||||
([#14333](https://github.com/nim-lang/Nim/issues/14333))
|
||||
- Fixed "nimvm: sysFatal: unhandled exception: 'sons' is not accessible using discriminant 'kind' of type 'TNode' [FieldError]"
|
||||
([#14340](https://github.com/nim-lang/Nim/issues/14340))
|
||||
- Fixed "[Regression] karax events are not firing "
|
||||
([#14350](https://github.com/nim-lang/Nim/issues/14350))
|
||||
- Fixed "odbcsql module has some wrong integer types"
|
||||
([#9771](https://github.com/nim-lang/Nim/issues/9771))
|
||||
- Fixed "db_sqlite needs sqlPrepared"
|
||||
([#13559](https://github.com/nim-lang/Nim/issues/13559))
|
||||
- Fixed "[Regression] `createThread` is not GC-safe"
|
||||
([#14370](https://github.com/nim-lang/Nim/issues/14370))
|
||||
- Fixed "Broken example on hot code reloading"
|
||||
([#14380](https://github.com/nim-lang/Nim/issues/14380))
|
||||
- Fixed "runnableExamples block with `except` on specified error fails with `nim doc`"
|
||||
([#12746](https://github.com/nim-lang/Nim/issues/12746))
|
||||
- Fixed "compiler as a library: findNimStdLibCompileTime fails to find system.nim"
|
||||
([#12293](https://github.com/nim-lang/Nim/issues/12293))
|
||||
- Fixed "5 bugs with importcpp exceptions"
|
||||
([#14369](https://github.com/nim-lang/Nim/issues/14369))
|
||||
- Fixed "Docs shouldn't collapse pragmas inside runnableExamples/code blocks"
|
||||
([#14174](https://github.com/nim-lang/Nim/issues/14174))
|
||||
- Fixed "Bad codegen/emit for hashes.hiXorLo in some contexts."
|
||||
([#14394](https://github.com/nim-lang/Nim/issues/14394))
|
||||
- Fixed "Boehm GC does not scan thread-local storage"
|
||||
([#14364](https://github.com/nim-lang/Nim/issues/14364))
|
||||
- Fixed "RVO not exception safe"
|
||||
([#14126](https://github.com/nim-lang/Nim/issues/14126))
|
||||
- Fixed "runnableExamples that are only compiled"
|
||||
([#10731](https://github.com/nim-lang/Nim/issues/10731))
|
||||
- Fixed "`foldr` raises IndexError when called on sequence"
|
||||
([#14404](https://github.com/nim-lang/Nim/issues/14404))
|
||||
- Fixed "moveFile does not overwrite destination file"
|
||||
([#14057](https://github.com/nim-lang/Nim/issues/14057))
|
||||
- Fixed "doc2 outputs in current work dir"
|
||||
([#6583](https://github.com/nim-lang/Nim/issues/6583))
|
||||
- Fixed "[docgen] proc doc comments silently omitted after 1st runnableExamples"
|
||||
([#9227](https://github.com/nim-lang/Nim/issues/9227))
|
||||
- Fixed "`nim doc --project` shows '@@/' instead of '../' for relative paths to submodules"
|
||||
([#14448](https://github.com/nim-lang/Nim/issues/14448))
|
||||
- Fixed "re, nre have wrong `start` semantics"
|
||||
([#14284](https://github.com/nim-lang/Nim/issues/14284))
|
||||
- Fixed "runnableExamples should preserve source code doc comments, strings, and (maybe) formatting"
|
||||
([#8871](https://github.com/nim-lang/Nim/issues/8871))
|
||||
- Fixed "`nim doc ..` fails when runnableExamples uses `$` [devel] [regression]"
|
||||
([#14485](https://github.com/nim-lang/Nim/issues/14485))
|
||||
- Fixed "`items` is 20%~30% slower than iteration via an index"
|
||||
([#14421](https://github.com/nim-lang/Nim/issues/14421))
|
||||
- Fixed "ARC: unreliable setLen "
|
||||
([#14495](https://github.com/nim-lang/Nim/issues/14495))
|
||||
- Fixed "lent is unsafe: after #14447 you can modify variables with "items" loop for sequences"
|
||||
([#14498](https://github.com/nim-lang/Nim/issues/14498))
|
||||
- Fixed "`var op = fn()` wrongly gives warning `ObservableStores` with `object of RootObj` type"
|
||||
([#14514](https://github.com/nim-lang/Nim/issues/14514))
|
||||
- Fixed "Compiler assertion"
|
||||
([#14562](https://github.com/nim-lang/Nim/issues/14562))
|
||||
- Fixed "Can't get `ord` of a value of a Range type in the JS backend "
|
||||
([#14570](https://github.com/nim-lang/Nim/issues/14570))
|
||||
- Fixed "js: can't take addr of param (including implicitly via `lent`)"
|
||||
([#14576](https://github.com/nim-lang/Nim/issues/14576))
|
||||
- Fixed "{.noinit.} ignored in for loop -> bad codegen for non-movable types"
|
||||
([#14118](https://github.com/nim-lang/Nim/issues/14118))
|
||||
- Fixed "generic destructor gives: `Error: unresolved generic parameter`"
|
||||
([#14315](https://github.com/nim-lang/Nim/issues/14315))
|
||||
- Fixed "Memory leak with arc gc"
|
||||
([#14568](https://github.com/nim-lang/Nim/issues/14568))
|
||||
- Fixed "escape analysis broken with `lent`"
|
||||
([#14557](https://github.com/nim-lang/Nim/issues/14557))
|
||||
- Fixed "`wrapWords` seems to ignore linebreaks when wrapping, leaving breaks in the wrong place"
|
||||
([#14579](https://github.com/nim-lang/Nim/issues/14579))
|
||||
- Fixed "`lent` gives wrong results with -d:release"
|
||||
([#14578](https://github.com/nim-lang/Nim/issues/14578))
|
||||
- Fixed "Nested await expressions regression: `await a(await expandValue())` doesnt compile"
|
||||
([#14279](https://github.com/nim-lang/Nim/issues/14279))
|
||||
- Fixed "windows CI docs fails with strange errors"
|
||||
([#14545](https://github.com/nim-lang/Nim/issues/14545))
|
||||
- Fixed "[CI] tests/async/tioselectors.nim flaky test for freebsd + OSX CI"
|
||||
([#13166](https://github.com/nim-lang/Nim/issues/13166))
|
||||
- Fixed "seq.setLen sometimes doesn't zero memory"
|
||||
([#14655](https://github.com/nim-lang/Nim/issues/14655))
|
||||
- Fixed "`nim dump` is roughly 100x slower in 1.3 versus 1.2"
|
||||
([#14179](https://github.com/nim-lang/Nim/issues/14179))
|
||||
- Fixed "Regression: devel docgen cannot generate document for method"
|
||||
([#14691](https://github.com/nim-lang/Nim/issues/14691))
|
||||
- Fixed "recently flaky tests/async/t7758.nim"
|
||||
([#14685](https://github.com/nim-lang/Nim/issues/14685))
|
||||
- Fixed "Bind no longer working in generic procs."
|
||||
([#11811](https://github.com/nim-lang/Nim/issues/11811))
|
||||
- Fixed "The pegs module doesn't work with generics!"
|
||||
([#14718](https://github.com/nim-lang/Nim/issues/14718))
|
||||
- Fixed "Defer is not properly working for asynchronous procedures."
|
||||
([#13899](https://github.com/nim-lang/Nim/issues/13899))
|
||||
- Fixed "Add an ARC test with threads in a loop"
|
||||
([#14690](https://github.com/nim-lang/Nim/issues/14690))
|
||||
- Fixed "[goto exceptions] {.noReturn.} pragma is not detected in a case expression"
|
||||
([#14458](https://github.com/nim-lang/Nim/issues/14458))
|
||||
- Fixed "[exceptions:goto] C compiler error with dynlib pragma calling a proc"
|
||||
([#14240](https://github.com/nim-lang/Nim/issues/14240))
|
||||
- Fixed "Cannot borrow var float64 in infix assignment"
|
||||
([#14440](https://github.com/nim-lang/Nim/issues/14440))
|
||||
- Fixed "lib/pure/memfiles.nim: compilation error with --taintMode:on"
|
||||
([#14760](https://github.com/nim-lang/Nim/issues/14760))
|
||||
- Fixed "newWideCString allocates a multiple of the memory needed"
|
||||
([#14750](https://github.com/nim-lang/Nim/issues/14750))
|
||||
- Fixed "Nim source archive install: 'install.sh' fails with error: cp: cannot stat 'bin/nim-gdb': No such file or directory"
|
||||
([#14748](https://github.com/nim-lang/Nim/issues/14748))
|
||||
- Fixed "`nim cpp -r tests/exception/t9657` hangs"
|
||||
([#10343](https://github.com/nim-lang/Nim/issues/10343))
|
||||
- Fixed "Detect tool fails on FreeBSD"
|
||||
([#14715](https://github.com/nim-lang/Nim/issues/14715))
|
||||
- Fixed "compiler crash: `findUnresolvedStatic` "
|
||||
([#14802](https://github.com/nim-lang/Nim/issues/14802))
|
||||
- Fixed "seq namespace (?) regression"
|
||||
([#4796](https://github.com/nim-lang/Nim/issues/4796))
|
||||
- Fixed "Possible out of bounds string access in std/colors parseColor and isColor"
|
||||
([#14839](https://github.com/nim-lang/Nim/issues/14839))
|
||||
- Fixed "compile error on latest devel with orc and ssl"
|
||||
([#14647](https://github.com/nim-lang/Nim/issues/14647))
|
||||
- Fixed "[minor] `$` wrong for type tuple"
|
||||
([#13432](https://github.com/nim-lang/Nim/issues/13432))
|
||||
- Fixed "Documentation missing on devel asyncftpclient"
|
||||
([#14846](https://github.com/nim-lang/Nim/issues/14846))
|
||||
- Fixed "nimpretty is confused with a trailing comma in enum definition"
|
||||
([#14401](https://github.com/nim-lang/Nim/issues/14401))
|
||||
- Fixed "Output arguments get ignored when compiling with --app:staticlib"
|
||||
([#12745](https://github.com/nim-lang/Nim/issues/12745))
|
||||
- Fixed "[ARC] destructive move destroys the object too early"
|
||||
([#14396](https://github.com/nim-lang/Nim/issues/14396))
|
||||
- Fixed "highlite.getNextToken() crashes if the buffer string is "echo "\"""
|
||||
([#14830](https://github.com/nim-lang/Nim/issues/14830))
|
||||
- Fixed "Memory corruption with --gc:arc with a seq of objects with an empty body."
|
||||
([#14472](https://github.com/nim-lang/Nim/issues/14472))
|
||||
- Fixed "Stropped identifiers don't work as field names in tuple literals"
|
||||
([#14911](https://github.com/nim-lang/Nim/issues/14911))
|
||||
- Fixed "Please revert my commit"
|
||||
([#14930](https://github.com/nim-lang/Nim/issues/14930))
|
||||
- Fixed "[ARC] C compiler error with inline iterators and imports"
|
||||
([#14864](https://github.com/nim-lang/Nim/issues/14864))
|
||||
- Fixed "AsyncHttpClient segfaults with gc:orc, possibly memory corruption"
|
||||
([#14402](https://github.com/nim-lang/Nim/issues/14402))
|
||||
- Fixed "[ARC] Template with a block evaluating to a GC'd value results in a compiler crash"
|
||||
([#14899](https://github.com/nim-lang/Nim/issues/14899))
|
||||
- Fixed "[ARC] Weird issue with if expressions and templates"
|
||||
([#14900](https://github.com/nim-lang/Nim/issues/14900))
|
||||
- Fixed "xmlparser does not compile on devel"
|
||||
([#14805](https://github.com/nim-lang/Nim/issues/14805))
|
||||
- Fixed "returning lent T from a var T param gives codegen errors or SIGSEGV"
|
||||
([#14878](https://github.com/nim-lang/Nim/issues/14878))
|
||||
- Fixed "[ARC] Weird issue with if expressions and templates"
|
||||
([#14900](https://github.com/nim-lang/Nim/issues/14900))
|
||||
- Fixed "threads:on + gc:orc + unittest = C compiler errors"
|
||||
([#14865](https://github.com/nim-lang/Nim/issues/14865))
|
||||
- Fixed "mitems, mpairs doesn't work at compile time anymore"
|
||||
([#12129](https://github.com/nim-lang/Nim/issues/12129))
|
||||
- Fixed "strange result from executing code in const expression"
|
||||
([#10465](https://github.com/nim-lang/Nim/issues/10465))
|
||||
- Fixed "Same warning printed 3 times"
|
||||
([#11009](https://github.com/nim-lang/Nim/issues/11009))
|
||||
- Fixed "type alias for generic typeclass doesn't work"
|
||||
([#4668](https://github.com/nim-lang/Nim/issues/4668))
|
||||
- Fixed "exceptions:goto Bug devel codegen lvalue NIM_FALSE=NIM_FALSE"
|
||||
([#14925](https://github.com/nim-lang/Nim/issues/14925))
|
||||
- Fixed "the --useVersion:1.0 no longer works in devel"
|
||||
([#14912](https://github.com/nim-lang/Nim/issues/14912))
|
||||
- Fixed "template declaration of iterator doesn't compile"
|
||||
([#4722](https://github.com/nim-lang/Nim/issues/4722))
|
||||
- Fixed "Compiler crash on type inheritance with static generic parameter and equality check"
|
||||
([#12571](https://github.com/nim-lang/Nim/issues/12571))
|
||||
- Fixed "Nim crashes while handling a cast in async circumstances."
|
||||
([#13815](https://github.com/nim-lang/Nim/issues/13815))
|
||||
- Fixed "[ARC] Internal compiler error when calling an iterator from an inline proc "
|
||||
([#14383](https://github.com/nim-lang/Nim/issues/14383))
|
||||
- Fixed ""Cannot instantiate" error when template uses generic type"
|
||||
([#5926](https://github.com/nim-lang/Nim/issues/5926))
|
||||
- Fixed "Different raises behaviour for newTerminal between Linux and Windows"
|
||||
([#12759](https://github.com/nim-lang/Nim/issues/12759))
|
||||
- Fixed "Expand on a type (that defines a proc type) in error message "
|
||||
([#6608](https://github.com/nim-lang/Nim/issues/6608))
|
||||
- Fixed "unittest require quits program with an exit code of 0"
|
||||
([#14475](https://github.com/nim-lang/Nim/issues/14475))
|
||||
- Fixed "Range type: Generics vs concrete type, semcheck difference."
|
||||
([#8426](https://github.com/nim-lang/Nim/issues/8426))
|
||||
- Fixed "[Macro] Type mismatch when parameter name is the same as a field"
|
||||
([#13253](https://github.com/nim-lang/Nim/issues/13253))
|
||||
- Fixed "Generic instantiation failure when converting a sequence of circular generic types to strings"
|
||||
([#10396](https://github.com/nim-lang/Nim/issues/10396))
|
||||
- Fixed "initOptParser ignores argument after value option with empty value."
|
||||
([#13086](https://github.com/nim-lang/Nim/issues/13086))
|
||||
- Fixed "[ARC] proc with both explicit and implicit return results in a C compiler error"
|
||||
([#14985](https://github.com/nim-lang/Nim/issues/14985))
|
||||
- Fixed "Alias type forgets implicit generic params depending on order"
|
||||
([#14990](https://github.com/nim-lang/Nim/issues/14990))
|
||||
- Fixed "[ARC] sequtils.insert has different behaviour between ARC/refc"
|
||||
([#14994](https://github.com/nim-lang/Nim/issues/14994))
|
||||
- Fixed "The documentation for "hot code reloading" references a non-existent npm package"
|
||||
([#13621](https://github.com/nim-lang/Nim/issues/13621))
|
||||
- Fixed "existsDir deprecated but breaking `dir` undeclared"
|
||||
([#15006](https://github.com/nim-lang/Nim/issues/15006))
|
||||
- Fixed "uri.decodeUrl crashes on incorrectly formatted input"
|
||||
([#14082](https://github.com/nim-lang/Nim/issues/14082))
|
||||
- Fixed "testament incorrectly reports time for tests, leading to wrong conclusions"
|
||||
([#14822](https://github.com/nim-lang/Nim/issues/14822))
|
||||
- Fixed "Calling peekChar with Stream returned from osproc.outputStream generate runtime error"
|
||||
([#14906](https://github.com/nim-lang/Nim/issues/14906))
|
||||
- Fixed "localPassC pragma should come *after* other flags"
|
||||
([#14194](https://github.com/nim-lang/Nim/issues/14194))
|
||||
- Fixed ""Could not load" dynamic library at runtime because of hidden dependency"
|
||||
([#2408](https://github.com/nim-lang/Nim/issues/2408))
|
||||
- Fixed "--gc:arc generate invalid code for {.global.} (`«nimErr_» in NIM_UNLIKELY`)"
|
||||
([#14480](https://github.com/nim-lang/Nim/issues/14480))
|
||||
- Fixed "Using `^` from stdlib/math along with converters gives a match for types that aren't SomeNumber"
|
||||
([#15033](https://github.com/nim-lang/Nim/issues/15033))
|
||||
- Fixed "[ARC] Weird exception behaviour from doAssertRaises"
|
||||
([#15026](https://github.com/nim-lang/Nim/issues/15026))
|
||||
- Fixed "[ARC] Compiler crash declaring a finalizer proc directly in 'new'"
|
||||
([#15044](https://github.com/nim-lang/Nim/issues/15044))
|
||||
- Fixed "[ARC] C compiler error when creating a var of a const seq"
|
||||
([#15036](https://github.com/nim-lang/Nim/issues/15036))
|
||||
- Fixed "code with named arguments in proc of winim/com can not been compiled"
|
||||
([#15056](https://github.com/nim-lang/Nim/issues/15056))
|
||||
- Fixed "javascript backend produces javascript code with syntax error in object syntax"
|
||||
([#14534](https://github.com/nim-lang/Nim/issues/14534))
|
||||
- Fixed "--gc:arc should be ignored in JS mode."
|
||||
([#14684](https://github.com/nim-lang/Nim/issues/14684))
|
||||
- Fixed "arc: C compilation error with imported global code using a closure iterator"
|
||||
([#12990](https://github.com/nim-lang/Nim/issues/12990))
|
||||
- Fixed "[ARC] Crash when modifying a string with mitems iterator"
|
||||
([#15052](https://github.com/nim-lang/Nim/issues/15052))
|
||||
- Fixed "[ARC] SIGSEGV when calling a closure as a tuple field in a seq"
|
||||
([#15038](https://github.com/nim-lang/Nim/issues/15038))
|
||||
- Fixed "pass varargs[seq[T]] to iterator give empty seq "
|
||||
([#12576](https://github.com/nim-lang/Nim/issues/12576))
|
||||
- Fixed "Compiler crashes when using string as object variant selector with else branch"
|
||||
([#14189](https://github.com/nim-lang/Nim/issues/14189))
|
||||
- Fixed "JS compiler error related to implicit return and return var type"
|
||||
([#11354](https://github.com/nim-lang/Nim/issues/11354))
|
||||
- Fixed "`nkRecWhen` causes internalAssert in semConstructFields"
|
||||
([#14698](https://github.com/nim-lang/Nim/issues/14698))
|
||||
- Fixed "Memory leaks with async (closure iterators?) under ORC"
|
||||
([#15076](https://github.com/nim-lang/Nim/issues/15076))
|
||||
- Fixed "strutil.insertSep() fails on negative numbers"
|
||||
([#11352](https://github.com/nim-lang/Nim/issues/11352))
|
||||
- Fixed "Constructing a uint64 range on a 32-bit machine leads to incorrect codegen"
|
||||
([#14616](https://github.com/nim-lang/Nim/issues/14616))
|
||||
- Fixed "heapqueue pushpop() proc doesn't compile"
|
||||
([#14139](https://github.com/nim-lang/Nim/issues/14139))
|
||||
- Fixed "[ARC] SIGSEGV when trying to swap in a literal/const string"
|
||||
([#15112](https://github.com/nim-lang/Nim/issues/15112))
|
||||
- Fixed "Defer and --gc:arc"
|
||||
([#15071](https://github.com/nim-lang/Nim/issues/15071))
|
||||
- Fixed "internal error: compiler/semobjconstr.nim(324, 20) example"
|
||||
([#15111](https://github.com/nim-lang/Nim/issues/15111))
|
||||
- Fixed "[ARC] Sequence "disappears" with a table inside of a table with an object variant"
|
||||
([#15122](https://github.com/nim-lang/Nim/issues/15122))
|
||||
- Fixed "[ARC] SIGSEGV with tuple assignment caused by cursor inference"
|
||||
([#15130](https://github.com/nim-lang/Nim/issues/15130))
|
||||
- Fixed "Issue with --gc:arc at compile time"
|
||||
([#15129](https://github.com/nim-lang/Nim/issues/15129))
|
||||
- Fixed "Writing an empty string to an AsyncFile raises an IndexDefect"
|
||||
([#15148](https://github.com/nim-lang/Nim/issues/15148))
|
||||
- Fixed "Compiler is confused about call convention of function with nested closure"
|
||||
([#5688](https://github.com/nim-lang/Nim/issues/5688))
|
||||
- Fixed "Nil check on each field fails in generic function"
|
||||
([#15101](https://github.com/nim-lang/Nim/issues/15101))
|
||||
- Fixed "{.nimcall.} convention won't avoid the creation of closures"
|
||||
([#8473](https://github.com/nim-lang/Nim/issues/8473))
|
||||
- Fixed "smtp.nim(161, 40) Error: type mismatch: got <typeof(nil)> but expected 'SslContext = void'"
|
||||
([#15177](https://github.com/nim-lang/Nim/issues/15177))
|
||||
- Fixed "[strscans] scanf doesn't match a single character with $+ if it's the end of the string"
|
||||
([#15064](https://github.com/nim-lang/Nim/issues/15064))
|
||||
- Fixed "Crash and incorrect return values when using readPasswordFromStdin on Windows."
|
||||
([#15207](https://github.com/nim-lang/Nim/issues/15207))
|
||||
- Fixed "Possible capture error with fieldPairs and genericParams"
|
||||
([#15221](https://github.com/nim-lang/Nim/issues/15221))
|
||||
- Fixed "The StmtList processing of template parameters can lead to unexpected errors"
|
||||
([#5691](https://github.com/nim-lang/Nim/issues/5691))
|
||||
- Fixed "[ARC] C compiler error when passing a var openArray to a sink openArray"
|
||||
([#15035](https://github.com/nim-lang/Nim/issues/15035))
|
||||
- Fixed "Inconsistent unsigned -> signed RangeDefect usage across integer sizes"
|
||||
([#15210](https://github.com/nim-lang/Nim/issues/15210))
|
||||
- Fixed "toHex results in RangeDefect exception when used with large uint64"
|
||||
([#15257](https://github.com/nim-lang/Nim/issues/15257))
|
||||
- Fixed "Arc sink arg crash"
|
||||
([#15238](https://github.com/nim-lang/Nim/issues/15238))
|
||||
- Fixed "SQL escape in db_mysql is not enough"
|
||||
([#15219](https://github.com/nim-lang/Nim/issues/15219))
|
||||
- Fixed "Mixing 'return' with expressions is allowed in 1.2"
|
||||
([#15280](https://github.com/nim-lang/Nim/issues/15280))
|
||||
- Fixed "os.getFileInfo() causes ICE with --gc:arc on Windows"
|
||||
([#15286](https://github.com/nim-lang/Nim/issues/15286))
|
||||
- Fixed "[ARC] Sequence "disappears" with a table inside of a table with an object variant"
|
||||
([#15122](https://github.com/nim-lang/Nim/issues/15122))
|
||||
- Fixed "Documentation regression jsre module missing"
|
||||
([#15183](https://github.com/nim-lang/Nim/issues/15183))
|
||||
- Fixed "CountTable.smallest/largest() on empty table either asserts or gives bogus answer"
|
||||
([#15021](https://github.com/nim-lang/Nim/issues/15021))
|
||||
- Fixed "[Regression] Parser regression"
|
||||
([#15305](https://github.com/nim-lang/Nim/issues/15305))
|
||||
- Fixed "[ARC] SIGSEGV with tuple unpacking caused by cursor inference"
|
||||
([#15147](https://github.com/nim-lang/Nim/issues/15147))
|
||||
- Fixed "LwIP/FreeRTOS compile error - missing SIGPIPE and more "
|
||||
([#15302](https://github.com/nim-lang/Nim/issues/15302))
|
||||
- Fixed "Memory leaks with async (closure iterators?) under ORC"
|
||||
([#15076](https://github.com/nim-lang/Nim/issues/15076))
|
||||
- Fixed "Bug compiling with --gc:arg or --gc:orc"
|
||||
([#15325](https://github.com/nim-lang/Nim/issues/15325))
|
||||
- Fixed "memory corruption in tmarshall.nim"
|
||||
([#9754](https://github.com/nim-lang/Nim/issues/9754))
|
||||
- Fixed "typed macros break generic proc definitions"
|
||||
([#15326](https://github.com/nim-lang/Nim/issues/15326))
|
||||
- Fixed "nim doc2 ignores --docSeeSrcUrl parameter"
|
||||
([#6071](https://github.com/nim-lang/Nim/issues/6071))
|
||||
- Fixed "The decodeData Iterator from cgi module crash"
|
||||
([#15369](https://github.com/nim-lang/Nim/issues/15369))
|
||||
- Fixed "|| iterator generates invalid code when compiling with --debugger:native"
|
||||
([#9710](https://github.com/nim-lang/Nim/issues/9710))
|
||||
- Fixed "Wrong number of variables"
|
||||
([#15360](https://github.com/nim-lang/Nim/issues/15360))
|
||||
- Fixed "Coercions with distinct types should traverse pointer modifiers transparently."
|
||||
([#7165](https://github.com/nim-lang/Nim/issues/7165))
|
||||
- Fixed "Error with distinct generic TableRef"
|
||||
([#6060](https://github.com/nim-lang/Nim/issues/6060))
|
||||
- Fixed "Support images in nim docgen"
|
||||
([#6430](https://github.com/nim-lang/Nim/issues/6430))
|
||||
- Fixed "Regression. Double sem check for procs."
|
||||
([#15389](https://github.com/nim-lang/Nim/issues/15389))
|
||||
- Fixed "uri.nim url with literal ipv6 address is printed wrong, and cannot parsed again"
|
||||
([#15333](https://github.com/nim-lang/Nim/issues/15333))
|
||||
- Fixed "[ARC] Object variant gets corrupted with cursor inference"
|
||||
([#15361](https://github.com/nim-lang/Nim/issues/15361))
|
||||
- Fixed "`nim doc ..` compiler crash (regression 0.19.6 => 1.0)"
|
||||
([#14474](https://github.com/nim-lang/Nim/issues/14474))
|
||||
- Fixed "cannot borrow result; what it borrows from is potentially mutated"
|
||||
([#15403](https://github.com/nim-lang/Nim/issues/15403))
|
||||
- Fixed "memory corruption for seq.add(seq) with gc:arc and d:useMalloc "
|
||||
([#14983](https://github.com/nim-lang/Nim/issues/14983))
|
||||
- Fixed "DocGen HTML output appears improperly when encountering text immediately after/before inline monospace; in some cases won't compile"
|
||||
([#11537](https://github.com/nim-lang/Nim/issues/11537))
|
||||
- Fixed "Deepcopy in arc crashes"
|
||||
([#15405](https://github.com/nim-lang/Nim/issues/15405))
|
||||
- Fixed "pop pragma takes invalid input"
|
||||
([#15430](https://github.com/nim-lang/Nim/issues/15430))
|
||||
- Fixed "tests/stdlib/tgetprotobyname fails on NetBSD"
|
||||
([#15452](https://github.com/nim-lang/Nim/issues/15452))
|
||||
- Fixed "defer doesnt work with block, break and await"
|
||||
([#15243](https://github.com/nim-lang/Nim/issues/15243))
|
||||
- Fixed "tests/stdlib/tssl failing on NetBSD"
|
||||
([#15493](https://github.com/nim-lang/Nim/issues/15493))
|
||||
- Fixed "strictFuncs doesn't seem to catch simple ref mutation"
|
||||
([#15508](https://github.com/nim-lang/Nim/issues/15508))
|
||||
- Fixed "Sizeof of case object is incorrect. Showstopper"
|
||||
([#15516](https://github.com/nim-lang/Nim/issues/15516))
|
||||
- Fixed "[ARC] Internal error when trying to use a parallel for loop"
|
||||
([#15512](https://github.com/nim-lang/Nim/issues/15512))
|
||||
- Fixed "[ARC] Type-bound assign op is not being generated"
|
||||
([#15510](https://github.com/nim-lang/Nim/issues/15510))
|
||||
- Fixed "[ARC] Crash when adding openArray proc argument to a local seq"
|
||||
([#15511](https://github.com/nim-lang/Nim/issues/15511))
|
||||
- Fixed "VM: const case object gets some fields zeroed out at runtime"
|
||||
([#13081](https://github.com/nim-lang/Nim/issues/13081))
|
||||
- Fixed "regression(1.2.6 => devel): VM: const case object field access gives: 'sons' is not accessible"
|
||||
([#15532](https://github.com/nim-lang/Nim/issues/15532))
|
||||
- Fixed "Csources: huge size increase (x2.3) in 0.20"
|
||||
([#12027](https://github.com/nim-lang/Nim/issues/12027))
|
||||
- Fixed "Out of date error message for GC options"
|
||||
([#15547](https://github.com/nim-lang/Nim/issues/15547))
|
||||
- Fixed "dbQuote additional escape regression"
|
||||
([#15560](https://github.com/nim-lang/Nim/issues/15560))
|
||||
@@ -2,7 +2,7 @@ REM Some debug info
|
||||
echo "Running on %CI_RUNNER_ID% (%CI_RUNNER_DESCRIPTION%) with tags %CI_RUNNER_TAGS%."
|
||||
gcc -v
|
||||
|
||||
git clone --depth 1 https://github.com/nim-lang/csources.git
|
||||
git clone --depth 1 https://github.com/nim-lang/csources_v1.git csources
|
||||
cd csources
|
||||
call build64.bat
|
||||
cd ..
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
sh ci/deps.sh
|
||||
|
||||
# Build from C sources.
|
||||
git clone --depth 1 https://github.com/nim-lang/csources.git
|
||||
git clone --depth 1 https://github.com/nim-lang/csources_v1.git csources
|
||||
cd csources
|
||||
sh build.sh
|
||||
cd ..
|
||||
|
||||
@@ -25,7 +25,7 @@ Rem Build csources
|
||||
koch csources -d:release || exit /b
|
||||
|
||||
rem Grab C sources and nimsuggest
|
||||
git clone --depth 1 https://github.com/nim-lang/csources.git
|
||||
git clone --depth 1 https://github.com/nim-lang/csources_v1.git csources
|
||||
|
||||
set PATH=%CD%\bin;%PATH%
|
||||
|
||||
|
||||
@@ -17,21 +17,17 @@ export int128
|
||||
|
||||
type
|
||||
TCallingConvention* = enum
|
||||
ccNimCall # nimcall, also the default
|
||||
ccStdCall # procedure is stdcall
|
||||
ccCDecl # cdecl
|
||||
ccSafeCall # safecall
|
||||
ccSysCall # system call
|
||||
ccInline # proc should be inlined
|
||||
ccNoInline # proc should not be inlined
|
||||
ccFastCall # fastcall (pass parameters in registers)
|
||||
ccThisCall # thiscall (parameters are pushed right-to-left)
|
||||
ccClosure # proc has a closure
|
||||
ccNoConvention # needed for generating proper C procs sometimes
|
||||
|
||||
const CallingConvToStr*: array[TCallingConvention, string] = ["nimcall", "stdcall",
|
||||
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "thiscall",
|
||||
"closure", "noconv"]
|
||||
ccNimCall = "nimcall" # nimcall, also the default
|
||||
ccStdCall = "stdcall" # procedure is stdcall
|
||||
ccCDecl = "cdecl" # cdecl
|
||||
ccSafeCall = "safecall" # safecall
|
||||
ccSysCall = "syscall" # system call
|
||||
ccInline = "inline" # proc should be inlined
|
||||
ccNoInline = "noinline" # proc should not be inlined
|
||||
ccFastCall = "fastcall" # fastcall (pass parameters in registers)
|
||||
ccThisCall = "thiscall" # thiscall (parameters are pushed right-to-left)
|
||||
ccClosure = "closure" # proc has a closure
|
||||
ccNoConvention = "noconv" # needed for generating proper C procs sometimes
|
||||
|
||||
type
|
||||
TNodeKind* = enum # order is extremely important, because ranges are used
|
||||
@@ -811,7 +807,7 @@ type
|
||||
|
||||
PInstantiation* = ref TInstantiation
|
||||
|
||||
TScope* = object
|
||||
TScope* {.acyclic.} = object
|
||||
depthLevel*: int
|
||||
symbols*: TStrTable
|
||||
parent*: PScope
|
||||
@@ -875,7 +871,7 @@ type
|
||||
annex*: PLib # additional fields (seldom used, so we use a
|
||||
# reference to another object to save space)
|
||||
when hasFFI:
|
||||
cname*: string # resolved C declaration name in importc decl, eg:
|
||||
cname*: string # resolved C declaration name in importc decl, e.g.:
|
||||
# proc fun() {.importc: "$1aux".} => cname = funaux
|
||||
constraint*: PNode # additional constraints like 'lit|result'; also
|
||||
# misused for the codegenDecl pragma in the hope
|
||||
@@ -1089,7 +1085,7 @@ proc safeLen*(n: PNode): int {.inline.} =
|
||||
|
||||
proc safeArrLen*(n: PNode): int {.inline.} =
|
||||
## works for array-like objects (strings passed as openArray in VM).
|
||||
if n.kind in {nkStrLit..nkTripleStrLit}:result = n.strVal.len
|
||||
if n.kind in {nkStrLit..nkTripleStrLit}: result = n.strVal.len
|
||||
elif n.kind in {nkNone..nkFloat128Lit}: result = 0
|
||||
else: result = n.len
|
||||
|
||||
@@ -1416,6 +1412,7 @@ proc copySym*(s: PSym): PSym =
|
||||
result.position = s.position
|
||||
result.loc = s.loc
|
||||
result.annex = s.annex # BUGFIX
|
||||
result.constraint = s.constraint
|
||||
if result.kind in {skVar, skLet, skField}:
|
||||
result.guard = s.guard
|
||||
result.bitsize = s.bitsize
|
||||
@@ -1779,7 +1776,7 @@ proc isAtom*(n: PNode): bool {.inline.} =
|
||||
result = n.kind >= nkNone and n.kind <= nkNilLit
|
||||
|
||||
proc isEmptyType*(t: PType): bool {.inline.} =
|
||||
## 'void' and 'stmt' types are often equivalent to 'nil' these days:
|
||||
## 'void' and 'typed' types are often equivalent to 'nil' these days:
|
||||
result = t == nil or t.kind in {tyVoid, tyTyped}
|
||||
|
||||
proc makeStmtList*(n: PNode): PNode =
|
||||
@@ -1808,6 +1805,7 @@ proc toVar*(typ: PType; kind: TTypeKind): PType =
|
||||
proc toRef*(typ: PType): PType =
|
||||
## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and
|
||||
## returned. Otherwise ``typ`` is simply returned as-is.
|
||||
result = typ
|
||||
if typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject:
|
||||
result = newType(tyRef, typ.owner)
|
||||
rawAddSon(result, typ)
|
||||
|
||||
@@ -110,14 +110,14 @@ proc iiTablePut*(t: var TIITable, key, val: int)
|
||||
|
||||
# implementation
|
||||
|
||||
proc skipConvAndClosure*(n: PNode): PNode =
|
||||
proc skipConvCastAndClosure*(n: PNode): PNode =
|
||||
result = n
|
||||
while true:
|
||||
case result.kind
|
||||
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64,
|
||||
nkClosure:
|
||||
result = result[0]
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast:
|
||||
result = result[1]
|
||||
else: break
|
||||
|
||||
@@ -345,7 +345,7 @@ proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int,
|
||||
result.addf("$N$1\"n\": $2", [istr, treeToYamlAux(conf, n.n, marker, indent + 2, maxRecDepth - 1)])
|
||||
if card(n.flags) > 0:
|
||||
result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
|
||||
result.addf("$N$1\"callconv\": $2", [istr, makeYamlString(CallingConvToStr[n.callConv])])
|
||||
result.addf("$N$1\"callconv\": $2", [istr, makeYamlString($n.callConv)])
|
||||
result.addf("$N$1\"size\": $2", [istr, rope(n.size)])
|
||||
result.addf("$N$1\"align\": $2", [istr, rope(n.align)])
|
||||
result.addf("$N$1\"sons\": $2", [istr, sonsRope])
|
||||
|
||||
@@ -16,7 +16,7 @@ const
|
||||
Mhalf = M div 2
|
||||
|
||||
type
|
||||
Node[Key, Val] = ref object
|
||||
Node[Key, Val] {.acyclic.} = ref object
|
||||
entries: int
|
||||
keys: array[M, Key]
|
||||
case isInternal: bool
|
||||
@@ -168,68 +168,3 @@ iterator pairs*[Key, Val](b: BTree[Key, Val]): (Key, Val) =
|
||||
yield (k, v)
|
||||
|
||||
proc len*[Key, Val](b: BTree[Key, Val]): int {.inline.} = b.entries
|
||||
|
||||
when isMainModule:
|
||||
|
||||
import random, tables
|
||||
|
||||
proc main =
|
||||
var st = initBTree[string, string]()
|
||||
st.add("www.cs.princeton.edu", "abc")
|
||||
st.add("www.princeton.edu", "128.112.128.15")
|
||||
st.add("www.yale.edu", "130.132.143.21")
|
||||
st.add("www.simpsons.com", "209.052.165.60")
|
||||
st.add("www.apple.com", "17.112.152.32")
|
||||
st.add("www.amazon.com", "207.171.182.16")
|
||||
st.add("www.ebay.com", "66.135.192.87")
|
||||
st.add("www.cnn.com", "64.236.16.20")
|
||||
st.add("www.google.com", "216.239.41.99")
|
||||
st.add("www.nytimes.com", "199.239.136.200")
|
||||
st.add("www.microsoft.com", "207.126.99.140")
|
||||
st.add("www.dell.com", "143.166.224.230")
|
||||
st.add("www.slashdot.org", "66.35.250.151")
|
||||
st.add("www.espn.com", "199.181.135.201")
|
||||
st.add("www.weather.com", "63.111.66.11")
|
||||
st.add("www.yahoo.com", "216.109.118.65")
|
||||
|
||||
assert st.getOrDefault("www.cs.princeton.edu") == "abc"
|
||||
assert st.getOrDefault("www.harvardsucks.com") == ""
|
||||
|
||||
assert st.getOrDefault("www.simpsons.com") == "209.052.165.60"
|
||||
assert st.getOrDefault("www.apple.com") == "17.112.152.32"
|
||||
assert st.getOrDefault("www.ebay.com") == "66.135.192.87"
|
||||
assert st.getOrDefault("www.dell.com") == "143.166.224.230"
|
||||
assert(st.entries == 16)
|
||||
|
||||
for k, v in st:
|
||||
echo k, ": ", v
|
||||
|
||||
when false:
|
||||
var b2 = initBTree[string, string]()
|
||||
const iters = 10_000
|
||||
for i in 1..iters:
|
||||
b2.add($i, $(iters - i))
|
||||
for i in 1..iters:
|
||||
let x = b2.getOrDefault($i)
|
||||
if x != $(iters - i):
|
||||
echo "got ", x, ", but expected ", iters - i
|
||||
echo b2.entries
|
||||
|
||||
when true:
|
||||
var b2 = initBTree[int, string]()
|
||||
var t2 = initTable[int, string]()
|
||||
const iters = 100_000
|
||||
for i in 1..iters:
|
||||
let x = rand(high(int))
|
||||
if not t2.hasKey(x):
|
||||
doAssert b2.getOrDefault(x).len == 0, " what, tree has this element " & $x
|
||||
t2[x] = $x
|
||||
b2.add(x, $x)
|
||||
|
||||
doAssert b2.entries == t2.len
|
||||
echo "unique entries ", b2.entries
|
||||
for k, v in t2:
|
||||
doAssert $k == v
|
||||
doAssert b2.getOrDefault(k) == $k
|
||||
|
||||
main()
|
||||
|
||||
@@ -249,13 +249,15 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
|
||||
else: internalError(p.config, "openArrayLoc: " & typeToString(a.t))
|
||||
|
||||
proc withTmpIfNeeded(p: BProc, a: TLoc, needsTmp: bool): TLoc =
|
||||
if needsTmp and a.lode.typ != nil:
|
||||
var tmp: TLoc
|
||||
getTemp(p, a.lode.typ, tmp, needsInit=false)
|
||||
genAssignment(p, tmp, a, {})
|
||||
tmp
|
||||
# Bug https://github.com/status-im/nimbus-eth2/issues/1549
|
||||
# Aliasing is preferred over stack overflows.
|
||||
# Also don't regress for non ARC-builds, too risky.
|
||||
if needsTmp and a.lode.typ != nil and p.config.selectedGC in {gcArc, gcOrc} and
|
||||
getSize(p.config, a.lode.typ) < 1024:
|
||||
getTemp(p, a.lode.typ, result, needsInit=false)
|
||||
genAssignment(p, result, a, {})
|
||||
else:
|
||||
a
|
||||
result = a
|
||||
|
||||
proc genArgStringToCString(p: BProc, n: PNode, needsTmp: bool): Rope {.inline.} =
|
||||
var a: TLoc
|
||||
|
||||
@@ -71,8 +71,10 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
|
||||
p.module.s[cfsData].addf(
|
||||
"static NIM_CONST $1 $2 = {NIM_NIL,NIM_NIL};$n",
|
||||
[getTypeDesc(p.module, ty), result])
|
||||
else:
|
||||
elif k in {tyPointer, tyNil, tyProc}:
|
||||
result = rope("NIM_NIL")
|
||||
else:
|
||||
result = "(($1) NIM_NIL)" % [getTypeDesc(p.module, ty)]
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
let k = if ty == nil: tyString
|
||||
else: skipTypes(ty, abstractVarRange + {tyStatic, tyUserTypeClass, tyUserTypeClassInst}).kind
|
||||
@@ -760,7 +762,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) =
|
||||
# See tmissingderef. So we get rid of the deref instead. The codegen
|
||||
# ends up using 'memcpy' for the array assignment,
|
||||
# so the '&' and '*' cancel out:
|
||||
putIntoDest(p, d, lodeTyp(a.t[0]), rdLoc(a), a.storage)
|
||||
putIntoDest(p, d, e, rdLoc(a), a.storage)
|
||||
else:
|
||||
putIntoDest(p, d, e, "(*$1)" % [rdLoc(a)], a.storage)
|
||||
|
||||
@@ -879,6 +881,7 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
|
||||
[rdLoc(test), strLit, raiseInstr(p)])
|
||||
|
||||
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||
assert e[0].kind == nkDotExpr
|
||||
if optFieldCheck in p.options:
|
||||
var a: TLoc
|
||||
genRecordFieldAux(p, e[0], d, a)
|
||||
@@ -1278,11 +1281,11 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
|
||||
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
if needsInit:
|
||||
b.r = ropecg(p.module, "($1) #nimNewObj($2)",
|
||||
[getTypeDesc(p.module, typ), sizeExpr])
|
||||
b.r = ropecg(p.module, "($1) #nimNewObj($2, NIM_ALIGNOF($3))",
|
||||
[getTypeDesc(p.module, typ), sizeExpr, getTypeDesc(p.module, bt)])
|
||||
else:
|
||||
b.r = ropecg(p.module, "($1) #nimNewObjUninit($2)",
|
||||
[getTypeDesc(p.module, typ), sizeExpr])
|
||||
b.r = ropecg(p.module, "($1) #nimNewObjUninit($2, NIM_ALIGNOF($3))",
|
||||
[getTypeDesc(p.module, typ), sizeExpr, getTypeDesc(p.module, bt)])
|
||||
genAssignment(p, a, b, {})
|
||||
else:
|
||||
let ti = genTypeInfoV1(p.module, typ, a.lode.info)
|
||||
@@ -2180,15 +2183,19 @@ proc genDestroy(p: BProc; n: PNode) =
|
||||
of tyString:
|
||||
var a: TLoc
|
||||
initLocExpr(p, arg, a)
|
||||
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
|
||||
" #deallocShared($1.p);$n" &
|
||||
"}$n",
|
||||
[rdLoc(a)])
|
||||
if optThreads in p.config.globalOptions:
|
||||
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
|
||||
" #deallocShared($1.p);$n" &
|
||||
"}$n", [rdLoc(a)])
|
||||
else:
|
||||
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
|
||||
" #dealloc($1.p);$n" &
|
||||
"}$n", [rdLoc(a)])
|
||||
of tySequence:
|
||||
var a: TLoc
|
||||
initLocExpr(p, arg, a)
|
||||
linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" &
|
||||
" #deallocShared($1.p);$n" &
|
||||
" #alignedDealloc($1.p, NIM_ALIGNOF($2));$n" &
|
||||
"}$n",
|
||||
[rdLoc(a), getTypeDesc(p.module, t.lastSon)])
|
||||
else: discard "nothing to do"
|
||||
@@ -2209,7 +2216,7 @@ proc genDispose(p: BProc; n: PNode) =
|
||||
if elemType.destructor != nil:
|
||||
var destroyCall = newNodeI(nkCall, n.info)
|
||||
genStmts(p, destroyCall)
|
||||
lineCg(p, cpsStmts, ["#nimRawDispose($#)", rdLoc(a)])
|
||||
lineFmt(p, cpsStmts, "#nimRawDispose($1, NIM_ALIGNOF($2))", [rdLoc(a), getTypeDesc(p.module, elemType)])
|
||||
else:
|
||||
# ``nimRawDisposeVirtual`` calls the ``finalizer`` which is the same as the
|
||||
# destructor, but it uses the runtime type. Afterwards the memory is freed:
|
||||
@@ -2300,7 +2307,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mCharToStr: genDollar(p, e, d, "#nimCharToStr($1)")
|
||||
of mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($1)")
|
||||
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
|
||||
of mStrToStr, mUnown, mIsolate: expr(p, e[1], d)
|
||||
of mStrToStr, mUnown: expr(p, e[1], d)
|
||||
of mIsolate: genCall(p, e, d)
|
||||
of mEnumToStr:
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
genEnumToStr(p, e, d)
|
||||
@@ -2316,14 +2324,19 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
gcUsage(p.config, e)
|
||||
else:
|
||||
genNewFinalize(p, e)
|
||||
of mNewSeq: genNewSeq(p, e)
|
||||
of mNewSeq:
|
||||
if optSeqDestructors in p.config.globalOptions:
|
||||
e[1] = makeAddr(e[1])
|
||||
genCall(p, e, d)
|
||||
else:
|
||||
genNewSeq(p, e)
|
||||
of mNewSeqOfCap: genNewSeqOfCap(p, e, d)
|
||||
of mSizeOf:
|
||||
let t = e[1].typ.skipTypes({tyTypeDesc})
|
||||
putIntoDest(p, d, e, "((NI)sizeof($1))" % [getTypeDesc(p.module, t)])
|
||||
putIntoDest(p, d, e, "((NI)sizeof($1))" % [getTypeDesc(p.module, t, skVar)])
|
||||
of mAlignOf:
|
||||
let t = e[1].typ.skipTypes({tyTypeDesc})
|
||||
putIntoDest(p, d, e, "((NI)NIM_ALIGNOF($1))" % [getTypeDesc(p.module, t)])
|
||||
putIntoDest(p, d, e, "((NI)NIM_ALIGNOF($1))" % [getTypeDesc(p.module, t, skVar)])
|
||||
of mOffsetOf:
|
||||
var dotExpr: PNode
|
||||
if e[1].kind == nkDotExpr:
|
||||
@@ -2333,7 +2346,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
else:
|
||||
internalError(p.config, e.info, "unknown ast")
|
||||
let t = dotExpr[0].typ.skipTypes({tyTypeDesc})
|
||||
let tname = getTypeDesc(p.module, t)
|
||||
let tname = getTypeDesc(p.module, t, skVar)
|
||||
let member =
|
||||
if t.kind == tyTuple:
|
||||
"Field" & rope(dotExpr[1].sym.position)
|
||||
@@ -2844,6 +2857,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
inc p.splitDecls
|
||||
genGotoState(p, n)
|
||||
of nkBreakState: genBreakState(p, n, d)
|
||||
of nkMixinStmt, nkBindStmt: discard
|
||||
else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind")
|
||||
|
||||
proc genNamedConstExpr(p: BProc, n: PNode; isConst: bool): Rope =
|
||||
|
||||
@@ -25,10 +25,10 @@ proc getTraverseProc(p: BProc, v: PSym): Rope =
|
||||
|
||||
proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) =
|
||||
if sfThread in v.flags:
|
||||
appcg(p.module, p.module.initProc.procSec(cpsInit),
|
||||
appcg(p.module, p.module.preInitProc.procSec(cpsInit),
|
||||
"$n\t#nimRegisterThreadLocalMarker($1);$n$n", [traverseProc])
|
||||
else:
|
||||
appcg(p.module, p.module.initProc.procSec(cpsInit),
|
||||
appcg(p.module, p.module.preInitProc.procSec(cpsInit),
|
||||
"$n\t#nimRegisterGlobalMarker($1);$n$n", [traverseProc])
|
||||
|
||||
proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} =
|
||||
@@ -382,7 +382,13 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||
|
||||
proc genSingleVar(p: BProc, a: PNode) =
|
||||
let v = a[0].sym
|
||||
if sfCompileTime in v.flags: return
|
||||
if sfCompileTime in v.flags:
|
||||
# fix issue #12640
|
||||
# {.global, compileTime.} pragma in proc
|
||||
if sfGlobal in v.flags and p.prc != nil and p.prc.kind == skProc:
|
||||
discard
|
||||
else:
|
||||
return
|
||||
genSingleVar(p, v, a[0], a[2])
|
||||
|
||||
proc genClosureVar(p: BProc, a: PNode) =
|
||||
|
||||
@@ -282,7 +282,8 @@ proc ccgIntroducedPtr(conf: ConfigRef; s: PSym, retType: PType): bool =
|
||||
result = false
|
||||
# first parameter and return type is 'lent T'? --> use pass by pointer
|
||||
if s.position == 0 and retType != nil and retType.kind == tyLent:
|
||||
result = pt.kind != tyVar
|
||||
result = not (pt.kind in {tyVar, tyArray, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} or
|
||||
pt.kind == tySet and mapSetType(conf, pt) == ctArray)
|
||||
|
||||
proc fillResult(conf: ConfigRef; param: PNode) =
|
||||
fillLoc(param.sym.loc, locParam, param, ~"Result",
|
||||
@@ -1326,6 +1327,10 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
|
||||
|
||||
genProc(m, theProc)
|
||||
result = theProc.loc.r
|
||||
|
||||
when false:
|
||||
if not canFormAcycle(t) and op == attachedTrace:
|
||||
echo "ayclic but has this =trace ", t, " ", theProc.ast
|
||||
else:
|
||||
when false:
|
||||
if op == attachedTrace and m.config.selectedGC == gcOrc and
|
||||
@@ -1351,9 +1356,12 @@ proc genTypeInfoV2Impl(m: BModule, t, origType: PType, name: Rope; info: TLineIn
|
||||
let traceImpl = genHook(m, t, info, attachedTrace)
|
||||
let disposeImpl = genHook(m, t, info, attachedDispose)
|
||||
|
||||
addf(m.s[cfsTypeInit3], "$1.destructor = (void*)$2; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.name = $4;$n; $1.traceImpl = (void*)$5; $1.disposeImpl = (void*)$6;", [
|
||||
var flags = 0
|
||||
if not canFormAcycle(t): flags = flags or 1
|
||||
|
||||
addf(m.s[cfsTypeInit3], "$1.destructor = (void*)$2; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.name = $4;$n; $1.traceImpl = (void*)$5; $1.disposeImpl = (void*)$6; $1.flags = $7;", [
|
||||
name, destroyImpl, getTypeDesc(m, t), typeName,
|
||||
traceImpl, disposeImpl])
|
||||
traceImpl, disposeImpl, rope(flags)])
|
||||
|
||||
if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions:
|
||||
discard genTypeInfoV1(m, t, info)
|
||||
|
||||
@@ -244,7 +244,7 @@ proc safeLineNm(info: TLineInfo): int =
|
||||
|
||||
proc genCLineDir(r: var Rope, filename: string, line: int; conf: ConfigRef) =
|
||||
assert line >= 0
|
||||
if optLineDir in conf.options:
|
||||
if optLineDir in conf.options and line > 0:
|
||||
r.addf("$N#line $2 $1$N",
|
||||
[rope(makeSingleLineCString(filename)), rope(line)])
|
||||
|
||||
@@ -471,6 +471,14 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
|
||||
result.storage = OnStack
|
||||
result.flags = {}
|
||||
constructLoc(p, result, not needsInit)
|
||||
when false:
|
||||
# XXX Introduce a compiler switch in order to detect these easily.
|
||||
if getSize(p.config, t) > 1024 * 1024:
|
||||
if p.prc != nil:
|
||||
echo "ENORMOUS TEMPORARY! ", p.config $ p.prc.info
|
||||
else:
|
||||
echo "ENORMOUS TEMPORARY! ", p.config $ p.lastLineInfo
|
||||
writeStackTrace()
|
||||
|
||||
proc getTempCpp(p: BProc, t: PType, result: var TLoc; value: Rope) =
|
||||
inc(p.labels)
|
||||
@@ -847,7 +855,8 @@ proc containsResult(n: PNode): bool =
|
||||
for i in 0..<n.safeLen:
|
||||
if containsResult(n[i]): return true
|
||||
|
||||
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef, nkMacroDef} +
|
||||
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef,
|
||||
nkMacroDef, nkMixinStmt, nkBindStmt} +
|
||||
declarativeDefs
|
||||
|
||||
proc easyResultAsgn(n: PNode): PNode =
|
||||
@@ -1678,7 +1687,7 @@ proc genInitCode(m: BModule) =
|
||||
writeSection(preInitProc, cpsLocals)
|
||||
writeSection(preInitProc, cpsInit, m.hcrOn)
|
||||
writeSection(preInitProc, cpsStmts)
|
||||
prc.addf("}$N", [])
|
||||
prc.addf("}/* preInitProc end */$N", [])
|
||||
when false:
|
||||
m.initProc.blocks[0].sections[cpsLocals].add m.preInitProc.s(cpsLocals)
|
||||
m.initProc.blocks[0].sections[cpsInit].prepend m.preInitProc.s(cpsInit)
|
||||
@@ -2044,7 +2053,7 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
|
||||
if m.config.exc == excGoto and getCompilerProc(graph, "nimTestErrorFlag") != nil:
|
||||
discard cgsym(m, "nimTestErrorFlag")
|
||||
|
||||
if {optGenStaticLib, optGenDynLib} * m.config.globalOptions == {}:
|
||||
if {optGenStaticLib, optGenDynLib, optNoMain} * m.config.globalOptions == {}:
|
||||
for i in countdown(high(graph.globalDestructors), 0):
|
||||
n.add graph.globalDestructors[i]
|
||||
if passes.skipCodegen(m.config, n): return
|
||||
|
||||
@@ -156,7 +156,7 @@ type
|
||||
|
||||
const
|
||||
nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
|
||||
nkCommentStmt} + procDefs
|
||||
nkCommentStmt, nkMixinStmt, nkBindStmt} + procDefs
|
||||
|
||||
proc newStateAccess(ctx: var Ctx): PNode =
|
||||
if ctx.stateVarSym.isNil:
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Helpers for binaries that use compiler passes, eg: nim, nimsuggest, nimfix
|
||||
## Helpers for binaries that use compiler passes, e.g.: nim, nimsuggest, nimfix
|
||||
|
||||
import
|
||||
options, idents, nimconf, extccomp, commands, msgs,
|
||||
|
||||
@@ -145,7 +145,7 @@ proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TC
|
||||
proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
|
||||
info: TLineInfo) =
|
||||
case arg.normalize
|
||||
of "","on": conf.options.incl op
|
||||
of "", "on": conf.options.incl op
|
||||
of "off": conf.options.excl op
|
||||
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
|
||||
|
||||
@@ -193,12 +193,12 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
|
||||
elif i < arg.len and (arg[i] in {':', '='}): inc(i)
|
||||
else: invalidCmdLineOption(conf, pass, orig, info)
|
||||
if state == wHint:
|
||||
let x = findStr(lineinfos.HintsToStr, id)
|
||||
if x >= 0: n = TNoteKind(x + ord(hintMin))
|
||||
let x = findStr(hintMin..hintMax, id, errUnknown)
|
||||
if x != errUnknown: n = TNoteKind(x)
|
||||
else: localError(conf, info, "unknown hint: " & id)
|
||||
else:
|
||||
let x = findStr(lineinfos.WarningsToStr, id)
|
||||
if x >= 0: n = TNoteKind(x + ord(warnMin))
|
||||
let x = findStr(warnMin..warnMax, id, errUnknown)
|
||||
if x != errUnknown: n = TNoteKind(x)
|
||||
else: localError(conf, info, "unknown warning: " & id)
|
||||
|
||||
var val = substr(arg, i).normalize
|
||||
@@ -391,6 +391,19 @@ proc handleStdinInput*(conf: ConfigRef) =
|
||||
if conf.outDir.isEmpty:
|
||||
conf.outDir = getNimcacheDir(conf)
|
||||
|
||||
proc specialDefine(conf: ConfigRef, key: string) =
|
||||
# Keep this syncronized with the default config/nim.cfg!
|
||||
if cmpIgnoreStyle(key, "nimQuirky") == 0:
|
||||
conf.exc = excQuirky
|
||||
elif cmpIgnoreStyle(key, "release") == 0 or cmpIgnoreStyle(key, "danger") == 0:
|
||||
conf.options.excl {optStackTrace, optLineTrace, optLineDir, optOptimizeSize}
|
||||
conf.globalOptions.excl {optExcessiveStackTrace, optCDebug}
|
||||
conf.options.incl optOptimizeSpeed
|
||||
if cmpIgnoreStyle(key, "danger") == 0 or cmpIgnoreStyle(key, "quick") == 0:
|
||||
conf.options.excl {optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck,
|
||||
optOverflowCheck, optAssert, optStackTrace, optLineTrace, optLineDir}
|
||||
conf.globalOptions.excl {optCDebug}
|
||||
|
||||
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
conf: ConfigRef) =
|
||||
var
|
||||
@@ -450,12 +463,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if {':', '='} in arg:
|
||||
splitSwitch(conf, arg, key, val, pass, info)
|
||||
if cmpIgnoreStyle(key, "nimQuirky") == 0:
|
||||
conf.exc = excQuirky
|
||||
specialDefine(conf, key)
|
||||
defineSymbol(conf.symbols, key, val)
|
||||
else:
|
||||
if cmpIgnoreStyle(arg, "nimQuirky") == 0:
|
||||
conf.exc = excQuirky
|
||||
specialDefine(conf, arg)
|
||||
defineSymbol(conf.symbols, arg)
|
||||
of "undef", "u":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
@@ -485,7 +496,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "project":
|
||||
processOnOffSwitchG(conf, {optWholeProject, optGenIndex}, arg, pass, info)
|
||||
of "gc":
|
||||
if conf.backend == backendJs:
|
||||
if conf.backend == backendJs or conf.command == "js":
|
||||
# for: bug #16033
|
||||
# This might still be imperfect, in rarse corner cases
|
||||
# (where command is reset in nimscript, maybe).
|
||||
return
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}:
|
||||
@@ -851,6 +865,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "off": conf.globalOptions = conf.globalOptions - {optStyleHint, optStyleError}
|
||||
of "hint": conf.globalOptions = conf.globalOptions + {optStyleHint} - {optStyleError}
|
||||
of "error": conf.globalOptions = conf.globalOptions + {optStyleError}
|
||||
of "usages": conf.globalOptions.incl optStyleUsages
|
||||
else: localError(conf, info, errOffHintsError % arg)
|
||||
of "showallmismatches":
|
||||
processOnOffSwitchG(conf, {optShowAllMismatches}, arg, pass, info)
|
||||
|
||||
@@ -13,7 +13,7 @@ import
|
||||
strtabs
|
||||
|
||||
from options import Feature
|
||||
from lineinfos import HintsToStr, WarningsToStr
|
||||
from lineinfos import hintMin, hintMax, warnMin, warnMax
|
||||
|
||||
proc defineSymbol*(symbols: StringTableRef; symbol: string, value: string = "true") =
|
||||
symbols[symbol] = value
|
||||
@@ -89,10 +89,10 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
for f in Feature:
|
||||
defineSymbol("nimHas" & $f)
|
||||
|
||||
for s in WarningsToStr:
|
||||
defineSymbol("nimHasWarning" & s)
|
||||
for s in HintsToStr:
|
||||
defineSymbol("nimHasHint" & s)
|
||||
for s in warnMin..warnMax:
|
||||
defineSymbol("nimHasWarning" & $s)
|
||||
for s in hintMin..hintMax:
|
||||
defineSymbol("nimHasHint" & $s)
|
||||
|
||||
defineSymbol("nimFixedOwned")
|
||||
defineSymbol("nimHasStyleChecks")
|
||||
@@ -123,3 +123,4 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasStacktracesModule")
|
||||
defineSymbol("nimHasEffectTraitsModule")
|
||||
defineSymbol("nimHasCastPragmaBlocks")
|
||||
defineSymbol("nimHasJsBigIntBackend")
|
||||
|
||||
@@ -30,7 +30,7 @@ type
|
||||
ExampleGroup = ref object
|
||||
## a group of runnableExamples with same rdoccmd
|
||||
rdoccmd: string ## from 1st arg in `runnableExamples(rdoccmd): body`
|
||||
docCmd: string ## from user config, eg --doccmd:-d:foo
|
||||
docCmd: string ## from user config, e.g. --doccmd:-d:foo
|
||||
code: string ## contains imports; each import contains `body`
|
||||
index: int ## group index
|
||||
TDocumentor = object of rstgen.RstGenerator
|
||||
@@ -168,7 +168,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
|
||||
result.module = module
|
||||
result.conf = conf
|
||||
result.cache = cache
|
||||
result.outDir = conf.outDir
|
||||
result.outDir = conf.outDir.string
|
||||
initRstGenerator(result[], (if conf.cmd != cmdRst2tex: outHtml else: outLatex),
|
||||
conf.configVars, filename.string, {roSupportRawDirective, roSupportMarkdown},
|
||||
docgenFindFile, compilerMsgHandler)
|
||||
@@ -230,8 +230,8 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
|
||||
if gotten != status:
|
||||
rawMessage(conf, errGenerated, "snippet failed: cmd: '$1' status: $2 expected: $3 output: $4" % [cmd, $gotten, $status, output])
|
||||
result.emitted = initIntSet()
|
||||
result.destFile = getOutFile2(conf, presentationPath(conf, filename), outExt, false)
|
||||
result.thisDir = result.destFile.splitFile.dir
|
||||
result.destFile = getOutFile2(conf, presentationPath(conf, filename), outExt, false).string
|
||||
result.thisDir = result.destFile.AbsoluteFile.splitFile.dir
|
||||
|
||||
template dispA(conf: ConfigRef; dest: var Rope, xml, tex: string, args: openArray[Rope]) =
|
||||
if conf.cmd != cmdRst2tex: dest.addf(xml, args)
|
||||
@@ -457,7 +457,7 @@ proc writeExample(d: PDoc; ex: PNode, rdoccmd: string) =
|
||||
|
||||
proc runAllExamples(d: PDoc) =
|
||||
# This used to be: `let backend = if isDefined(d.conf, "js"): "js"` (etc), however
|
||||
# using `-d:js` (etc) cannot work properly, eg would fail with `importjs`
|
||||
# using `-d:js` (etc) cannot work properly, e.g. would fail with `importjs`
|
||||
# since semantics are affected by `config.backend`, not by isDefined(d.conf, "js")
|
||||
let outputDir = d.exampleOutputDir
|
||||
for _, group in d.exampleGroups:
|
||||
@@ -591,8 +591,10 @@ proc getRoutineBody(n: PNode): PNode =
|
||||
(0 or more) doc comments and runnableExamples.
|
||||
]##
|
||||
result = n[bodyPos]
|
||||
if result.kind == nkAsgn and n.len > bodyPos+1 and n[bodyPos+1].kind == nkSym:
|
||||
doAssert result[0].kind == nkSym
|
||||
|
||||
# This won't be transformed: result.id = 10. Namely result[0].kind != nkSym.
|
||||
if result.kind == nkAsgn and result[0].kind == nkSym and
|
||||
n.len > bodyPos+1 and n[bodyPos+1].kind == nkSym:
|
||||
doAssert result.len == 2
|
||||
result = result[1]
|
||||
|
||||
@@ -715,7 +717,7 @@ proc complexName(k: TSymKind, n: PNode, baseName: string): string =
|
||||
of skTemplate: result.add(".t")
|
||||
of skConverter: result.add(".c")
|
||||
else: discard
|
||||
if n.len > paramsPos and n[paramsPos].kind == nkFormalParams:
|
||||
if n.safeLen > paramsPos and n[paramsPos].kind == nkFormalParams:
|
||||
let params = renderParamTypes(n[paramsPos])
|
||||
if params.len > 0:
|
||||
result.add(defaultParamSeparator)
|
||||
@@ -849,7 +851,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
|
||||
symbolOrIdRope, plainSymbolEncRope, symbolOrIdEncRope, seeSrcRope,
|
||||
deprecationMsgRope]))
|
||||
|
||||
let external = d.destFile.relativeTo(d.conf.outDir, '/').changeFileExt(HtmlExt).string
|
||||
let external = d.destFile.AbsoluteFile.relativeTo(d.conf.outDir, '/').changeFileExt(HtmlExt).string
|
||||
|
||||
var attype: Rope
|
||||
if k in routineKinds and nameNode.kind == nkSym:
|
||||
@@ -866,19 +868,13 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
|
||||
xmltree.escape(getPlainDocstring(e).docstringSummary))
|
||||
|
||||
d.toc[k].add(ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item.toc"),
|
||||
["name", "header", "desc", "itemID", "header_plain", "itemSym",
|
||||
"itemSymOrID", "itemSymEnc", "itemSymOrIDEnc", "attype"],
|
||||
[rope(getName(d, nameNode, d.splitAfter)), result, comm,
|
||||
itemIDRope, plainNameRope, plainSymbolRope, symbolOrIdRope,
|
||||
plainSymbolEncRope, symbolOrIdEncRope, attype]))
|
||||
["name", "header_plain", "itemSymOrIDEnc"],
|
||||
[nameRope, plainNameRope, symbolOrIdEncRope]))
|
||||
|
||||
d.tocTable[k].mgetOrPut(cleanPlainSymbol, nil).add(ropeFormatNamedVars(
|
||||
d.conf, getConfigVar(d.conf, "doc.item.tocTable"),
|
||||
["name", "header", "desc", "itemID", "header_plain", "itemSym",
|
||||
"itemSymOrID", "itemSymEnc", "itemSymOrIDEnc", "attype"],
|
||||
[rope(getName(d, nameNode, d.splitAfter)), result, comm,
|
||||
itemIDRope, plainNameRope, plainSymbolRope,
|
||||
symbolOrIdRope, plainSymbolEncRope, symbolOrIdEncRope, attype]))
|
||||
["name", "header_plain", "itemSymOrID", "itemSymOrIDEnc"],
|
||||
[nameRope, plainNameRope, rope(symbolOrId.replace(",", ",<wbr>")), symbolOrIdEncRope]))
|
||||
|
||||
# Ironically for types the complexSymbol is *cleaner* than the plainName
|
||||
# because it doesn't include object fields or documentation comments. So we
|
||||
@@ -970,13 +966,17 @@ proc exportSym(d: PDoc; s: PSym) =
|
||||
elif s.kind != skModule and s.owner != nil:
|
||||
let module = originatingModule(s)
|
||||
if belongsToPackage(d.conf, module):
|
||||
let external = externalDep(d, module)
|
||||
let
|
||||
complexSymbol = complexName(s.kind, s.ast, s.name.s)
|
||||
symbolOrIdRope = rope(d.newUniquePlainSymbol(complexSymbol))
|
||||
external = externalDep(d, module)
|
||||
if d.section[k] != nil: d.section[k].add(", ")
|
||||
# XXX proper anchor generation here
|
||||
dispA(d.conf, d.section[k],
|
||||
"<a href=\"$2#$1\"><span class=\"Identifier\">$1</span></a>",
|
||||
"<a href=\"$2#$3\"><span class=\"Identifier\">$1</span></a>",
|
||||
"$1", [rope esc(d.target, s.name.s),
|
||||
rope changeFileExt(external, "html")])
|
||||
rope changeFileExt(external, "html"),
|
||||
symbolOrIdRope])
|
||||
|
||||
proc documentNewEffect(cache: IdentCache; n: PNode): PNode =
|
||||
let s = n[namePos].sym
|
||||
@@ -1002,7 +1002,7 @@ proc documentEffect(cache: IdentCache; n, x: PNode, effectType: TSpecialWord, id
|
||||
effects[i].typ = real[i].typ
|
||||
|
||||
result = newTreeI(nkExprColonExpr, n.info,
|
||||
newIdentNode(getIdent(cache, specialWords[effectType]), n.info), effects)
|
||||
newIdentNode(getIdent(cache, $effectType), n.info), effects)
|
||||
|
||||
proc documentWriteEffect(cache: IdentCache; n: PNode; flag: TSymFlag; pragmaName: string): PNode =
|
||||
let s = n[namePos].sym
|
||||
@@ -1079,7 +1079,7 @@ proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
|
||||
if it.kind == nkSym:
|
||||
if d.module != nil and d.module == it.sym.owner:
|
||||
generateDoc(d, it.sym.ast, orig, kForceExport)
|
||||
else:
|
||||
elif it.sym.ast != nil:
|
||||
exportSym(d, it.sym)
|
||||
of nkExportExceptStmt: discard "transformed into nkExportStmt by semExportExcept"
|
||||
of nkFromStmt, nkImportExceptStmt: traceDeps(d, n[0])
|
||||
@@ -1237,14 +1237,14 @@ proc genOutFile(d: PDoc, groupedToc = false): Rope =
|
||||
content = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, bodyname), ["title",
|
||||
"tableofcontents", "moduledesc", "date", "time", "content", "deprecationMsg", "theindexhref", "body_toc_groupsection"],
|
||||
[title.rope, toc, d.modDesc, rope(getDateStr()),
|
||||
rope(getClockStr()), code, d.modDeprecationMsg, relLink(d.conf.outDir, d.destFile, theindexFname.RelativeFile), groupsection.rope])
|
||||
rope(getClockStr()), code, d.modDeprecationMsg, relLink(d.conf.outDir, d.destFile.AbsoluteFile, theindexFname.RelativeFile), groupsection.rope])
|
||||
if optCompileOnly notin d.conf.globalOptions:
|
||||
# XXX what is this hack doing here? 'optCompileOnly' means raw output!?
|
||||
code = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.file"), [
|
||||
"nimdoccss", "dochackjs", "title", "tableofcontents", "moduledesc", "date", "time",
|
||||
"content", "author", "version", "analytics", "deprecationMsg"],
|
||||
[relLink(d.conf.outDir, d.destFile, nimdocOutCss.RelativeFile),
|
||||
relLink(d.conf.outDir, d.destFile, docHackJsFname.RelativeFile),
|
||||
[relLink(d.conf.outDir, d.destFile.AbsoluteFile, nimdocOutCss.RelativeFile),
|
||||
relLink(d.conf.outDir, d.destFile.AbsoluteFile, docHackJsFname.RelativeFile),
|
||||
title.rope, toc, d.modDesc, rope(getDateStr()), rope(getClockStr()),
|
||||
content, d.meta[metaAuthor].rope, d.meta[metaVersion].rope, d.analytics.rope, d.modDeprecationMsg])
|
||||
else:
|
||||
@@ -1259,7 +1259,7 @@ proc generateIndex*(d: PDoc) =
|
||||
writeIndexFile(d[], dest.string)
|
||||
|
||||
proc updateOutfile(d: PDoc, outfile: AbsoluteFile) =
|
||||
if d.module == nil or sfMainModule in d.module.flags: # nil for eg for commandRst2Html
|
||||
if d.module == nil or sfMainModule in d.module.flags: # nil for e.g. for commandRst2Html
|
||||
if d.conf.outFile.isEmpty:
|
||||
d.conf.outFile = outfile.relativeTo(d.conf.outDir)
|
||||
if isAbsolute(d.conf.outFile.string):
|
||||
@@ -1271,7 +1271,7 @@ proc writeOutput*(d: PDoc, useWarning = false, groupedToc = false) =
|
||||
if optStdout in d.conf.globalOptions:
|
||||
writeRope(stdout, content)
|
||||
else:
|
||||
template outfile: untyped = d.destFile
|
||||
template outfile: untyped = d.destFile.AbsoluteFile
|
||||
#let outfile = getOutFile2(d.conf, shortenDir(d.conf, filename), outExt)
|
||||
let dir = outfile.splitFile.dir
|
||||
createDir(dir)
|
||||
@@ -1300,13 +1300,13 @@ proc writeOutputJson*(d: PDoc, useWarning = false) =
|
||||
write(stdout, $content)
|
||||
else:
|
||||
var f: File
|
||||
if open(f, d.destFile.string, fmWrite):
|
||||
if open(f, d.destFile, fmWrite):
|
||||
write(f, $content)
|
||||
close(f)
|
||||
updateOutfile(d, d.destFile)
|
||||
updateOutfile(d, d.destFile.AbsoluteFile)
|
||||
else:
|
||||
localError(d.conf, newLineInfo(d.conf, AbsoluteFile d.filename, -1, -1),
|
||||
warnUser, "unable to open file \"" & d.destFile.string &
|
||||
warnUser, "unable to open file \"" & d.destFile &
|
||||
"\" for writing")
|
||||
|
||||
proc handleDocOutputOptions*(conf: ConfigRef) =
|
||||
|
||||
@@ -627,10 +627,7 @@ proc footprint(conf: ConfigRef; cfile: Cfile): SecureHash =
|
||||
getCompileCFileCmd(conf, cfile))
|
||||
|
||||
proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
|
||||
case conf.backend
|
||||
of backendInvalid: doAssert false
|
||||
of backendJs: return false # pre-existing behavior, but not sure it's good
|
||||
else: discard
|
||||
if conf.backend == backendJs: return false # pre-existing behavior, but not sure it's good
|
||||
|
||||
var hashFile = toGeneratedFile(conf, conf.withPackageName(cfile.cname), "sha1")
|
||||
var currentHash = footprint(conf, cfile)
|
||||
|
||||
@@ -110,8 +110,8 @@ proc newIdentCache*(): IdentCache =
|
||||
result.idDelegator = result.getIdent":delegator"
|
||||
result.emptyIdent = result.getIdent("")
|
||||
# initialize the keywords:
|
||||
for s in succ(low(specialWords))..high(specialWords):
|
||||
result.getIdent(specialWords[s], hashIgnoreStyle(specialWords[s])).id = ord(s)
|
||||
for s in succ(low(TSpecialWord))..high(TSpecialWord):
|
||||
result.getIdent($s, hashIgnoreStyle($s)).id = ord(s)
|
||||
|
||||
proc whichKeyword*(id: PIdent): TSpecialWord =
|
||||
if id.id < 0: result = wInvalid
|
||||
|
||||
@@ -37,7 +37,7 @@ type
|
||||
g: ControlFlowGraph
|
||||
graph: ModuleGraph
|
||||
otherRead: PNode
|
||||
inLoop, inSpawn: int
|
||||
inLoop, inSpawn, inLoopCond: int
|
||||
uninit: IntSet # set of uninit'ed vars
|
||||
uninitComputed: bool
|
||||
|
||||
@@ -295,8 +295,8 @@ proc isNoInit(dest: PNode): bool {.inline.} =
|
||||
result = dest.kind == nkSym and sfNoInit in dest.sym.flags
|
||||
|
||||
proc genSink(c: var Con; dest, ri: PNode, isDecl = false): PNode =
|
||||
if isUnpackedTuple(dest) or isDecl or
|
||||
(isAnalysableFieldAccess(dest, c.owner) and isFirstWrite(dest, c)) or
|
||||
if (c.inLoopCond == 0 and (isUnpackedTuple(dest) or isDecl or
|
||||
(isAnalysableFieldAccess(dest, c.owner) and isFirstWrite(dest, c)))) or
|
||||
isNoInit(dest):
|
||||
# optimize sink call into a bitwise memcopy
|
||||
result = newTree(nkFastAsgn, dest, ri)
|
||||
@@ -588,8 +588,10 @@ template handleNestedTempl(n, processCall: untyped, willProduceStmt = false) =
|
||||
|
||||
of nkWhileStmt:
|
||||
inc c.inLoop
|
||||
inc c.inLoopCond
|
||||
result = copyNode(n)
|
||||
result.add p(n[0], c, s, normal)
|
||||
dec c.inLoopCond
|
||||
var bodyScope = nestedScope(s)
|
||||
let bodyResult = p(n[1], c, bodyScope, normal)
|
||||
result.add processScope(c, bodyScope, bodyResult)
|
||||
@@ -823,14 +825,10 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
|
||||
of nkAsgn, nkFastAsgn:
|
||||
if hasDestructor(c, n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda} and
|
||||
not isCursor(n[0], c):
|
||||
# rule (self-assignment-removal):
|
||||
if n[1].kind == nkSym and n[0].kind == nkSym and n[0].sym == n[1].sym:
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
else:
|
||||
if n[0].kind in {nkDotExpr, nkCheckedFieldExpr}:
|
||||
cycleCheck(n, c)
|
||||
assert n[1].kind notin {nkAsgn, nkFastAsgn}
|
||||
result = moveOrCopy(p(n[0], c, s, mode), n[1], c, s)
|
||||
if n[0].kind in {nkDotExpr, nkCheckedFieldExpr}:
|
||||
cycleCheck(n, c)
|
||||
assert n[1].kind notin {nkAsgn, nkFastAsgn}
|
||||
result = moveOrCopy(p(n[0], c, s, mode), n[1], c, s)
|
||||
elif isDiscriminantField(n[0]):
|
||||
result = c.genDiscriminantAsgn(s, n)
|
||||
else:
|
||||
@@ -845,7 +843,8 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
|
||||
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef,
|
||||
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
|
||||
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState, nkTypeOfExpr:
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
|
||||
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
|
||||
result = n
|
||||
|
||||
of nkStringToCString, nkCStringToString, nkChckRangeF, nkChckRange64, nkChckRange, nkPragmaBlock:
|
||||
@@ -953,8 +952,11 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNod
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
||||
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
||||
of nkSym:
|
||||
if isSinkParam(ri.sym) and isLastRead(ri, c):
|
||||
of nkSym:
|
||||
if dest.kind == nkSym and dest.sym == ri.sym:
|
||||
# rule (self-assignment-removal):
|
||||
result = newNodeI(nkEmpty, dest.info)
|
||||
elif isSinkParam(ri.sym) and isLastRead(ri, c):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
let snk = c.genSink(dest, ri, isDecl)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
|
||||
@@ -6,10 +6,10 @@ Name: "Nim"
|
||||
Version: "$version"
|
||||
Platforms: """
|
||||
windows: i386;amd64
|
||||
linux: i386;hppa;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv64
|
||||
macosx: i386;amd64;powerpc64
|
||||
linux: i386;hppa;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv32;riscv64
|
||||
macosx: i386;amd64;powerpc64;arm64
|
||||
solaris: i386;amd64;sparc;sparc64
|
||||
freebsd: i386;amd64;powerpc64;arm;arm64;riscv64;sparc64;mips;mipsel;mips64;mips64el;powerpc
|
||||
freebsd: i386;amd64;powerpc64;arm;arm64;riscv64;sparc64;mips;mipsel;mips64;mips64el;powerpc;powerpc64el
|
||||
netbsd: i386;amd64
|
||||
openbsd: i386;amd64;arm;arm64
|
||||
dragonfly: i386;amd64
|
||||
@@ -110,6 +110,7 @@ Download: r"Aporia Text Editor|dist|aporia.zip|97997|https://nim-lang.org/downlo
|
||||
Files: "bin/makelink.exe"
|
||||
Files: "bin/7zG.exe"
|
||||
Files: "bin/*.dll"
|
||||
Files: "bin/cacert.pem"
|
||||
|
||||
[UnixBin]
|
||||
Files: "bin/nim"
|
||||
|
||||
@@ -592,190 +592,3 @@ proc maskBytes*(arg: Int128, numbytes: int): Int128 {.noinit.} =
|
||||
return maskUInt64(arg)
|
||||
else:
|
||||
assert(false, "masking only implemented for 1, 2, 4 and 8 bytes")
|
||||
|
||||
|
||||
|
||||
|
||||
when isMainModule:
|
||||
let (a,b) = divMod(Ten,Ten)
|
||||
|
||||
doAssert $One == "1"
|
||||
doAssert $Ten == "10"
|
||||
doAssert $Zero == "0"
|
||||
let c = parseDecimalInt128("12345678989876543210123456789")
|
||||
doAssert $c == "12345678989876543210123456789"
|
||||
|
||||
var d : array[39, Int128]
|
||||
d[0] = parseDecimalInt128("1")
|
||||
d[1] = parseDecimalInt128("10")
|
||||
d[2] = parseDecimalInt128("100")
|
||||
d[3] = parseDecimalInt128("1000")
|
||||
d[4] = parseDecimalInt128("10000")
|
||||
d[5] = parseDecimalInt128("100000")
|
||||
d[6] = parseDecimalInt128("1000000")
|
||||
d[7] = parseDecimalInt128("10000000")
|
||||
d[8] = parseDecimalInt128("100000000")
|
||||
d[9] = parseDecimalInt128("1000000000")
|
||||
d[10] = parseDecimalInt128("10000000000")
|
||||
d[11] = parseDecimalInt128("100000000000")
|
||||
d[12] = parseDecimalInt128("1000000000000")
|
||||
d[13] = parseDecimalInt128("10000000000000")
|
||||
d[14] = parseDecimalInt128("100000000000000")
|
||||
d[15] = parseDecimalInt128("1000000000000000")
|
||||
d[16] = parseDecimalInt128("10000000000000000")
|
||||
d[17] = parseDecimalInt128("100000000000000000")
|
||||
d[18] = parseDecimalInt128("1000000000000000000")
|
||||
d[19] = parseDecimalInt128("10000000000000000000")
|
||||
d[20] = parseDecimalInt128("100000000000000000000")
|
||||
d[21] = parseDecimalInt128("1000000000000000000000")
|
||||
d[22] = parseDecimalInt128("10000000000000000000000")
|
||||
d[23] = parseDecimalInt128("100000000000000000000000")
|
||||
d[24] = parseDecimalInt128("1000000000000000000000000")
|
||||
d[25] = parseDecimalInt128("10000000000000000000000000")
|
||||
d[26] = parseDecimalInt128("100000000000000000000000000")
|
||||
d[27] = parseDecimalInt128("1000000000000000000000000000")
|
||||
d[28] = parseDecimalInt128("10000000000000000000000000000")
|
||||
d[29] = parseDecimalInt128("100000000000000000000000000000")
|
||||
d[30] = parseDecimalInt128("1000000000000000000000000000000")
|
||||
d[31] = parseDecimalInt128("10000000000000000000000000000000")
|
||||
d[32] = parseDecimalInt128("100000000000000000000000000000000")
|
||||
d[33] = parseDecimalInt128("1000000000000000000000000000000000")
|
||||
d[34] = parseDecimalInt128("10000000000000000000000000000000000")
|
||||
d[35] = parseDecimalInt128("100000000000000000000000000000000000")
|
||||
d[36] = parseDecimalInt128("1000000000000000000000000000000000000")
|
||||
d[37] = parseDecimalInt128("10000000000000000000000000000000000000")
|
||||
d[38] = parseDecimalInt128("100000000000000000000000000000000000000")
|
||||
|
||||
for i in 0..<d.len:
|
||||
for j in 0..<d.len:
|
||||
doAssert(cmp(d[i], d[j]) == cmp(i,j))
|
||||
if i + j < d.len:
|
||||
doAssert d[i] * d[j] == d[i+j]
|
||||
if i - j >= 0:
|
||||
doAssert d[i] div d[j] == d[i-j]
|
||||
|
||||
var sum: Int128
|
||||
|
||||
for it in d:
|
||||
sum += it
|
||||
|
||||
doAssert $sum == "111111111111111111111111111111111111111"
|
||||
|
||||
for it in d.mitems:
|
||||
it = -it
|
||||
|
||||
for i in 0..<d.len:
|
||||
for j in 0..<d.len:
|
||||
doAssert(cmp(d[i], d[j]) == -cmp(i,j))
|
||||
if i + j < d.len:
|
||||
doAssert d[i] * d[j] == -d[i+j]
|
||||
if i - j >= 0:
|
||||
doAssert d[i] div d[j] == -d[i-j]
|
||||
|
||||
doAssert $high(Int128) == "170141183460469231731687303715884105727"
|
||||
doAssert $low(Int128) == "-170141183460469231731687303715884105728"
|
||||
|
||||
var ma = 100'i64
|
||||
var mb = 13
|
||||
|
||||
doAssert toInt128(ma) * toInt128(0) == toInt128(0)
|
||||
doAssert toInt128(-ma) * toInt128(0) == toInt128(0)
|
||||
|
||||
# sign correctness
|
||||
doAssert divMod(toInt128( ma),toInt128( mb)) == (toInt128( ma div mb), toInt128( ma mod mb))
|
||||
doAssert divMod(toInt128(-ma),toInt128( mb)) == (toInt128(-ma div mb), toInt128(-ma mod mb))
|
||||
doAssert divMod(toInt128( ma),toInt128(-mb)) == (toInt128( ma div -mb), toInt128( ma mod -mb))
|
||||
doAssert divMod(toInt128(-ma),toInt128(-mb)) == (toInt128(-ma div -mb), toInt128(-ma mod -mb))
|
||||
|
||||
doAssert divMod(toInt128( mb),toInt128( mb)) == (toInt128( mb div mb), toInt128( mb mod mb))
|
||||
doAssert divMod(toInt128(-mb),toInt128( mb)) == (toInt128(-mb div mb), toInt128(-mb mod mb))
|
||||
doAssert divMod(toInt128( mb),toInt128(-mb)) == (toInt128( mb div -mb), toInt128( mb mod -mb))
|
||||
doAssert divMod(toInt128(-mb),toInt128(-mb)) == (toInt128(-mb div -mb), toInt128(-mb mod -mb))
|
||||
|
||||
doAssert divMod(toInt128( mb),toInt128( ma)) == (toInt128( mb div ma), toInt128( mb mod ma))
|
||||
doAssert divMod(toInt128(-mb),toInt128( ma)) == (toInt128(-mb div ma), toInt128(-mb mod ma))
|
||||
doAssert divMod(toInt128( mb),toInt128(-ma)) == (toInt128( mb div -ma), toInt128( mb mod -ma))
|
||||
doAssert divMod(toInt128(-mb),toInt128(-ma)) == (toInt128(-mb div -ma), toInt128(-mb mod -ma))
|
||||
|
||||
let e = parseDecimalInt128("70997106675279150998592376708984375")
|
||||
|
||||
let strArray = [
|
||||
# toHex(e shr 0), toHex(e shr 1), toHex(e shr 2), toHex(e shr 3)
|
||||
"000dac6d782d266a37300c32591eee37", "0006d636bc1693351b9806192c8f771b", "00036b1b5e0b499a8dcc030c9647bb8d", "0001b58daf05a4cd46e601864b23ddc6",
|
||||
"0000dac6d782d266a37300c32591eee3", "00006d636bc1693351b9806192c8f771", "000036b1b5e0b499a8dcc030c9647bb8", "00001b58daf05a4cd46e601864b23ddc",
|
||||
"00000dac6d782d266a37300c32591eee", "000006d636bc1693351b9806192c8f77", "0000036b1b5e0b499a8dcc030c9647bb", "000001b58daf05a4cd46e601864b23dd",
|
||||
"000000dac6d782d266a37300c32591ee", "0000006d636bc1693351b9806192c8f7", "00000036b1b5e0b499a8dcc030c9647b", "0000001b58daf05a4cd46e601864b23d",
|
||||
"0000000dac6d782d266a37300c32591e", "00000006d636bc1693351b9806192c8f", "000000036b1b5e0b499a8dcc030c9647", "00000001b58daf05a4cd46e601864b23",
|
||||
"00000000dac6d782d266a37300c32591", "000000006d636bc1693351b9806192c8", "0000000036b1b5e0b499a8dcc030c964", "000000001b58daf05a4cd46e601864b2",
|
||||
"000000000dac6d782d266a37300c3259", "0000000006d636bc1693351b9806192c", "00000000036b1b5e0b499a8dcc030c96", "0000000001b58daf05a4cd46e601864b",
|
||||
"0000000000dac6d782d266a37300c325", "00000000006d636bc1693351b9806192", "000000000036b1b5e0b499a8dcc030c9", "00000000001b58daf05a4cd46e601864",
|
||||
"00000000000dac6d782d266a37300c32", "000000000006d636bc1693351b980619", "0000000000036b1b5e0b499a8dcc030c", "000000000001b58daf05a4cd46e60186",
|
||||
"000000000000dac6d782d266a37300c3", "0000000000006d636bc1693351b98061", "00000000000036b1b5e0b499a8dcc030", "0000000000001b58daf05a4cd46e6018",
|
||||
"0000000000000dac6d782d266a37300c", "00000000000006d636bc1693351b9806", "000000000000036b1b5e0b499a8dcc03", "00000000000001b58daf05a4cd46e601",
|
||||
"00000000000000dac6d782d266a37300", "000000000000006d636bc1693351b980", "0000000000000036b1b5e0b499a8dcc0", "000000000000001b58daf05a4cd46e60",
|
||||
"000000000000000dac6d782d266a3730", "0000000000000006d636bc1693351b98", "00000000000000036b1b5e0b499a8dcc", "0000000000000001b58daf05a4cd46e6",
|
||||
"0000000000000000dac6d782d266a373", "00000000000000006d636bc1693351b9", "000000000000000036b1b5e0b499a8dc", "00000000000000001b58daf05a4cd46e",
|
||||
"00000000000000000dac6d782d266a37", "000000000000000006d636bc1693351b", "0000000000000000036b1b5e0b499a8d", "000000000000000001b58daf05a4cd46",
|
||||
"000000000000000000dac6d782d266a3", "0000000000000000006d636bc1693351", "00000000000000000036b1b5e0b499a8", "0000000000000000001b58daf05a4cd4",
|
||||
"0000000000000000000dac6d782d266a", "00000000000000000006d636bc169335", "000000000000000000036b1b5e0b499a", "00000000000000000001b58daf05a4cd",
|
||||
"00000000000000000000dac6d782d266", "000000000000000000006d636bc16933", "0000000000000000000036b1b5e0b499", "000000000000000000001b58daf05a4c",
|
||||
"000000000000000000000dac6d782d26", "0000000000000000000006d636bc1693", "00000000000000000000036b1b5e0b49", "0000000000000000000001b58daf05a4",
|
||||
"0000000000000000000000dac6d782d2", "00000000000000000000006d636bc169", "000000000000000000000036b1b5e0b4", "00000000000000000000001b58daf05a",
|
||||
"00000000000000000000000dac6d782d", "000000000000000000000006d636bc16", "0000000000000000000000036b1b5e0b", "000000000000000000000001b58daf05",
|
||||
"000000000000000000000000dac6d782", "0000000000000000000000006d636bc1", "00000000000000000000000036b1b5e0", "0000000000000000000000001b58daf0",
|
||||
"0000000000000000000000000dac6d78", "00000000000000000000000006d636bc", "000000000000000000000000036b1b5e", "00000000000000000000000001b58daf",
|
||||
"00000000000000000000000000dac6d7", "000000000000000000000000006d636b", "0000000000000000000000000036b1b5", "000000000000000000000000001b58da",
|
||||
"000000000000000000000000000dac6d", "0000000000000000000000000006d636", "00000000000000000000000000036b1b", "0000000000000000000000000001b58d",
|
||||
"0000000000000000000000000000dac6", "00000000000000000000000000006d63", "000000000000000000000000000036b1", "00000000000000000000000000001b58",
|
||||
"00000000000000000000000000000dac", "000000000000000000000000000006d6", "0000000000000000000000000000036b", "000000000000000000000000000001b5",
|
||||
"000000000000000000000000000000da", "0000000000000000000000000000006d", "00000000000000000000000000000036", "0000000000000000000000000000001b",
|
||||
"0000000000000000000000000000000d", "00000000000000000000000000000006", "00000000000000000000000000000003", "00000000000000000000000000000001",
|
||||
"00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
|
||||
]
|
||||
|
||||
for i in 0 ..< 128:
|
||||
let str1 = toHex(e shr i)
|
||||
let str2 = strArray[i]
|
||||
doAssert str1 == str2
|
||||
|
||||
let strArray2 = [
|
||||
"000dac6d782d266a37300c32591eee37", "001b58daf05a4cd46e601864b23ddc6e", "0036b1b5e0b499a8dcc030c9647bb8dc", "006d636bc1693351b9806192c8f771b8",
|
||||
"00dac6d782d266a37300c32591eee370", "01b58daf05a4cd46e601864b23ddc6e0", "036b1b5e0b499a8dcc030c9647bb8dc0", "06d636bc1693351b9806192c8f771b80",
|
||||
"0dac6d782d266a37300c32591eee3700", "1b58daf05a4cd46e601864b23ddc6e00", "36b1b5e0b499a8dcc030c9647bb8dc00", "6d636bc1693351b9806192c8f771b800",
|
||||
"dac6d782d266a37300c32591eee37000", "b58daf05a4cd46e601864b23ddc6e000", "6b1b5e0b499a8dcc030c9647bb8dc000", "d636bc1693351b9806192c8f771b8000",
|
||||
"ac6d782d266a37300c32591eee370000", "58daf05a4cd46e601864b23ddc6e0000", "b1b5e0b499a8dcc030c9647bb8dc0000", "636bc1693351b9806192c8f771b80000",
|
||||
"c6d782d266a37300c32591eee3700000", "8daf05a4cd46e601864b23ddc6e00000", "1b5e0b499a8dcc030c9647bb8dc00000", "36bc1693351b9806192c8f771b800000",
|
||||
"6d782d266a37300c32591eee37000000", "daf05a4cd46e601864b23ddc6e000000", "b5e0b499a8dcc030c9647bb8dc000000", "6bc1693351b9806192c8f771b8000000",
|
||||
"d782d266a37300c32591eee370000000", "af05a4cd46e601864b23ddc6e0000000", "5e0b499a8dcc030c9647bb8dc0000000", "bc1693351b9806192c8f771b80000000",
|
||||
"782d266a37300c32591eee3700000000", "f05a4cd46e601864b23ddc6e00000000", "e0b499a8dcc030c9647bb8dc00000000", "c1693351b9806192c8f771b800000000",
|
||||
"82d266a37300c32591eee37000000000", "05a4cd46e601864b23ddc6e000000000", "0b499a8dcc030c9647bb8dc000000000", "1693351b9806192c8f771b8000000000",
|
||||
"2d266a37300c32591eee370000000000", "5a4cd46e601864b23ddc6e0000000000", "b499a8dcc030c9647bb8dc0000000000", "693351b9806192c8f771b80000000000",
|
||||
"d266a37300c32591eee3700000000000", "a4cd46e601864b23ddc6e00000000000", "499a8dcc030c9647bb8dc00000000000", "93351b9806192c8f771b800000000000",
|
||||
"266a37300c32591eee37000000000000", "4cd46e601864b23ddc6e000000000000", "99a8dcc030c9647bb8dc000000000000", "3351b9806192c8f771b8000000000000",
|
||||
"66a37300c32591eee370000000000000", "cd46e601864b23ddc6e0000000000000", "9a8dcc030c9647bb8dc0000000000000", "351b9806192c8f771b80000000000000",
|
||||
"6a37300c32591eee3700000000000000", "d46e601864b23ddc6e00000000000000", "a8dcc030c9647bb8dc00000000000000", "51b9806192c8f771b800000000000000",
|
||||
"a37300c32591eee37000000000000000", "46e601864b23ddc6e000000000000000", "8dcc030c9647bb8dc000000000000000", "1b9806192c8f771b8000000000000000",
|
||||
"37300c32591eee370000000000000000", "6e601864b23ddc6e0000000000000000", "dcc030c9647bb8dc0000000000000000", "b9806192c8f771b80000000000000000",
|
||||
"7300c32591eee3700000000000000000", "e601864b23ddc6e00000000000000000", "cc030c9647bb8dc00000000000000000", "9806192c8f771b800000000000000000",
|
||||
"300c32591eee37000000000000000000", "601864b23ddc6e000000000000000000", "c030c9647bb8dc000000000000000000", "806192c8f771b8000000000000000000",
|
||||
"00c32591eee370000000000000000000", "01864b23ddc6e0000000000000000000", "030c9647bb8dc0000000000000000000", "06192c8f771b80000000000000000000",
|
||||
"0c32591eee3700000000000000000000", "1864b23ddc6e00000000000000000000", "30c9647bb8dc00000000000000000000", "6192c8f771b800000000000000000000",
|
||||
"c32591eee37000000000000000000000", "864b23ddc6e000000000000000000000", "0c9647bb8dc000000000000000000000", "192c8f771b8000000000000000000000",
|
||||
"32591eee370000000000000000000000", "64b23ddc6e0000000000000000000000", "c9647bb8dc0000000000000000000000", "92c8f771b80000000000000000000000",
|
||||
"2591eee3700000000000000000000000", "4b23ddc6e00000000000000000000000", "9647bb8dc00000000000000000000000", "2c8f771b800000000000000000000000",
|
||||
"591eee37000000000000000000000000", "b23ddc6e000000000000000000000000", "647bb8dc000000000000000000000000", "c8f771b8000000000000000000000000",
|
||||
"91eee370000000000000000000000000", "23ddc6e0000000000000000000000000", "47bb8dc0000000000000000000000000", "8f771b80000000000000000000000000",
|
||||
"1eee3700000000000000000000000000", "3ddc6e00000000000000000000000000", "7bb8dc00000000000000000000000000", "f771b800000000000000000000000000",
|
||||
"eee37000000000000000000000000000", "ddc6e000000000000000000000000000", "bb8dc000000000000000000000000000", "771b8000000000000000000000000000",
|
||||
"ee370000000000000000000000000000", "dc6e0000000000000000000000000000", "b8dc0000000000000000000000000000", "71b80000000000000000000000000000",
|
||||
"e3700000000000000000000000000000", "c6e00000000000000000000000000000", "8dc00000000000000000000000000000", "1b800000000000000000000000000000",
|
||||
"37000000000000000000000000000000", "6e000000000000000000000000000000", "dc000000000000000000000000000000", "b8000000000000000000000000000000",
|
||||
"70000000000000000000000000000000", "e0000000000000000000000000000000", "c0000000000000000000000000000000", "80000000000000000000000000000000",
|
||||
]
|
||||
|
||||
for i in 0 ..< 128:
|
||||
let str1 = toHex(e shl i)
|
||||
let str2 = strArray2[i]
|
||||
doAssert str1 == str2
|
||||
|
||||
@@ -64,9 +64,18 @@ proc canAlias(arg, ret: PType; marker: var IntSet): bool =
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc isValueOnlyType(t: PType): bool =
|
||||
# t doesn't contain pointers and references
|
||||
proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr, tyVar, tyLent}
|
||||
result = not types.searchTypeFor(t, wrap)
|
||||
|
||||
proc canAlias*(arg, ret: PType): bool =
|
||||
var marker = initIntSet()
|
||||
result = canAlias(arg, ret, marker)
|
||||
if isValueOnlyType(arg):
|
||||
# can alias only with unsafeAddr(arg.x) and we don't care if it is not safe
|
||||
result = false
|
||||
else:
|
||||
var marker = initIntSet()
|
||||
result = canAlias(arg, ret, marker)
|
||||
|
||||
proc checkIsolate*(n: PNode): bool =
|
||||
if types.containsTyRef(n.typ):
|
||||
|
||||
@@ -14,27 +14,28 @@ The JS code generator contains only 2 tricks:
|
||||
|
||||
Trick 1
|
||||
-------
|
||||
Some locations (for example 'var int') require "fat pointers" (``etyBaseIndex``)
|
||||
Some locations (for example 'var int') require "fat pointers" (`etyBaseIndex`)
|
||||
which are pairs (array, index). The derefence operation is then 'array[index]'.
|
||||
Check ``mapType`` for the details.
|
||||
Check `mapType` for the details.
|
||||
|
||||
Trick 2
|
||||
-------
|
||||
It is preferable to generate '||' and '&&' if possible since that is more
|
||||
idiomatic and hence should be friendlier for the JS JIT implementation. However
|
||||
code like ``foo and (let bar = baz())`` cannot be translated this way. Instead
|
||||
the expressions need to be transformed into statements. ``isSimpleExpr``
|
||||
code like `foo and (let bar = baz())` cannot be translated this way. Instead
|
||||
the expressions need to be transformed into statements. `isSimpleExpr`
|
||||
implements the required case distinction.
|
||||
"""
|
||||
|
||||
|
||||
import
|
||||
ast, strutils, trees, magicsys, options,
|
||||
nversion, msgs, idents, types, tables,
|
||||
ropes, math, passes, ccgutils, wordrecg, renderer,
|
||||
intsets, cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
|
||||
transf, injectdestructors, sourcemap, json, sets
|
||||
ast, trees, magicsys, options,
|
||||
nversion, msgs, idents, types,
|
||||
ropes, passes, ccgutils, wordrecg, renderer,
|
||||
cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
|
||||
transf, injectdestructors, sourcemap
|
||||
|
||||
import json, sets, math, tables, intsets, strutils
|
||||
|
||||
from modulegraphs import ModuleGraph, PPassContext
|
||||
|
||||
@@ -865,6 +866,7 @@ proc genRaiseStmt(p: PProc, n: PNode) =
|
||||
proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
|
||||
var
|
||||
cond, stmt: TCompRes
|
||||
totalRange = 0
|
||||
genLineDir(p, n)
|
||||
gen(p, n[0], cond)
|
||||
let stringSwitch = skipTypes(n[0].typ, abstractVar).kind == tyString
|
||||
@@ -884,6 +886,10 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
|
||||
let e = it[j]
|
||||
if e.kind == nkRange:
|
||||
var v = copyNode(e[0])
|
||||
inc(totalRange, int(e[1].intVal - v.intVal))
|
||||
if totalRange > 65535:
|
||||
localError(p.config, n.info,
|
||||
"Your case statement contains too many branches, consider using if/else instead!")
|
||||
while v.intVal <= e[1].intVal:
|
||||
gen(p, v, cond)
|
||||
lineF(p, "case $1:$n", [cond.rdLoc])
|
||||
@@ -1044,6 +1050,10 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
||||
var a, b: TCompRes
|
||||
var xtyp = mapType(p, x.typ)
|
||||
|
||||
# disable `[]=` for cstring
|
||||
if x.kind == nkBracketExpr and x.len >= 2 and x[0].typ.skipTypes(abstractInst).kind == tyCString:
|
||||
localError(p.config, x.info, "cstring doesn't support `[]=` operator")
|
||||
|
||||
gen(p, x, a)
|
||||
genLineDir(p, y)
|
||||
gen(p, y, b)
|
||||
@@ -1336,7 +1346,15 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of nkStmtListExpr:
|
||||
if n.len == 1: gen(p, n[0], r)
|
||||
else: internalError(p.config, n[0].info, "genAddr for complex nkStmtListExpr")
|
||||
else: internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
|
||||
of nkCallKinds:
|
||||
if n[0].typ.kind == tyOpenArray:
|
||||
# 'var openArray' for instance produces an 'addr' but this is harmless:
|
||||
# namely toOpenArray(a, 1, 3)
|
||||
gen(p, n[0], r)
|
||||
else:
|
||||
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
|
||||
else:
|
||||
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
|
||||
|
||||
proc attachProc(p: PProc; content: Rope; s: PSym) =
|
||||
p.g.code.add(content)
|
||||
@@ -1409,7 +1427,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
||||
s.name.s)
|
||||
discard mangleName(p.module, s)
|
||||
r.res = s.loc.r
|
||||
if lfNoDecl in s.loc.flags or s.magic != mNone or
|
||||
if lfNoDecl in s.loc.flags or s.magic notin {mNone, mIsolate} or
|
||||
{sfImportc, sfInfixCall} * s.flags != {}:
|
||||
discard
|
||||
elif s.kind == skMethod and s.getBody.kind == nkEmpty:
|
||||
@@ -1663,7 +1681,10 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
var t = skipTypes(typ, abstractInst)
|
||||
case t.kind
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar:
|
||||
result = putToSeq("0", indirect)
|
||||
if $t.sym.loc.r == "bigint":
|
||||
result = putToSeq("0n", indirect)
|
||||
else:
|
||||
result = putToSeq("0", indirect)
|
||||
of tyFloat..tyFloat128:
|
||||
result = putToSeq("0.0", indirect)
|
||||
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned:
|
||||
@@ -1736,6 +1757,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||
varCode: string
|
||||
varName = mangleName(p.module, v)
|
||||
useReloadingGuard = sfGlobal in v.flags and p.config.hcrOn
|
||||
useGlobalPragmas = sfGlobal in v.flags and ({sfPure, sfThread} * v.flags != {})
|
||||
|
||||
if v.constraint.isNil:
|
||||
if useReloadingGuard:
|
||||
@@ -1743,6 +1765,10 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||
lineF(p, "if ($1 === undefined) {$n", varName)
|
||||
varCode = $varName
|
||||
inc p.extraIndent
|
||||
elif useGlobalPragmas:
|
||||
lineF(p, "if (globalThis.$1 === undefined) {$n", varName)
|
||||
varCode = $varName
|
||||
inc p.extraIndent
|
||||
else:
|
||||
varCode = "var $2"
|
||||
else:
|
||||
@@ -1795,7 +1821,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||
else:
|
||||
line(p, runtimeFormat(varCode & " = $3;$n", [returnType, v.loc.r, s]))
|
||||
|
||||
if useReloadingGuard:
|
||||
if useReloadingGuard or useGlobalPragmas:
|
||||
dec p.extraIndent
|
||||
lineF(p, "}$n")
|
||||
|
||||
@@ -1922,6 +1948,7 @@ proc genRepr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
genReprAux(p, n, r, "reprJSONStringify")
|
||||
else:
|
||||
genReprAux(p, n, r, "reprAny", genTypeInfo(p, t))
|
||||
r.kind = resExpr
|
||||
|
||||
proc genOf(p: PProc, n: PNode, r: var TCompRes) =
|
||||
var x: TCompRes
|
||||
@@ -1979,7 +2006,9 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||
gen(p, n[2], rhs)
|
||||
|
||||
if skipTypes(n[1].typ, abstractVarRange).kind == tyCString:
|
||||
r.res = "$1 += $2;" % [lhs.rdLoc, rhs.rdLoc]
|
||||
let (b, tmp) = maybeMakeTemp(p, n[2], rhs)
|
||||
r.res = "if (null != $1) { if (null == $2) $2 = $3; else $2 += $3; }" %
|
||||
[b, lhs.rdLoc, tmp]
|
||||
else:
|
||||
let (a, tmp) = maybeMakeTemp(p, n[1], lhs)
|
||||
r.res = "$1.push.apply($3, $2);" % [a, rhs.rdLoc, tmp]
|
||||
@@ -2030,9 +2059,23 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of mDestroy: discard "ignore calls to the default destructor"
|
||||
of mOrd: genOrd(p, n, r)
|
||||
of mLengthStr, mLengthSeq, mLengthOpenArray, mLengthArray:
|
||||
unaryExpr(p, n, r, "", "($1).length")
|
||||
var x: TCompRes
|
||||
gen(p, n[1], x)
|
||||
if skipTypes(n[1].typ, abstractInst).kind == tyCString:
|
||||
let (a, tmp) = maybeMakeTemp(p, n[1], x)
|
||||
r.res = "(($1) == null ? 0 : ($2).length)" % [a, tmp]
|
||||
else:
|
||||
r.res = "($1).length" % [x.rdLoc]
|
||||
r.kind = resExpr
|
||||
of mHigh:
|
||||
unaryExpr(p, n, r, "", "(($1).length-1)")
|
||||
var x: TCompRes
|
||||
gen(p, n[1], x)
|
||||
if skipTypes(n[1].typ, abstractInst).kind == tyCString:
|
||||
let (a, tmp) = maybeMakeTemp(p, n[1], x)
|
||||
r.res = "(($1) == null ? -1 : ($2).length - 1)" % [a, tmp]
|
||||
else:
|
||||
r.res = "($1).length - 1" % [x.rdLoc]
|
||||
r.kind = resExpr
|
||||
of mInc:
|
||||
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
|
||||
binaryUintExpr(p, n, r, "+", true)
|
||||
@@ -2193,11 +2236,17 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) =
|
||||
if dest.kind == src.kind:
|
||||
# no-op conversion
|
||||
return
|
||||
case dest.kind:
|
||||
of tyBool:
|
||||
let toInt = (dest.kind in tyInt..tyInt32)
|
||||
let fromInt = (src.kind in tyInt..tyInt32)
|
||||
let toUint = (dest.kind in tyUInt..tyUInt32)
|
||||
let fromUint = (src.kind in tyUInt..tyUInt32)
|
||||
if toUint and (fromInt or fromUint):
|
||||
let trimmer = unsignedTrimmer(dest.size)
|
||||
r.res = "($1 $2)" % [r.res, trimmer]
|
||||
elif dest.kind == tyBool:
|
||||
r.res = "(!!($1))" % [r.res]
|
||||
r.kind = resExpr
|
||||
of tyInt:
|
||||
elif toInt:
|
||||
r.res = "(($1)|0)" % [r.res]
|
||||
else:
|
||||
# TODO: What types must we handle here?
|
||||
@@ -2395,8 +2444,7 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
|
||||
r.res = "($1 $2)" % [r.res, trimmer]
|
||||
elif toInt:
|
||||
if fromInt:
|
||||
let trimmer = unsignedTrimmer(dest.size)
|
||||
r.res = "($1 $2)" % [r.res, trimmer]
|
||||
return
|
||||
elif fromUint:
|
||||
if src.size == 4 and dest.size == 4:
|
||||
# XXX prevent multi evaluations
|
||||
@@ -2503,7 +2551,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
let s = n[namePos].sym
|
||||
discard mangleName(p.module, s)
|
||||
r.res = s.loc.r
|
||||
if lfNoDecl in s.loc.flags or s.magic != mNone: discard
|
||||
if lfNoDecl in s.loc.flags or s.magic notin {mNone, mIsolate}: discard
|
||||
elif not p.g.generatedSyms.containsOrIncl(s.id):
|
||||
p.locals.add(genProc(p, s))
|
||||
of nkType: r.res = genTypeInfo(p, n.typ)
|
||||
@@ -2534,12 +2582,17 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
if n[0].kind != nkEmpty:
|
||||
genLineDir(p, n)
|
||||
gen(p, n[0], r)
|
||||
r.res = "var _ = " & r.res
|
||||
of nkAsmStmt: genAsmOrEmitStmt(p, n)
|
||||
of nkTryStmt, nkHiddenTryStmt: genTry(p, n, r)
|
||||
of nkRaiseStmt: genRaiseStmt(p, n)
|
||||
of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt,
|
||||
of nkTypeSection, nkCommentStmt, nkIncludeStmt,
|
||||
nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt,
|
||||
nkFromStmt, nkTemplateDef, nkMacroDef, nkStaticStmt: discard
|
||||
nkFromStmt, nkTemplateDef, nkMacroDef, nkStaticStmt,
|
||||
nkMixinStmt, nkBindStmt: discard
|
||||
of nkIteratorDef:
|
||||
if n[0].sym.typ.callConv == TCallingConvention.ccClosure:
|
||||
globalError(p.config, n.info, "Closure iterators are not supported by JS backend!")
|
||||
of nkPragma: genPragma(p, n)
|
||||
of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef:
|
||||
var s = n[namePos].sym
|
||||
@@ -2547,7 +2600,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
genSym(p, n[namePos], r)
|
||||
r.res = nil
|
||||
of nkGotoState, nkState:
|
||||
internalError(p.config, n.info, "first class iterators not implemented")
|
||||
globalError(p.config, n.info, "First class iterators not implemented")
|
||||
of nkPragmaBlock: gen(p, n.lastSon, r)
|
||||
of nkComesFrom:
|
||||
discard "XXX to implement for better stack traces"
|
||||
@@ -2569,14 +2622,6 @@ proc genHeader(): Rope =
|
||||
var framePtr = null;
|
||||
var excHandler = 0;
|
||||
var lastJSError = null;
|
||||
if (typeof Int8Array === 'undefined') Int8Array = Array;
|
||||
if (typeof Int16Array === 'undefined') Int16Array = Array;
|
||||
if (typeof Int32Array === 'undefined') Int32Array = Array;
|
||||
if (typeof Uint8Array === 'undefined') Uint8Array = Array;
|
||||
if (typeof Uint16Array === 'undefined') Uint16Array = Array;
|
||||
if (typeof Uint32Array === 'undefined') Uint32Array = Array;
|
||||
if (typeof Float32Array === 'undefined') Float32Array = Array;
|
||||
if (typeof Float64Array === 'undefined') Float64Array = Array;
|
||||
""".unindent.format(VersionAsString))
|
||||
|
||||
proc addHcrInitGuards(p: PProc, n: PNode,
|
||||
|
||||
@@ -238,10 +238,11 @@ proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
|
||||
result = conf.backend == backendJs and not isCompileTime
|
||||
|
||||
proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; owner: PSym) =
|
||||
createTypeBoundOps(g, nil, refType.lastSon, info)
|
||||
createTypeBoundOps(g, nil, refType, info)
|
||||
if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions:
|
||||
owner.flags.incl sfInjectDestructors
|
||||
if owner.kind != skMacro:
|
||||
createTypeBoundOps(g, nil, refType.lastSon, info)
|
||||
createTypeBoundOps(g, nil, refType, info)
|
||||
if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions:
|
||||
owner.flags.incl sfInjectDestructors
|
||||
|
||||
proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
|
||||
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
|
||||
@@ -295,7 +296,7 @@ proc markAsClosure(g: ModuleGraph; owner: PSym; n: PNode) =
|
||||
[s.name.s, typeToString(s.typ), g.config$s.info])
|
||||
elif not (owner.typ.callConv == ccClosure or owner.typ.callConv == ccNimCall and tfExplicitCallConv notin owner.typ.flags):
|
||||
localError(g.config, n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" %
|
||||
[s.name.s, owner.name.s, CallingConvToStr[owner.typ.callConv]])
|
||||
[s.name.s, owner.name.s, $owner.typ.callConv])
|
||||
incl(owner.typ.flags, tfCapturesEnv)
|
||||
owner.typ.callConv = ccClosure
|
||||
|
||||
@@ -494,7 +495,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
w = up
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
|
||||
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef,
|
||||
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt, nkTypeOfExpr:
|
||||
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt,
|
||||
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
|
||||
discard
|
||||
of nkLambdaKinds, nkIteratorDef:
|
||||
if n.typ != nil:
|
||||
@@ -611,7 +613,8 @@ proc rawClosureCreation(owner: PSym;
|
||||
let fieldAccess = indirectAccess(env, local, env.info)
|
||||
# add ``env.param = param``
|
||||
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
|
||||
createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info)
|
||||
if owner.kind != skMacro:
|
||||
createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info)
|
||||
if tfHasAsgn in fieldAccess.typ.flags or optSeqDestructors in d.graph.config.globalOptions:
|
||||
owner.flags.incl sfInjectDestructors
|
||||
|
||||
@@ -748,7 +751,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
|
||||
result = accessViaEnvVar(n, owner, d, c)
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkComesFrom,
|
||||
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef, nkConverterDef,
|
||||
nkMacroDef, nkFuncDef:
|
||||
nkMacroDef, nkFuncDef, nkMixinStmt, nkBindStmt:
|
||||
discard
|
||||
of nkClosure:
|
||||
if n[1].kind == nkNilLit:
|
||||
|
||||
@@ -494,7 +494,7 @@ proc emitTok*(em: var Emitter; L: Lexer; tok: Token) =
|
||||
wrSpace em
|
||||
|
||||
if not em.inquote:
|
||||
wr(em, TokTypeToStr[tok.tokType], ltKeyword)
|
||||
wr(em, $tok.tokType, ltKeyword)
|
||||
if tok.tokType in {tkAnd, tkOr, tkIn, tkNotin}:
|
||||
rememberSplit(splitIn)
|
||||
wrSpace em
|
||||
@@ -503,28 +503,28 @@ proc emitTok*(em: var Emitter; L: Lexer; tok: Token) =
|
||||
wr(em, tok.ident.s, ltIdent)
|
||||
|
||||
of tkColon:
|
||||
wr(em, TokTypeToStr[tok.tokType], ltOther)
|
||||
wr(em, $tok.tokType, ltOther)
|
||||
wrSpace em
|
||||
of tkSemiColon, tkComma:
|
||||
wr(em, TokTypeToStr[tok.tokType], ltOther)
|
||||
wr(em, $tok.tokType, ltOther)
|
||||
rememberSplit(splitComma)
|
||||
wrSpace em
|
||||
of openPars:
|
||||
if tok.strongSpaceA > 0 and not em.endsInWhite and
|
||||
(not em.wasExportMarker or tok.tokType == tkCurlyDotLe):
|
||||
wrSpace em
|
||||
wr(em, TokTypeToStr[tok.tokType], ltSomeParLe)
|
||||
wr(em, $tok.tokType, ltSomeParLe)
|
||||
rememberSplit(splitParLe)
|
||||
of closedPars:
|
||||
wr(em, TokTypeToStr[tok.tokType], ltSomeParRi)
|
||||
wr(em, $tok.tokType, ltSomeParRi)
|
||||
of tkColonColon:
|
||||
wr(em, TokTypeToStr[tok.tokType], ltOther)
|
||||
wr(em, $tok.tokType, ltOther)
|
||||
of tkDot:
|
||||
lastTokWasTerse = true
|
||||
wr(em, TokTypeToStr[tok.tokType], ltOther)
|
||||
wr(em, $tok.tokType, ltOther)
|
||||
of tkEquals:
|
||||
if not em.inquote and not em.endsInWhite: wrSpace(em)
|
||||
wr(em, TokTypeToStr[tok.tokType], ltOther)
|
||||
wr(em, $tok.tokType, ltOther)
|
||||
if not em.inquote: wrSpace(em)
|
||||
of tkOpr, tkDotDot:
|
||||
if em.inquote or ((tok.strongSpaceA == 0 and tok.strongSpaceB == 0) and
|
||||
@@ -544,7 +544,7 @@ proc emitTok*(em: var Emitter; L: Lexer; tok: Token) =
|
||||
wrSpace(em)
|
||||
of tkAccent:
|
||||
if not em.inquote and endsInAlpha(em): wrSpace(em)
|
||||
wr(em, TokTypeToStr[tok.tokType], ltOther)
|
||||
wr(em, $tok.tokType, ltOther)
|
||||
em.inquote = not em.inquote
|
||||
of tkComment:
|
||||
if not preventComment:
|
||||
|
||||
@@ -31,37 +31,44 @@ const
|
||||
|
||||
type
|
||||
TokType* = enum
|
||||
tkInvalid, tkEof, # order is important here!
|
||||
tkSymbol, # keywords:
|
||||
tkAddr, tkAnd, tkAs, tkAsm,
|
||||
tkBind, tkBlock, tkBreak, tkCase, tkCast,
|
||||
tkConcept, tkConst, tkContinue, tkConverter,
|
||||
tkDefer, tkDiscard, tkDistinct, tkDiv, tkDo,
|
||||
tkElif, tkElse, tkEnd, tkEnum, tkExcept, tkExport,
|
||||
tkFinally, tkFor, tkFrom, tkFunc,
|
||||
tkIf, tkImport, tkIn, tkInclude, tkInterface,
|
||||
tkIs, tkIsnot, tkIterator,
|
||||
tkLet,
|
||||
tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin,
|
||||
tkObject, tkOf, tkOr, tkOut,
|
||||
tkProc, tkPtr, tkRaise, tkRef, tkReturn,
|
||||
tkShl, tkShr, tkStatic,
|
||||
tkTemplate,
|
||||
tkTry, tkTuple, tkType, tkUsing,
|
||||
tkVar, tkWhen, tkWhile, tkXor,
|
||||
tkYield, # end of keywords
|
||||
tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit,
|
||||
tkUIntLit, tkUInt8Lit, tkUInt16Lit, tkUInt32Lit, tkUInt64Lit,
|
||||
tkFloatLit, tkFloat32Lit, tkFloat64Lit, tkFloat128Lit,
|
||||
tkStrLit, tkRStrLit, tkTripleStrLit,
|
||||
tkGStrLit, tkGTripleStrLit, tkCharLit, tkParLe, tkParRi, tkBracketLe,
|
||||
tkBracketRi, tkCurlyLe, tkCurlyRi,
|
||||
tkBracketDotLe, tkBracketDotRi, # [. and .]
|
||||
tkCurlyDotLe, tkCurlyDotRi, # {. and .}
|
||||
tkParDotLe, tkParDotRi, # (. and .)
|
||||
tkComma, tkSemiColon,
|
||||
tkColon, tkColonColon, tkEquals, tkDot, tkDotDot, tkBracketLeColon,
|
||||
tkOpr, tkComment, tkAccent,
|
||||
tkInvalid = "tkInvalid", tkEof = "[EOF]", # order is important here!
|
||||
tkSymbol = "tkSymbol", # keywords:
|
||||
tkAddr = "addr", tkAnd = "and", tkAs = "as", tkAsm = "asm",
|
||||
tkBind = "bind", tkBlock = "block", tkBreak = "break", tkCase = "case", tkCast = "cast",
|
||||
tkConcept = "concept", tkConst = "const", tkContinue = "continue", tkConverter = "converter",
|
||||
tkDefer = "defer", tkDiscard = "discard", tkDistinct = "distinct", tkDiv = "div", tkDo = "do",
|
||||
tkElif = "elif", tkElse = "else", tkEnd = "end", tkEnum = "enum", tkExcept = "except", tkExport = "export",
|
||||
tkFinally = "finally", tkFor = "for", tkFrom = "from", tkFunc = "func",
|
||||
tkIf = "if", tkImport = "import", tkIn = "in", tkInclude = "include", tkInterface = "interface",
|
||||
tkIs = "is", tkIsnot = "isnot", tkIterator = "iterator",
|
||||
tkLet = "let",
|
||||
tkMacro = "macro", tkMethod = "method", tkMixin = "mixin", tkMod = "mod", tkNil = "nil", tkNot = "not", tkNotin = "notin",
|
||||
tkObject = "object", tkOf = "of", tkOr = "or", tkOut = "out",
|
||||
tkProc = "proc", tkPtr = "ptr", tkRaise = "raise", tkRef = "ref", tkReturn = "return",
|
||||
tkShl = "shl", tkShr = "shr", tkStatic = "static",
|
||||
tkTemplate = "template",
|
||||
tkTry = "try", tkTuple = "tuple", tkType = "type", tkUsing = "using",
|
||||
tkVar = "var", tkWhen = "when", tkWhile = "while", tkXor = "xor",
|
||||
tkYield = "yield", # end of keywords
|
||||
|
||||
tkIntLit = "tkIntLit", tkInt8Lit = "tkInt8Lit", tkInt16Lit = "tkInt16Lit",
|
||||
tkInt32Lit = "tkInt32Lit", tkInt64Lit = "tkInt64Lit",
|
||||
tkUIntLit = "tkUIntLit", tkUInt8Lit = "tkUInt8Lit", tkUInt16Lit = "tkUInt16Lit",
|
||||
tkUInt32Lit = "tkUInt32Lit", tkUInt64Lit = "tkUInt64Lit",
|
||||
tkFloatLit = "tkFloatLit", tkFloat32Lit = "tkFloat32Lit",
|
||||
tkFloat64Lit = "tkFloat64Lit", tkFloat128Lit = "tkFloat128Lit",
|
||||
tkStrLit = "tkStrLit", tkRStrLit = "tkRStrLit", tkTripleStrLit = "tkTripleStrLit",
|
||||
tkGStrLit = "tkGStrLit", tkGTripleStrLit = "tkGTripleStrLit", tkCharLit = "tkCharLit",
|
||||
|
||||
tkParLe = "(", tkParRi = ")", tkBracketLe = "[",
|
||||
tkBracketRi = "]", tkCurlyLe = "{", tkCurlyRi = "}",
|
||||
tkBracketDotLe = "[.", tkBracketDotRi = ".]",
|
||||
tkCurlyDotLe = "{.", tkCurlyDotRi = ".}",
|
||||
tkParDotLe = "(.", tkParDotRi = ".)",
|
||||
tkComma = ",", tkSemiColon = ";",
|
||||
tkColon = ":", tkColonColon = "::", tkEquals = "=",
|
||||
tkDot = ".", tkDotDot = "..", tkBracketLeColon = "[:",
|
||||
tkOpr, tkComment, tkAccent = "`",
|
||||
# these are fake tokens used by renderer.nim
|
||||
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr
|
||||
|
||||
@@ -74,35 +81,6 @@ const
|
||||
# tokens that should not be considered for previousToken
|
||||
tokKeywordLow* = succ(tkSymbol)
|
||||
tokKeywordHigh* = pred(tkIntLit)
|
||||
TokTypeToStr*: array[TokType, string] = ["tkInvalid", "[EOF]",
|
||||
"tkSymbol",
|
||||
"addr", "and", "as", "asm",
|
||||
"bind", "block", "break", "case", "cast",
|
||||
"concept", "const", "continue", "converter",
|
||||
"defer", "discard", "distinct", "div", "do",
|
||||
"elif", "else", "end", "enum", "except", "export",
|
||||
"finally", "for", "from", "func", "if",
|
||||
"import", "in", "include", "interface", "is", "isnot", "iterator",
|
||||
"let",
|
||||
"macro", "method", "mixin", "mod",
|
||||
"nil", "not", "notin", "object", "of", "or",
|
||||
"out", "proc", "ptr", "raise", "ref", "return",
|
||||
"shl", "shr", "static",
|
||||
"template",
|
||||
"try", "tuple", "type", "using",
|
||||
"var", "when", "while", "xor",
|
||||
"yield",
|
||||
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
|
||||
"tkUIntLit", "tkUInt8Lit", "tkUInt16Lit", "tkUInt32Lit", "tkUInt64Lit",
|
||||
"tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkFloat128Lit",
|
||||
"tkStrLit", "tkRStrLit",
|
||||
"tkTripleStrLit", "tkGStrLit", "tkGTripleStrLit", "tkCharLit", "(",
|
||||
")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)",
|
||||
",", ";",
|
||||
":", "::", "=", ".", "..", "[:",
|
||||
"tkOpr", "tkComment", "`",
|
||||
"tkSpaces", "tkInfixOpr",
|
||||
"tkPrefixOpr", "tkPostfixOpr"]
|
||||
|
||||
type
|
||||
NumericalBase* = enum
|
||||
@@ -171,7 +149,7 @@ proc `$`*(tok: Token): string =
|
||||
of tkIntLit..tkInt64Lit: $tok.iNumber
|
||||
of tkFloatLit..tkFloat64Lit: $tok.fNumber
|
||||
of tkInvalid, tkStrLit..tkCharLit, tkComment: tok.literal
|
||||
of tkParLe..tkColon, tkEof, tkAccent: TokTypeToStr[tok.tokType]
|
||||
of tkParLe..tkColon, tkEof, tkAccent: $tok.tokType
|
||||
else:
|
||||
if tok.ident != nil:
|
||||
tok.ident.s
|
||||
@@ -183,8 +161,7 @@ proc prettyTok*(tok: Token): string =
|
||||
else: $tok
|
||||
|
||||
proc printTok*(conf: ConfigRef; tok: Token) =
|
||||
msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" &
|
||||
TokTypeToStr[tok.tokType] & " " & $tok)
|
||||
msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" & $tok.tokType & " " & $tok)
|
||||
|
||||
proc initToken*(L: var Token) =
|
||||
L.tokType = tkInvalid
|
||||
@@ -1042,7 +1019,7 @@ proc scanComment(L: var Lexer, tok: var Token) =
|
||||
tok.iNumber = 0
|
||||
assert L.buf[pos+1] == '#'
|
||||
when defined(nimpretty):
|
||||
tok.commentOffsetA = L.offsetBase + pos - 1
|
||||
tok.commentOffsetA = L.offsetBase + pos
|
||||
|
||||
if L.buf[pos+2] == '[':
|
||||
skipMultiLineComment(L, tok, pos+3, true)
|
||||
|
||||
@@ -40,6 +40,9 @@ proc at(a, i: PNode, elemType: PType): PNode =
|
||||
result[1] = i
|
||||
result.typ = elemType
|
||||
|
||||
proc destructorOverriden(t: PType): bool =
|
||||
t.attachedOps[attachedDestructor] != nil and sfOverriden in t.attachedOps[attachedDestructor].flags
|
||||
|
||||
proc fillBodyTup(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
for i in 0..<t.len:
|
||||
let lit = lowerings.newIntLit(c.g, x.info, i)
|
||||
@@ -290,8 +293,10 @@ proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym =
|
||||
proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||
field: var PSym): bool =
|
||||
if optSeqDestructors in c.g.config.globalOptions:
|
||||
let op = field
|
||||
if field != nil and sfOverriden in field.flags:
|
||||
var op = field
|
||||
let destructorOverriden = destructorOverriden(t)
|
||||
if op != nil and op != c.fn and
|
||||
(sfOverriden in op.flags or destructorOverriden):
|
||||
if sfError in op.flags:
|
||||
incl c.fn.flags, sfError
|
||||
#else:
|
||||
@@ -299,6 +304,10 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||
onUse(c.info, op)
|
||||
body.add newHookCall(c, op, x, y)
|
||||
result = true
|
||||
elif op == nil and destructorOverriden:
|
||||
op = produceSym(c.g, c.c, t, c.kind, c.info)
|
||||
body.add newHookCall(c, op, x, y)
|
||||
result = true
|
||||
elif tfHasAsgn in t.flags:
|
||||
var op: PSym
|
||||
if sameType(t, c.asgnForType):
|
||||
@@ -390,6 +399,16 @@ proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
|
||||
v.addVar(result, lowerings.newIntLit(c.g, body.info, first))
|
||||
body.add v
|
||||
|
||||
proc declareTempOf(c: var TLiftCtx; body: PNode; value: PNode): PNode =
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
|
||||
temp.typ = value.typ
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
|
||||
var v = newNodeI(nkVarSection, c.info)
|
||||
result = newSymNode(temp)
|
||||
v.addVar(result, value)
|
||||
body.add v
|
||||
|
||||
proc addIncStmt(c: var TLiftCtx; body, i: PNode) =
|
||||
let incCall = genBuiltin(c.g, mInc, "inc", i)
|
||||
incCall.add lowerings.newIntLit(c.g, c.info, 1)
|
||||
@@ -416,13 +435,17 @@ proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
|
||||
result = newTree(nkCall, newSymNode(op, x.info), x, lenCall)
|
||||
|
||||
proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let counterIdx = body.len
|
||||
let i = declareCounter(c, body, toInt64(firstOrd(c.g.config, t)))
|
||||
let whileLoop = genWhileLoop(c, i, x)
|
||||
let elemType = t.lastSon
|
||||
let b = if c.kind == attachedTrace: y else: y.at(i, elemType)
|
||||
fillBody(c, elemType, whileLoop[1], x.at(i, elemType), b)
|
||||
addIncStmt(c, whileLoop[1], i)
|
||||
body.add whileLoop
|
||||
if whileLoop[1].len > 0:
|
||||
addIncStmt(c, whileLoop[1], i)
|
||||
body.add whileLoop
|
||||
else:
|
||||
body.sons.setLen counterIdx
|
||||
|
||||
proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
case c.kind
|
||||
@@ -445,8 +468,9 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
forallElements(c, t, body, x, y)
|
||||
body.add genBuiltin(c.g, mDestroy, "destroy", x)
|
||||
of attachedTrace:
|
||||
# follow all elements:
|
||||
forallElements(c, t, body, x, y)
|
||||
if canFormAcycle(t.elemType):
|
||||
# follow all elements:
|
||||
forallElements(c, t, body, x, y)
|
||||
of attachedDispose:
|
||||
forallElements(c, t, body, x, y)
|
||||
body.add genBuiltin(c.g, mDestroy, "destroy", x)
|
||||
@@ -506,55 +530,93 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
discard "strings are atomic and have no inner elements that are to trace"
|
||||
|
||||
proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
#[ bug #15753 is really subtle. Usually the classical write barrier for reference
|
||||
counting looks like this::
|
||||
|
||||
incRef source # increment first; this takes care of self-assignments1
|
||||
decRef dest
|
||||
dest[] = source
|
||||
|
||||
However, 'decRef dest' might trigger a cycle collection and then the collector
|
||||
traverses the graph. It is crucial that when it follows the pointers the assignment
|
||||
'dest[] = source' already happened so that we don't do trial deletion on a wrong
|
||||
graph -- this causes premature freeing of objects! The correct barrier looks like
|
||||
this::
|
||||
|
||||
let tmp = dest
|
||||
incRef source
|
||||
dest[] = source
|
||||
decRef tmp
|
||||
|
||||
]#
|
||||
var actions = newNodeI(nkStmtList, c.info)
|
||||
let elemType = t.lastSon
|
||||
|
||||
createTypeBoundOps(c.g, c.c, elemType, c.info)
|
||||
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(elemType)
|
||||
|
||||
let tmp =
|
||||
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
|
||||
declareTempOf(c, body, x)
|
||||
else:
|
||||
x
|
||||
|
||||
if isFinal(elemType):
|
||||
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
|
||||
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x)
|
||||
addDestructorCall(c, elemType, actions, genDeref(tmp, nkDerefExpr))
|
||||
var alignOf = genBuiltin(c.g, mAlignOf, "alignof", newNodeIT(nkType, c.info, elemType))
|
||||
alignOf.typ = getSysType(c.g, c.info, tyInt)
|
||||
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, tmp, alignOf)
|
||||
else:
|
||||
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
|
||||
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x)
|
||||
|
||||
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(elemType)
|
||||
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(tmp, nkDerefExpr))
|
||||
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, tmp)
|
||||
|
||||
var cond: PNode
|
||||
if isCyclic:
|
||||
if isFinal(elemType):
|
||||
let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
|
||||
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, x, typInfo)
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, tmp, typInfo)
|
||||
else:
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, x)
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, tmp)
|
||||
else:
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x)
|
||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||
|
||||
case c.kind
|
||||
of attachedSink:
|
||||
body.add genIf(c, cond, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
if isCyclic:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, cond, actions)
|
||||
else:
|
||||
body.add genIf(c, cond, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedAsgn:
|
||||
body.add genIf(c, y, callCodegenProc(c.g,
|
||||
if isCyclic: "nimIncRefCyclic" else: "nimIncRef", c.info, y))
|
||||
body.add genIf(c, cond, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
if isCyclic:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, cond, actions)
|
||||
else:
|
||||
body.add genIf(c, cond, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDestructor:
|
||||
body.add genIf(c, cond, actions)
|
||||
of attachedDeepCopy: assert(false, "cannot happen")
|
||||
of attachedTrace:
|
||||
if isFinal(elemType):
|
||||
let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
|
||||
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
||||
body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x), typInfo, y)
|
||||
else:
|
||||
# If the ref is polymorphic we have to account for this
|
||||
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x), y)
|
||||
if isCyclic:
|
||||
if isFinal(elemType):
|
||||
let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
|
||||
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
||||
body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x), typInfo, y)
|
||||
else:
|
||||
# If the ref is polymorphic we have to account for this
|
||||
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x), y)
|
||||
#echo "can follow ", elemType, " static ", isFinal(elemType)
|
||||
of attachedDispose:
|
||||
# this is crucial! dispose is like =destroy but we don't follow refs
|
||||
# as that is dealt within the cycle collector.
|
||||
if not isCyclic:
|
||||
body.add genIf(c, cond, actions)
|
||||
when false:
|
||||
let cond = copyTree(x)
|
||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||
@@ -567,19 +629,30 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let xenv = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
|
||||
xenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||
|
||||
let isCyclic = c.g.config.selectedGC == gcOrc
|
||||
let tmp =
|
||||
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
|
||||
declareTempOf(c, body, xenv)
|
||||
else:
|
||||
xenv
|
||||
|
||||
var actions = newNodeI(nkStmtList, c.info)
|
||||
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xenv)
|
||||
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, tmp)
|
||||
|
||||
let decRefProc =
|
||||
if c.g.config.selectedGC == gcOrc: "nimDecRefIsLastCyclicDyn"
|
||||
if isCyclic: "nimDecRefIsLastCyclicDyn"
|
||||
else: "nimDecRefIsLast"
|
||||
let cond = callCodegenProc(c.g, decRefProc, c.info, xenv)
|
||||
let cond = callCodegenProc(c.g, decRefProc, c.info, tmp)
|
||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||
|
||||
case c.kind
|
||||
of attachedSink:
|
||||
body.add genIf(c, cond, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
if isCyclic:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, cond, actions)
|
||||
else:
|
||||
body.add genIf(c, cond, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedAsgn:
|
||||
let yenv = genBuiltin(c.g, mAccessEnv, "accessEnv", y)
|
||||
yenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||
@@ -587,8 +660,12 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if c.g.config.selectedGC == gcOrc: "nimIncRefCyclic"
|
||||
else: "nimIncRef"
|
||||
body.add genIf(c, yenv, callCodegenProc(c.g, incRefProc, c.info, yenv))
|
||||
body.add genIf(c, cond, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
if isCyclic:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, cond, actions)
|
||||
else:
|
||||
body.add genIf(c, cond, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDestructor:
|
||||
body.add genIf(c, cond, actions)
|
||||
of attachedDeepCopy: assert(false, "cannot happen")
|
||||
@@ -636,7 +713,9 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
|
||||
if isFinal(elemType):
|
||||
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
|
||||
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x)
|
||||
var alignOf = genBuiltin(c.g, mAlignOf, "alignof", newNodeIT(nkType, c.info, elemType))
|
||||
alignOf.typ = getSysType(c.g, c.info, tyInt)
|
||||
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x, alignOf)
|
||||
else:
|
||||
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
|
||||
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x)
|
||||
@@ -844,8 +923,7 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
# register this operation already:
|
||||
typ.attachedOps[kind] = result
|
||||
|
||||
if kind == attachedSink and typ.attachedOps[attachedDestructor] != nil and
|
||||
sfOverriden in typ.attachedOps[attachedDestructor].flags:
|
||||
if kind == attachedSink and destructorOverriden(typ):
|
||||
## compiler can use a combination of `=destroy` and memCopy for sink op
|
||||
dest.flags.incl sfCursor
|
||||
result.ast[bodyPos].add newOpCall(a, typ.attachedOps[attachedDestructor], d[0])
|
||||
|
||||
@@ -42,7 +42,7 @@ proc liftLocals(n: PNode; i: int; c: var Ctx) =
|
||||
of nkSym:
|
||||
if interestingVar(it.sym):
|
||||
n[i] = lookupOrAdd(c, it.sym, it.info)
|
||||
of procDefs, nkTypeSection: discard
|
||||
of procDefs, nkTypeSection, nkMixinStmt, nkBindStmt: discard
|
||||
else:
|
||||
for i in 0..<it.safeLen:
|
||||
liftLocals(it, i, c)
|
||||
|
||||
@@ -36,39 +36,40 @@ type
|
||||
errProveInit, # deadcode
|
||||
errGenerated,
|
||||
errUser,
|
||||
warnCannotOpenFile,
|
||||
warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit,
|
||||
warnDeprecated, warnConfigDeprecated,
|
||||
warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel,
|
||||
warnUnknownSubstitutionX, warnLanguageXNotSupported,
|
||||
warnFieldXNotSupported, warnCommentXIgnored,
|
||||
warnTypelessParam,
|
||||
warnUseBase, warnWriteToForeignHeap, warnUnsafeCode,
|
||||
warnUnusedImportX,
|
||||
warnInheritFromException,
|
||||
warnEachIdentIsTuple,
|
||||
warnUnsafeSetLen,
|
||||
warnUnsafeDefault,
|
||||
warnProveInit, warnProveField, warnProveIndex,
|
||||
warnUnreachableElse, warnUnreachableCode,
|
||||
warnStaticIndexCheck, warnGcUnsafe, warnGcUnsafe2,
|
||||
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
|
||||
warnInconsistentSpacing, warnCaseTransition, warnCycleCreated,
|
||||
warnObservableStores,
|
||||
warnUser,
|
||||
hintSuccess, hintSuccessX, hintCC,
|
||||
hintLineTooLong, hintXDeclaredButNotUsed,
|
||||
hintXCannotRaiseY,
|
||||
hintConvToBaseNotNeeded,
|
||||
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
|
||||
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
|
||||
hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern,
|
||||
hintExecuting, hintLinking, hintDependency,
|
||||
hintSource, hintPerformance, hintStackTrace, hintGCStats,
|
||||
hintGlobalVar, hintExpandMacro,
|
||||
hintUser, hintUserRaw,
|
||||
hintExtendedContext,
|
||||
hintMsgOrigin, # since 1.3.5
|
||||
|
||||
warnCannotOpenFile = "CannotOpenFile", warnOctalEscape = "OctalEscape",
|
||||
warnXIsNeverRead = "XIsNeverRead", warnXmightNotBeenInit = "XmightNotBeenInit",
|
||||
warnDeprecated = "Deprecated", warnConfigDeprecated = "ConfigDeprecated",
|
||||
warnSmallLshouldNotBeUsed = "SmallLshouldNotBeUsed", warnUnknownMagic = "UnknownMagic",
|
||||
warnRedefinitionOfLabel = "RedefinitionOfLabel", warnUnknownSubstitutionX = "UnknownSubstitutionX",
|
||||
warnLanguageXNotSupported = "LanguageXNotSupported", warnFieldXNotSupported = "FieldXNotSupported",
|
||||
warnCommentXIgnored = "CommentXIgnored", warnTypelessParam = "TypelessParam",
|
||||
warnUseBase = "UseBase", warnWriteToForeignHeap = "WriteToForeignHeap",
|
||||
warnUnsafeCode = "UnsafeCode", warnUnusedImportX = "UnusedImport",
|
||||
warnInheritFromException = "InheritFromException", warnEachIdentIsTuple = "EachIdentIsTuple",
|
||||
warnUnsafeSetLen = "UnsafeSetLen", warnUnsafeDefault = "UnsafeDefault",
|
||||
warnProveInit = "ProveInit", warnProveField = "ProveField", warnProveIndex = "ProveIndex",
|
||||
warnUnreachableElse = "UnreachableElse", warnUnreachableCode = "UnreachableCode",
|
||||
warnStaticIndexCheck = "IndexCheck", warnGcUnsafe = "GcUnsafe", warnGcUnsafe2 = "GcUnsafe2",
|
||||
warnUninit = "Uninit", warnGcMem = "GcMem", warnDestructor = "Destructor",
|
||||
warnLockLevel = "LockLevel", warnResultShadowed = "ResultShadowed",
|
||||
warnInconsistentSpacing = "Spacing", warnCaseTransition = "CaseTransition",
|
||||
warnCycleCreated = "CycleCreated", warnObservableStores = "ObservableStores",
|
||||
warnResultUsed = "ResultUsed",
|
||||
warnUser = "User",
|
||||
|
||||
hintSuccess = "Success", hintSuccessX = "SuccessX", hintCC = "CC",
|
||||
hintLineTooLong = "LineTooLong", hintXDeclaredButNotUsed = "XDeclaredButNotUsed",
|
||||
hintXCannotRaiseY = "XCannotRaiseY", hintConvToBaseNotNeeded = "ConvToBaseNotNeeded",
|
||||
hintConvFromXtoItselfNotNeeded = "ConvFromXtoItselfNotNeeded", hintExprAlwaysX = "ExprAlwaysX",
|
||||
hintQuitCalled = "QuitCalled", hintProcessing = "Processing", hintCodeBegin = "CodeBegin",
|
||||
hintCodeEnd = "CodeEnd", hintConf = "Conf", hintPath = "Path",
|
||||
hintConditionAlwaysTrue = "CondTrue", hintConditionAlwaysFalse = "CondFalse", hintName = "Name",
|
||||
hintPattern = "Pattern", hintExecuting = "Exec", hintLinking = "Link", hintDependency = "Dependency",
|
||||
hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace",
|
||||
hintGCStats = "GCStats", hintGlobalVar = "GlobalVar", hintExpandMacro = "ExpandMacro",
|
||||
hintUser = "User", hintUserRaw = "UserRaw", hintExtendedContext = "ExtendedContext",
|
||||
hintMsgOrigin = "MsgOrigin", # since 1.3.5
|
||||
|
||||
const
|
||||
MsgKindToStr*: array[TMsgKind, string] = [
|
||||
@@ -125,6 +126,7 @@ const
|
||||
warnCaseTransition: "Potential object case transition, instantiate new object instead",
|
||||
warnCycleCreated: "$1",
|
||||
warnObservableStores: "observable stores to '$1'",
|
||||
warnResultUsed: "used 'result' variable",
|
||||
warnUser: "$1",
|
||||
hintSuccess: "operation successful: $#",
|
||||
# keep in sync with `testament.isSuccess`
|
||||
@@ -161,34 +163,6 @@ const
|
||||
hintMsgOrigin: "$1",
|
||||
]
|
||||
|
||||
const
|
||||
WarningsToStr* = ["CannotOpenFile", "OctalEscape",
|
||||
"XIsNeverRead", "XmightNotBeenInit",
|
||||
"Deprecated", "ConfigDeprecated",
|
||||
"SmallLshouldNotBeUsed", "UnknownMagic",
|
||||
"RedefinitionOfLabel", "UnknownSubstitutionX",
|
||||
"LanguageXNotSupported", "FieldXNotSupported",
|
||||
"CommentXIgnored",
|
||||
"TypelessParam", "UseBase", "WriteToForeignHeap",
|
||||
"UnsafeCode", "UnusedImport", "InheritFromException",
|
||||
"EachIdentIsTuple",
|
||||
"UnsafeSetLen", "UnsafeDefault",
|
||||
"ProveInit", "ProveField", "ProveIndex", "UnreachableElse", "UnreachableCode",
|
||||
"IndexCheck", "GcUnsafe", "GcUnsafe2", "Uninit",
|
||||
"GcMem", "Destructor", "LockLevel", "ResultShadowed",
|
||||
"Spacing", "CaseTransition", "CycleCreated",
|
||||
"ObservableStores", "User"]
|
||||
|
||||
HintsToStr* = [
|
||||
"Success", "SuccessX", "CC", "LineTooLong",
|
||||
"XDeclaredButNotUsed", "XCannotRaiseY",
|
||||
"ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
|
||||
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
|
||||
"Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency",
|
||||
"Source", "Performance", "StackTrace", "GCStats", "GlobalVar", "ExpandMacro",
|
||||
"User", "UserRaw", "ExtendedContext", "MsgOrigin",
|
||||
]
|
||||
|
||||
const
|
||||
fatalMin* = errUnknown
|
||||
fatalMax* = errInternal
|
||||
@@ -199,22 +173,12 @@ const
|
||||
hintMin* = hintSuccess
|
||||
hintMax* = high(TMsgKind)
|
||||
|
||||
proc msgToStr*(msg: TMsgKind): string =
|
||||
case msg
|
||||
of warnMin..warnMax: WarningsToStr[ord(msg) - ord(warnMin)]
|
||||
of hintMin..hintMax: HintsToStr[ord(msg) - ord(hintMin)]
|
||||
else: "" # we could at least do $msg - prefix `err`
|
||||
|
||||
static:
|
||||
doAssert HintsToStr.len == ord(hintMax) - ord(hintMin) + 1
|
||||
doAssert WarningsToStr.len == ord(warnMax) - ord(warnMin) + 1
|
||||
|
||||
type
|
||||
TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints
|
||||
TNoteKinds* = set[TNoteKind]
|
||||
|
||||
proc computeNotesVerbosity(): array[0..3, TNoteKinds] =
|
||||
result[3] = {low(TNoteKind)..high(TNoteKind)} - {warnObservableStores}
|
||||
result[3] = {low(TNoteKind)..high(TNoteKind)} - {warnObservableStores, warnResultUsed}
|
||||
result[2] = result[3] - {hintStackTrace, warnUninit, hintExtendedContext}
|
||||
result[1] = result[2] - {warnProveField, warnProveIndex,
|
||||
warnGcUnsafe, hintPath, hintDependency, hintCodeBegin, hintCodeEnd,
|
||||
|
||||
@@ -93,7 +93,7 @@ proc nep1CheckDefImpl(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
|
||||
lintReport(conf, info, beau, s.name.s)
|
||||
|
||||
template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
|
||||
if {optStyleHint, optStyleError} * conf.globalOptions != {}:
|
||||
if {optStyleHint, optStyleError} * conf.globalOptions != {} and optStyleUsages notin conf.globalOptions:
|
||||
nep1CheckDefImpl(conf, info, s, k)
|
||||
|
||||
template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym) =
|
||||
@@ -128,6 +128,6 @@ proc styleCheckUse*(conf: ConfigRef; info: TLineInfo; s: PSym) =
|
||||
lintReport(conf, info, newName, oldName)
|
||||
|
||||
proc checkPragmaUse*(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragmaName: string) =
|
||||
let wanted = specialWords[w]
|
||||
let wanted = $w
|
||||
if pragmaName != wanted:
|
||||
lintReport(conf, info, wanted, pragmaName)
|
||||
|
||||
@@ -136,6 +136,7 @@ proc lowerSwap*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
|
||||
var temp = newSym(skVar, getIdent(g.cache, genPrefix), owner, n.info, owner.options)
|
||||
temp.typ = n[1].typ
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
incl(temp.flags, sfGenSym)
|
||||
|
||||
var v = newNodeI(nkVarSection, n.info)
|
||||
let tempAsNode = newSymNode(temp)
|
||||
|
||||
@@ -265,7 +265,7 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
conf.setNoteDefaults(warnLockLevel, false) # issue #13218
|
||||
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # issue #13218
|
||||
# because currently generates lots of false positives due to conflation
|
||||
# of labels links in doc comments, eg for random.rand:
|
||||
# of labels links in doc comments, e.g. for random.rand:
|
||||
# ## * `rand proc<#rand,Rand,Natural>`_ that returns an integer
|
||||
# ## * `rand proc<#rand,Rand,range[]>`_ that returns a float
|
||||
commandDoc2(graph, false)
|
||||
@@ -308,10 +308,10 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
|
||||
var hints = newJObject() # consider factoring with `listHints`
|
||||
for a in hintMin..hintMax:
|
||||
hints[a.msgToStr] = %(a in conf.notes)
|
||||
hints[$a] = %(a in conf.notes)
|
||||
var warnings = newJObject()
|
||||
for a in warnMin..warnMax:
|
||||
warnings[a.msgToStr] = %(a in conf.notes)
|
||||
warnings[$a] = %(a in conf.notes)
|
||||
|
||||
var dumpdata = %[
|
||||
(key: "version", val: %VersionAsString),
|
||||
|
||||
@@ -31,7 +31,7 @@ import ast, intsets, tables, options, lineinfos, hashes, idents,
|
||||
type
|
||||
SigHash* = distinct MD5Digest
|
||||
|
||||
ModuleGraph* = ref object
|
||||
ModuleGraph* {.acyclic.} = ref object
|
||||
modules*: seq[PSym] ## indexed by int32 fileIdx
|
||||
packageSyms*: TStrTable
|
||||
deps*: IntSet # the dependency graph or potentially its transitive closure.
|
||||
|
||||
@@ -233,11 +233,10 @@ template toFullPathConsiderDirty*(conf: ConfigRef; info: TLineInfo): string =
|
||||
string toFullPathConsiderDirty(conf, info.fileIndex)
|
||||
|
||||
type FilenameOption* = enum
|
||||
foAbs # absolute path, eg: /pathto/bar/foo.nim
|
||||
foRelProject # relative to project path, eg: ../foo.nim
|
||||
foAbs # absolute path, e.g.: /pathto/bar/foo.nim
|
||||
foRelProject # relative to project path, e.g.: ../foo.nim
|
||||
foMagicSauce # magic sauce, shortest of (foAbs, foRelProject)
|
||||
foName # lastPathPart, eg: foo.nim
|
||||
foShort # foName without extension, eg: foo
|
||||
foName # lastPathPart, e.g.: foo.nim
|
||||
foStacktrace # if optExcessiveStackTrace: foAbs else: foName
|
||||
|
||||
proc toFilenameOption*(conf: ConfigRef, fileIdx: FileIndex, opt: FilenameOption): string =
|
||||
@@ -255,7 +254,6 @@ proc toFilenameOption*(conf: ConfigRef, fileIdx: FileIndex, opt: FilenameOption)
|
||||
else:
|
||||
relPath
|
||||
of foName: result = toProjPath(conf, fileIdx).lastPathPart
|
||||
of foShort: result = toFilename(conf, fileIdx)
|
||||
of foStacktrace:
|
||||
if optExcessiveStackTrace in conf.globalOptions:
|
||||
result = toFilenameOption(conf, fileIdx, foAbs)
|
||||
@@ -489,7 +487,7 @@ proc liMessage*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
|
||||
color: ForegroundColor
|
||||
ignoreMsg = false
|
||||
sev: Severity
|
||||
let kind = if msg != hintUserRaw: msg.msgToStr else: "" # xxx not sure why hintUserRaw is special
|
||||
let kind = if msg in warnMin..hintMax and msg != hintUserRaw: $msg else: "" # xxx not sure why hintUserRaw is special
|
||||
case msg
|
||||
of errMin..errMax:
|
||||
sev = Severity.Error
|
||||
@@ -536,7 +534,7 @@ proc liMessage*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
|
||||
if hintMsgOrigin in conf.mainPackageNotes:
|
||||
styledMsgWriteln(styleBright, toFileLineCol(info2), resetStyle,
|
||||
" compiler msg initiated here", KindColor,
|
||||
KindFormat % hintMsgOrigin.msgToStr,
|
||||
KindFormat % $hintMsgOrigin,
|
||||
resetStyle)
|
||||
handleError(conf, msg, eh, s)
|
||||
|
||||
@@ -612,7 +610,7 @@ proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope =
|
||||
|
||||
template listMsg(title, r) =
|
||||
msgWriteln(conf, title)
|
||||
for a in r: msgWriteln(conf, " [$1] $2" % [if a in conf.notes: "x" else: " ", a.msgToStr])
|
||||
for a in r: msgWriteln(conf, " [$1] $2" % [if a in conf.notes: "x" else: " ", $a])
|
||||
|
||||
proc listWarnings*(conf: ConfigRef) = listMsg("Warnings:", warnMin..warnMax)
|
||||
proc listHints*(conf: ConfigRef) = listMsg("Hints:", hintMin..hintMax)
|
||||
|
||||
@@ -24,7 +24,7 @@ import
|
||||
idents, lineinfos, cmdlinehelper,
|
||||
pathutils, modulegraphs
|
||||
|
||||
from std/browsers import openDefaultBrowser
|
||||
from browsers import openDefaultBrowser
|
||||
from nodejs import findNodeJs
|
||||
|
||||
when hasTinyCBackend:
|
||||
|
||||
@@ -134,30 +134,3 @@ proc nimblePath*(conf: ConfigRef; path: AbsoluteDir, info: TLineInfo) =
|
||||
if i != -1:
|
||||
conf.nimblePaths.delete(i)
|
||||
conf.nimblePaths.insert(path, 0)
|
||||
|
||||
when isMainModule:
|
||||
proc v(s: string): Version = s.newVersion
|
||||
# #head is special in the sense that it's assumed to always be newest.
|
||||
doAssert v"1.0" < v"#head"
|
||||
doAssert v"1.0" < v"1.1"
|
||||
doAssert v"1.0.1" < v"1.1"
|
||||
doAssert v"1" < v"1.1"
|
||||
doAssert v"#aaaqwe" < v"1.1" # We cannot assume that a branch is newer.
|
||||
doAssert v"#a111" < v"#head"
|
||||
|
||||
let conf = newConfigRef()
|
||||
var rr = newStringTable()
|
||||
addPackage conf, rr, "irc-#a111", unknownLineInfo
|
||||
addPackage conf, rr, "irc-#head", unknownLineInfo
|
||||
addPackage conf, rr, "irc-0.1.0", unknownLineInfo
|
||||
#addPackage conf, rr, "irc", unknownLineInfo
|
||||
#addPackage conf, rr, "another", unknownLineInfo
|
||||
addPackage conf, rr, "another-0.1", unknownLineInfo
|
||||
|
||||
addPackage conf, rr, "ab-0.1.3", unknownLineInfo
|
||||
addPackage conf, rr, "ab-0.1", unknownLineInfo
|
||||
addPackage conf, rr, "justone-1.0", unknownLineInfo
|
||||
|
||||
doAssert toSeq(rr.chosen) ==
|
||||
@["irc-#head", "another-0.1", "ab-0.1.3", "justone-1.0"]
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ interpolation variables:
|
||||
Unstable API
|
||||
]##
|
||||
|
||||
import std/[os,strutils]
|
||||
import os, strutils
|
||||
|
||||
const
|
||||
docCss* = "$nimr/doc/nimdoc.css"
|
||||
|
||||
@@ -150,7 +150,8 @@ proc analyse(c: var Con; b: var BasicBlock; n: PNode) =
|
||||
of nkNone..pred(nkSym), succ(nkSym)..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef,
|
||||
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
|
||||
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState, nkTypeOfExpr:
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
|
||||
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
|
||||
discard "do not follow the construct"
|
||||
|
||||
of nkAsgn, nkFastAsgn:
|
||||
@@ -249,7 +250,8 @@ proc opt(c: Con; n, parent: PNode; parentPos: int) =
|
||||
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef,
|
||||
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
|
||||
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState, nkTypeOfExpr:
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState, nkTypeOfExpr,
|
||||
nkMixinStmt, nkBindStmt:
|
||||
parent[parentPos] = n
|
||||
|
||||
else:
|
||||
|
||||
@@ -19,7 +19,7 @@ const
|
||||
useEffectSystem* = true
|
||||
useWriteTracking* = false
|
||||
hasFFI* = defined(nimHasLibFFI)
|
||||
copyrightYear* = "2020"
|
||||
copyrightYear* = "2021"
|
||||
|
||||
type # please make sure we have under 32 options
|
||||
# (improves code efficiency a lot!)
|
||||
@@ -59,6 +59,7 @@ type # please make sure we have under 32 options
|
||||
optUseNimcache, # save artifacts (including binary) in $nimcache
|
||||
optStyleHint, # check that the names adhere to NEP-1
|
||||
optStyleError, # enforce that the names adhere to NEP-1
|
||||
optStyleUsages, # only enforce consistent **usages** of the symbol
|
||||
optSkipSystemConfigFile, # skip the system's cfg/nims config file
|
||||
optSkipProjConfigFile, # skip the project's cfg/nims config file
|
||||
optSkipUserConfigFile, # skip the users's cfg/nims config file
|
||||
@@ -77,7 +78,7 @@ type # please make sure we have under 32 options
|
||||
optIdeTerse # idetools: use terse descriptions
|
||||
optExcessiveStackTrace # fully qualified module filenames
|
||||
optShowAllMismatches # show all overloading resolution candidates
|
||||
optWholeProject # for 'doc2': output any dependency
|
||||
optWholeProject # for 'doc': output any dependency
|
||||
optDocInternal # generate documentation for non-exported symbols
|
||||
optMixedMode # true if some module triggered C++ codegen
|
||||
optListFullPaths # use full paths in toMsgFilename
|
||||
@@ -229,7 +230,7 @@ type
|
||||
ProfileData* = ref object
|
||||
data*: TableRef[TLineInfo, ProfileInfo]
|
||||
|
||||
ConfigRef* = ref object ## every global configuration
|
||||
ConfigRef* {.acyclic.} = ref object ## every global configuration
|
||||
## fields marked with '*' are subject to
|
||||
## the incremental compilation mechanisms
|
||||
## (+) means "part of the dependency"
|
||||
@@ -355,7 +356,7 @@ proc hasHint*(conf: ConfigRef, note: TNoteKind): bool =
|
||||
note in conf.mainPackageNotes
|
||||
else: note in conf.notes
|
||||
|
||||
proc hasWarn*(conf: ConfigRef, note: TNoteKind): bool =
|
||||
proc hasWarn*(conf: ConfigRef, note: TNoteKind): bool {.inline.} =
|
||||
optWarns in conf.options and note in conf.notes
|
||||
|
||||
proc hcrOn*(conf: ConfigRef): bool = return optHotCodeReloading in conf.globalOptions
|
||||
|
||||
@@ -16,7 +16,7 @@ iterator myParentDirs(p: string): string =
|
||||
yield current
|
||||
|
||||
proc getNimbleFile*(conf: ConfigRef; path: string): string =
|
||||
## returns absolute path to nimble file, eg: /pathto/cligen.nimble
|
||||
## returns absolute path to nimble file, e.g.: /pathto/cligen.nimble
|
||||
var parents = 0
|
||||
block packageSearch:
|
||||
for d in myParentDirs(path):
|
||||
@@ -35,7 +35,7 @@ proc getNimbleFile*(conf: ConfigRef; path: string): string =
|
||||
if parents <= 0: break
|
||||
|
||||
proc getPackageName*(conf: ConfigRef; path: string): string =
|
||||
## returns nimble package name, eg: `cligen`
|
||||
## returns nimble package name, e.g.: `cligen`
|
||||
let path = getNimbleFile(conf, path)
|
||||
result = path.splitFile.name
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ proc eat(p: var Parser, tokType: TokType) =
|
||||
getTok(p)
|
||||
else:
|
||||
lexMessage(p.lex, errGenerated,
|
||||
"expected: '" & TokTypeToStr[tokType] & "', but got: '" & prettyTok(p.tok) & "'")
|
||||
"expected: '" & $tokType & "', but got: '" & prettyTok(p.tok) & "'")
|
||||
|
||||
proc parLineInfo(p: Parser): TLineInfo =
|
||||
## Retrieve the line information associated with the parser's current state.
|
||||
@@ -1310,6 +1310,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||
#| | IND{=} 'of' exprList ':' stmt
|
||||
#| | IND{=} 'elif' expr ':' stmt
|
||||
#| | IND{=} 'except' exprList ':' stmt
|
||||
#| | IND{=} 'finally' ':' stmt
|
||||
#| | IND{=} 'else' ':' stmt )*
|
||||
result = x
|
||||
if p.tok.indent >= 0: return
|
||||
@@ -1364,6 +1365,9 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||
of tkExcept:
|
||||
nextBlock = newNodeP(nkExceptBranch, p)
|
||||
exprList(p, tkColon, nextBlock)
|
||||
of tkFinally:
|
||||
nextBlock = newNodeP(nkFinally, p)
|
||||
getTok(p)
|
||||
of tkElse:
|
||||
nextBlock = newNodeP(nkElse, p)
|
||||
getTok(p)
|
||||
@@ -1374,7 +1378,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||
nextBlock.flags.incl nfBlockArg
|
||||
result.add nextBlock
|
||||
|
||||
if nextBlock.kind == nkElse: break
|
||||
if nextBlock.kind in {nkElse, nkFinally}: break
|
||||
else:
|
||||
if openingParams.kind != nkEmpty:
|
||||
parMessage(p, "expected ':'")
|
||||
|
||||
@@ -99,19 +99,3 @@ when true:
|
||||
proc addFileExt*(x: RelativeFile; ext: string): RelativeFile {.borrow.}
|
||||
|
||||
proc writeFile*(x: AbsoluteFile; content: string) {.borrow.}
|
||||
|
||||
when isMainModule:
|
||||
doAssert AbsoluteDir"/Users/me///" / RelativeFile"z.nim" == AbsoluteFile"/Users/me/z.nim"
|
||||
doAssert AbsoluteDir"/Users/me" / RelativeFile"../z.nim" == AbsoluteFile"/Users/z.nim"
|
||||
doAssert AbsoluteDir"/Users/me/" / RelativeFile"../z.nim" == AbsoluteFile"/Users/z.nim"
|
||||
doAssert relativePath("/foo/bar.nim", "/foo/", '/') == "bar.nim"
|
||||
doAssert $RelativeDir"foo/bar" == "foo/bar"
|
||||
doAssert RelativeDir"foo/bar" == RelativeDir"foo/bar"
|
||||
doAssert RelativeFile"foo/bar".changeFileExt(".txt") == RelativeFile"foo/bar.txt"
|
||||
doAssert RelativeFile"foo/bar".addFileExt(".txt") == RelativeFile"foo/bar.txt"
|
||||
doAssert not RelativeDir"foo/bar".isEmpty
|
||||
doAssert RelativeDir"".isEmpty
|
||||
|
||||
when isMainModule and defined(windows):
|
||||
let nasty = string(AbsoluteDir(r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\linkedPkgs\pkgB-#head\../../simplePkgs/pkgB-#head/") / RelativeFile"pkgA/module.nim")
|
||||
doAssert nasty.replace('/', '\\') == r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\simplePkgs\pkgB-#head\pkgA\module.nim"
|
||||
|
||||
@@ -193,7 +193,7 @@ type
|
||||
cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
|
||||
cpuPowerpc64el, cpuSparc, cpuVm, cpuHppa, cpuIa64, cpuAmd64, cpuMips,
|
||||
cpuMipsel, cpuArm, cpuArm64, cpuJS, cpuNimVM, cpuAVR, cpuMSP430,
|
||||
cpuSparc64, cpuMips64, cpuMips64el, cpuRiscV64, cpuEsp, cpuWasm32
|
||||
cpuSparc64, cpuMips64, cpuMips64el, cpuRiscV32, cpuRiscV64, cpuEsp, cpuWasm32
|
||||
|
||||
type
|
||||
TEndian* = enum
|
||||
@@ -226,6 +226,7 @@ const
|
||||
(name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
|
||||
(name: "mips64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
|
||||
(name: "mips64el", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "riscv32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||
(name: "riscv64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "esp", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||
(name: "wasm32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32)]
|
||||
|
||||
@@ -20,7 +20,7 @@ const
|
||||
|
||||
const
|
||||
declPragmas = {wImportc, wImportObjC, wImportCpp, wImportJs, wExportc, wExportCpp,
|
||||
wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed, wAlign}
|
||||
wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed}
|
||||
## common pragmas for declarations, to a good approximation
|
||||
procPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||
wMagic, wNoSideEffect, wSideEffect, wNoreturn, wNosinks, wDynlib, wHeader,
|
||||
@@ -54,22 +54,23 @@ const
|
||||
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
||||
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
|
||||
wInjectStmt, wExperimental, wThis, wUsed, wInvariant, wAssume, wAssert}
|
||||
lambdaPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||
lambdaPragmas* = {FirstCallConv..LastCallConv,
|
||||
wNoSideEffect, wSideEffect, wNoreturn, wNosinks, wDynlib, wHeader,
|
||||
wThread, wAsmNoStackFrame,
|
||||
wRaises, wLocks, wTags, wRequires, wEnsures,
|
||||
wGcSafe, wCodegenDecl} - {wExportNims, wError, wUsed} # why exclude these?
|
||||
wGcSafe, wCodegenDecl, wNoInit}
|
||||
typePragmas* = declPragmas + {wMagic, wAcyclic,
|
||||
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wShallow,
|
||||
wIncompleteStruct, wCompleteStruct, wByCopy, wByRef,
|
||||
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
|
||||
wBorrow, wGcSafe, wPartial, wExplain, wPackage}
|
||||
fieldPragmas* = declPragmas + {
|
||||
wGuard, wBitsize, wCursor, wRequiresInit, wNoalias} - {wExportNims, wNodecl} # why exclude these?
|
||||
fieldPragmas* = declPragmas + {wGuard, wBitsize, wCursor,
|
||||
wRequiresInit, wNoalias, wAlign} - {wExportNims, wNodecl} # why exclude these?
|
||||
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
|
||||
wMagic, wHeader, wCompilerProc, wCore, wDynlib,
|
||||
wNoInit, wCompileTime, wGlobal,
|
||||
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wCursor, wNoalias}
|
||||
wGensym, wInject, wCodegenDecl,
|
||||
wGuard, wGoto, wCursor, wNoalias, wAlign}
|
||||
constPragmas* = declPragmas + {wHeader, wMagic,
|
||||
wGensym, wInject,
|
||||
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
|
||||
@@ -330,10 +331,10 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
|
||||
sym.typ.callConv = ccCDecl
|
||||
|
||||
proc processNote(c: PContext, n: PNode) =
|
||||
template handleNote(toStrArray, msgMin, notes) =
|
||||
let x = findStr(toStrArray, n[0][1].ident.s)
|
||||
if x >= 0:
|
||||
nk = TNoteKind(x + ord(msgMin))
|
||||
template handleNote(enumVals, notes) =
|
||||
let x = findStr(enumVals, n[0][1].ident.s, errUnknown)
|
||||
if x != errUnknown:
|
||||
nk = TNoteKind(x)
|
||||
let x = c.semConstBoolExpr(c, n[1])
|
||||
n[1] = x
|
||||
if x.kind == nkIntLit and x.intVal != 0: incl(notes, nk)
|
||||
@@ -347,9 +348,9 @@ proc processNote(c: PContext, n: PNode) =
|
||||
n[0][1].kind == nkIdent and n[0][0].kind == nkIdent:
|
||||
var nk: TNoteKind
|
||||
case whichKeyword(n[0][0].ident)
|
||||
of wHint: handleNote(HintsToStr, hintMin, c.config.notes)
|
||||
of wWarning: handleNote(WarningsToStr, warnMin, c.config.notes)
|
||||
of wWarningAsError: handleNote(WarningsToStr, warnMin, c.config.warningAsErrors)
|
||||
of wHint: handleNote(hintMin .. hintMax, c.config.notes)
|
||||
of wWarning: handleNote(warnMin .. warnMax, c.config.notes)
|
||||
of wWarningAsError: handleNote(warnMin .. warnMax, c.config.warningAsErrors)
|
||||
else: invalidPragma(c, n)
|
||||
else: invalidPragma(c, n)
|
||||
|
||||
@@ -896,7 +897,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
of wMagic: processMagic(c, it, sym)
|
||||
of wCompileTime:
|
||||
noVal(c, it)
|
||||
incl(sym.flags, sfCompileTime)
|
||||
if comesFromPush:
|
||||
if sym.kind in {skProc, skFunc}:
|
||||
incl(sym.flags, sfCompileTime)
|
||||
else:
|
||||
incl(sym.flags, sfCompileTime)
|
||||
#incl(sym.loc.flags, lfNoDecl)
|
||||
of wGlobal:
|
||||
noVal(c, it)
|
||||
@@ -1110,9 +1115,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
else:
|
||||
sym.typ.kind = tyUncheckedArray
|
||||
of wUnion:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ.flags, tfUnion)
|
||||
if c.config.backend == backendJs:
|
||||
localError(c.config, it.info, "`{.union.}` is not implemented for js backend.")
|
||||
else:
|
||||
noVal(c, it)
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
else: incl(sym.typ.flags, tfUnion)
|
||||
of wRequiresInit:
|
||||
noVal(c, it)
|
||||
if sym.kind == skField:
|
||||
|
||||
@@ -54,36 +54,3 @@ proc prefixMatch*(p, s: string): PrefixMatch =
|
||||
else:
|
||||
return PrefixMatch.None
|
||||
return PrefixMatch.None
|
||||
|
||||
when isMainModule:
|
||||
import macros
|
||||
|
||||
macro check(val, body: untyped): untyped =
|
||||
result = newStmtList()
|
||||
expectKind body, nnkStmtList
|
||||
for b in body:
|
||||
expectKind b, nnkPar
|
||||
expectLen b, 2
|
||||
let p = b[0]
|
||||
let s = b[1]
|
||||
result.add quote do:
|
||||
echo prefixMatch(`p`, `s`) == `val`
|
||||
|
||||
check PrefixMatch.Prefix:
|
||||
("abc", "abc")
|
||||
("a", "abc")
|
||||
("xyz", "X_yzzzZe")
|
||||
|
||||
check PrefixMatch.Substr:
|
||||
("b", "abc")
|
||||
("abc", "fooabcabc")
|
||||
("abC", "foo_AB_c")
|
||||
|
||||
check PrefixMatch.Abbrev:
|
||||
("abc", "AxxxBxxxCxxx")
|
||||
("xyz", "X_yabcZe")
|
||||
|
||||
check PrefixMatch.None:
|
||||
("foobar", "afkslfjd_as")
|
||||
("xyz", "X_yuuZuuZe")
|
||||
("ru", "remotes")
|
||||
|
||||
@@ -597,7 +597,7 @@ proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0,
|
||||
gsub(g, n[i])
|
||||
if c:
|
||||
if g.tokens.len > oldLen:
|
||||
putWithSpace(g, separator, TokTypeToStr[separator])
|
||||
putWithSpace(g, separator, $separator)
|
||||
if hasCom(n[i]):
|
||||
gcoms(g)
|
||||
optNL(g, ind)
|
||||
@@ -1226,7 +1226,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
infixArgument(g, n, 1)
|
||||
put(g, tkSpaces, Space)
|
||||
gsub(g, n, 0) # binary operator
|
||||
# eg: `n1 == n2` decompses as following sum:
|
||||
# e.g.: `n1 == n2` decompses as following sum:
|
||||
if n.len == 3 and not fits(g, oldLineLen + lsub(g, n[1]) + lsub(g, n[2]) + lsub(g, n[0]) + len(" ")):
|
||||
optNL(g, g.indent + longIndentWid)
|
||||
else:
|
||||
|
||||
@@ -105,6 +105,7 @@ proc computeDeps(cache: IdentCache; n: PNode, declares, uses: var IntSet; topLev
|
||||
decl(a[1])
|
||||
else:
|
||||
for i in 0..<n.safeLen: deps(n[i])
|
||||
of nkMixinStmt, nkBindStmt: discard
|
||||
else:
|
||||
for i in 0..<n.safeLen: deps(n[i])
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ proc endsInNoReturn(n: PNode): bool =
|
||||
var it = n
|
||||
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
|
||||
it = it.lastSon
|
||||
result = it.kind in (nkLastBlockStmts-{nkReturnStmt}) or
|
||||
result = it.kind in nkLastBlockStmts or
|
||||
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags
|
||||
|
||||
proc commonType*(x: PType, y: PNode): PType =
|
||||
|
||||
@@ -230,6 +230,9 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||
doAssert err.firstMismatch.formal != nil
|
||||
candidates.add("\n required type for " & nameParam & ": ")
|
||||
candidates.add typeToString(wanted)
|
||||
when false:
|
||||
if wanted.sym != nil:
|
||||
candidates.add "(" & (c.config $ wanted.sym.info) & ")"
|
||||
candidates.add "\n but expression '"
|
||||
if err.firstMismatch.kind == kVarNeeded:
|
||||
candidates.add renderNotLValue(nArg)
|
||||
@@ -239,6 +242,10 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||
candidates.add "' is of type: "
|
||||
var got = nArg.typ
|
||||
candidates.add typeToString(got)
|
||||
when false:
|
||||
if got.sym != nil:
|
||||
candidates.add "(" & (c.config $ got.sym.info) & ")"
|
||||
|
||||
doAssert wanted != nil
|
||||
if got != nil: effectProblem(wanted, got, candidates, c)
|
||||
of kUnknown: discard "do not break 'nim check'"
|
||||
@@ -323,7 +330,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
|
||||
var typeHint = ""
|
||||
if sym == nil:
|
||||
# Perhaps we're in a `compiles(foo.bar)` expression, or
|
||||
# in a concept, eg:
|
||||
# in a concept, e.g.:
|
||||
# ExplainedConcept {.explain.} = concept x
|
||||
# x.foo is int
|
||||
# We could use: `(c.config $ n[1].info)` to get more context.
|
||||
|
||||
@@ -25,8 +25,8 @@ type
|
||||
|
||||
POptionEntry* = ref TOptionEntry
|
||||
PProcCon* = ref TProcCon
|
||||
TProcCon* = object # procedure context; also used for top-level
|
||||
# statements
|
||||
TProcCon* {.acyclic.} = object # procedure context; also used for top-level
|
||||
# statements
|
||||
owner*: PSym # the symbol this context belongs to
|
||||
resultSym*: PSym # the result symbol (if we are in a proc)
|
||||
selfSym*: PSym # the 'self' symbol (if available)
|
||||
@@ -38,6 +38,7 @@ type
|
||||
mappingExists*: bool
|
||||
mapping*: TIdTable
|
||||
caseContext*: seq[tuple[n: PNode, idx: int]]
|
||||
localBindStmts*: seq[PNode]
|
||||
|
||||
TMatchedConcept* = object
|
||||
candidateType*: PType
|
||||
|
||||
@@ -431,7 +431,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
m.diagnostics = @[]
|
||||
m.diagnosticsEnabled = true
|
||||
res = typeRel(m, t2, t1) >= isSubtype # isNone
|
||||
# `res = sameType(t1, t2)` would be wrong, eg for `int is (int|float)`
|
||||
# `res = sameType(t1, t2)` would be wrong, e.g. for `int is (int|float)`
|
||||
|
||||
result = newIntNode(nkIntLit, ord(res))
|
||||
result.typ = n.typ
|
||||
@@ -1216,6 +1216,9 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
# not sure the symbol really ends up being used:
|
||||
# var len = 0 # but won't be called
|
||||
# genericThatUsesLen(x) # marked as taking a closure?
|
||||
if hasWarn(c.config, warnResultUsed):
|
||||
message(c.config, n.info, warnResultUsed)
|
||||
|
||||
of skGenericParam:
|
||||
onUse(n.info, s)
|
||||
if s.typ.kind == tyStatic:
|
||||
@@ -2901,6 +2904,13 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
for i in 0..<n.len:
|
||||
n[i] = semExpr(c, n[i])
|
||||
of nkComesFrom: discard "ignore the comes from information for now"
|
||||
of nkMixinStmt: discard
|
||||
of nkBindStmt:
|
||||
if c.p != nil:
|
||||
c.p.localBindStmts.add n
|
||||
else:
|
||||
localError(c.config, n.info, "invalid context for 'bind' statement: " &
|
||||
renderTree(n, {renderNoComments}))
|
||||
else:
|
||||
localError(c.config, n.info, "invalid expression: " &
|
||||
renderTree(n, {renderNoComments}))
|
||||
|
||||
@@ -720,6 +720,7 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
of nkBracketExpr: result = foldArrayAccess(m, n, g)
|
||||
of nkDotExpr: result = foldFieldAccess(m, n, g)
|
||||
of nkCheckedFieldExpr:
|
||||
assert n[0].kind == nkDotExpr
|
||||
result = foldFieldAccess(m, n[0], g)
|
||||
of nkStmtListExpr:
|
||||
var i = 0
|
||||
|
||||
@@ -319,6 +319,14 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
|
||||
prc.typ = result
|
||||
popInfoContext(c.config)
|
||||
|
||||
proc fillMixinScope(c: PContext) =
|
||||
var p = c.p
|
||||
while p != nil:
|
||||
for bnd in p.localBindStmts:
|
||||
for n in bnd:
|
||||
addSym(c.currentScope, n.sym)
|
||||
p = p.next
|
||||
|
||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
info: TLineInfo): PSym {.nosinks.} =
|
||||
## Generates a new instance of a generic procedure.
|
||||
@@ -345,6 +353,10 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
result.ast = n
|
||||
pushOwner(c, result)
|
||||
|
||||
# mixin scope:
|
||||
openScope(c)
|
||||
fillMixinScope(c)
|
||||
|
||||
openScope(c)
|
||||
let gp = n[genericParamsPos]
|
||||
internalAssert c.config, gp.kind != nkEmpty
|
||||
@@ -395,6 +407,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
popProcCon(c)
|
||||
popInfoContext(c.config)
|
||||
closeScope(c) # close scope for parameters
|
||||
closeScope(c) # close scope for 'mixin' declarations
|
||||
popOwner(c)
|
||||
c.currentScope = oldScope
|
||||
discard c.friendModules.pop()
|
||||
|
||||
@@ -527,14 +527,24 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
if n[^1].kind == nkSym and n[^1].sym.kind notin {skProc, skFunc}:
|
||||
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
|
||||
elif optTinyRtti in c.config.globalOptions:
|
||||
let fin = if n[^1].kind == nkLambda: n[^1][namePos].sym
|
||||
else: n[^1].sym
|
||||
# check if we converted this finalizer into a destructor already:
|
||||
let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef}))
|
||||
if t != nil and t.attachedOps[attachedDestructor] != nil and t.attachedOps[attachedDestructor].owner == fin:
|
||||
discard "already turned this one into a finalizer"
|
||||
else:
|
||||
bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor)
|
||||
let nfin = skipConvCastAndClosure(n[^1])
|
||||
let fin = case nfin.kind
|
||||
of nkSym: nfin.sym
|
||||
of nkLambda, nkDo: nfin[namePos].sym
|
||||
else:
|
||||
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
|
||||
nil
|
||||
if fin != nil:
|
||||
if fin.kind notin {skProc, skFunc}:
|
||||
# calling convention is checked in codegen
|
||||
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
|
||||
|
||||
# check if we converted this finalizer into a destructor already:
|
||||
let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef}))
|
||||
if t != nil and t.attachedOps[attachedDestructor] != nil and t.attachedOps[attachedDestructor].owner == fin:
|
||||
discard "already turned this one into a finalizer"
|
||||
else:
|
||||
bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor)
|
||||
result = n
|
||||
of mDestroy:
|
||||
result = n
|
||||
|
||||
@@ -391,7 +391,8 @@ proc analyse(c: var AnalysisCtx; n: PNode) =
|
||||
addFactNeg(c.guards, canon(n[0], c.guards.o))
|
||||
dec c.inLoop
|
||||
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
|
||||
nkMacroDef, nkTemplateDef, nkConstSection, nkPragma, nkFuncDef:
|
||||
nkMacroDef, nkTemplateDef, nkConstSection, nkPragma, nkFuncDef,
|
||||
nkMixinStmt, nkBindStmt, nkExportStmt:
|
||||
discard
|
||||
else:
|
||||
analyseSons(c, n)
|
||||
|
||||
@@ -510,29 +510,30 @@ proc procVarCheck(n: PNode; conf: ConfigRef) =
|
||||
proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
|
||||
let n = n.skipConv
|
||||
if paramType.isNil or paramType.kind != tyTypeDesc:
|
||||
procVarCheck skipConvAndClosure(n), tracked.config
|
||||
procVarCheck skipConvCastAndClosure(n), tracked.config
|
||||
#elif n.kind in nkSymChoices:
|
||||
# echo "came here"
|
||||
let paramType = paramType.skipTypesOrNil(abstractInst)
|
||||
if paramType != nil and tfNotNil in paramType.flags and
|
||||
n.typ != nil and tfNotNil notin n.typ.flags:
|
||||
if isAddrNode(n):
|
||||
# addr(x[]) can't be proven, but addr(x) can:
|
||||
if not containsNode(n, {nkDerefExpr, nkHiddenDeref}): return
|
||||
elif (n.kind == nkSym and n.sym.kind in routineKinds) or
|
||||
(n.kind in procDefs+{nkObjConstr, nkBracket, nkClosure, nkStrLit..nkTripleStrLit}) or
|
||||
(n.kind in nkCallKinds and n[0].kind == nkSym and n[0].sym.magic == mArrToSeq) or
|
||||
n.typ.kind == tyTypeDesc:
|
||||
# 'p' is not nil obviously:
|
||||
return
|
||||
case impliesNotNil(tracked.guards, n)
|
||||
of impUnknown:
|
||||
message(tracked.config, n.info, errGenerated,
|
||||
"cannot prove '$1' is not nil" % n.renderTree)
|
||||
of impNo:
|
||||
message(tracked.config, n.info, errGenerated,
|
||||
"'$1' is provably nil" % n.renderTree)
|
||||
of impYes: discard
|
||||
if paramType != nil and tfNotNil in paramType.flags and n.typ != nil:
|
||||
let ntyp = n.typ.skipTypesOrNil({tyVar, tyLent, tySink})
|
||||
if ntyp != nil and tfNotNil notin ntyp.flags:
|
||||
if isAddrNode(n):
|
||||
# addr(x[]) can't be proven, but addr(x) can:
|
||||
if not containsNode(n, {nkDerefExpr, nkHiddenDeref}): return
|
||||
elif (n.kind == nkSym and n.sym.kind in routineKinds) or
|
||||
(n.kind in procDefs+{nkObjConstr, nkBracket, nkClosure, nkStrLit..nkTripleStrLit}) or
|
||||
(n.kind in nkCallKinds and n[0].kind == nkSym and n[0].sym.magic == mArrToSeq) or
|
||||
n.typ.kind == tyTypeDesc:
|
||||
# 'p' is not nil obviously:
|
||||
return
|
||||
case impliesNotNil(tracked.guards, n)
|
||||
of impUnknown:
|
||||
message(tracked.config, n.info, errGenerated,
|
||||
"cannot prove '$1' is not nil" % n.renderTree)
|
||||
of impNo:
|
||||
message(tracked.config, n.info, errGenerated,
|
||||
"'$1' is provably nil" % n.renderTree)
|
||||
of impYes: discard
|
||||
|
||||
proc assumeTheWorst(tracked: PEffects; n: PNode; op: PType) =
|
||||
addRaiseEffect(tracked, createRaise(tracked.graph, n), nil)
|
||||
@@ -555,7 +556,7 @@ proc isTrival(caller: PNode): bool {.inline.} =
|
||||
result = caller.kind == nkSym and caller.sym.magic in {mEqProc, mIsNil, mMove, mWasMoved, mSwap}
|
||||
|
||||
proc trackOperandForIndirectCall(tracked: PEffects, n: PNode, paramType: PType; caller: PNode) =
|
||||
let a = skipConvAndClosure(n)
|
||||
let a = skipConvCastAndClosure(n)
|
||||
let op = a.typ
|
||||
# assume indirect calls are taken here:
|
||||
if op != nil and op.kind == tyProc and n.skipConv.kind != nkNilLit and not isTrival(caller):
|
||||
@@ -754,63 +755,66 @@ proc trackCall(tracked: PEffects; n: PNode) =
|
||||
if n.typ != nil:
|
||||
if tracked.owner.kind != skMacro and n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
createTypeBoundOps(tracked, n.typ, n.info)
|
||||
if getConstExpr(tracked.ownerModule, n, tracked.graph) != nil:
|
||||
return
|
||||
if a.kind == nkCast and a[1].typ.kind == tyProc:
|
||||
a = a[1]
|
||||
# XXX: in rare situations, templates and macros will reach here after
|
||||
# calling getAst(templateOrMacro()). Currently, templates and macros
|
||||
# are indistinguishable from normal procs (both have tyProc type) and
|
||||
# we can detect them only by checking for attached nkEffectList.
|
||||
if op != nil and op.kind == tyProc and op.n[0].kind == nkEffectList:
|
||||
if a.kind == nkSym:
|
||||
if a.sym == tracked.owner: tracked.isRecursive = true
|
||||
# even for recursive calls we need to check the lock levels (!):
|
||||
mergeLockLevels(tracked, n, a.sym.getLockLevel)
|
||||
if sfSideEffect in a.sym.flags: markSideEffect(tracked, a)
|
||||
else:
|
||||
mergeLockLevels(tracked, n, op.lockLevel)
|
||||
var effectList = op.n[0]
|
||||
if a.kind == nkSym and a.sym.kind == skMethod:
|
||||
propagateEffects(tracked, n, a.sym)
|
||||
elif isNoEffectList(effectList):
|
||||
if isForwardedProc(a):
|
||||
propagateEffects(tracked, n, a.sym)
|
||||
elif isIndirectCall(a, tracked.owner):
|
||||
assumeTheWorst(tracked, n, op)
|
||||
gcsafeAndSideeffectCheck()
|
||||
else:
|
||||
mergeRaises(tracked, effectList[exceptionEffects], n)
|
||||
mergeTags(tracked, effectList[tagEffects], n)
|
||||
gcsafeAndSideeffectCheck()
|
||||
if a.kind != nkSym or a.sym.magic != mNBindSym:
|
||||
for i in 1..<n.len: trackOperandForIndirectCall(tracked, n[i], paramType(op, i), a)
|
||||
if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
|
||||
# may not look like an assignment, but it is:
|
||||
let arg = n[1]
|
||||
initVarViaNew(tracked, arg)
|
||||
if arg.typ.len != 0 and {tfRequiresInit} * arg.typ.lastSon.flags != {}:
|
||||
if a.sym.magic == mNewSeq and n[2].kind in {nkCharLit..nkUInt64Lit} and
|
||||
n[2].intVal == 0:
|
||||
# var s: seq[notnil]; newSeq(s, 0) is a special case!
|
||||
discard
|
||||
if getConstExpr(tracked.ownerModule, n, tracked.graph) == nil:
|
||||
if a.kind == nkCast and a[1].typ.kind == tyProc:
|
||||
a = a[1]
|
||||
# XXX: in rare situations, templates and macros will reach here after
|
||||
# calling getAst(templateOrMacro()). Currently, templates and macros
|
||||
# are indistinguishable from normal procs (both have tyProc type) and
|
||||
# we can detect them only by checking for attached nkEffectList.
|
||||
if op != nil and op.kind == tyProc and op.n[0].kind == nkEffectList:
|
||||
if a.kind == nkSym:
|
||||
if a.sym == tracked.owner: tracked.isRecursive = true
|
||||
# even for recursive calls we need to check the lock levels (!):
|
||||
mergeLockLevels(tracked, n, a.sym.getLockLevel)
|
||||
if sfSideEffect in a.sym.flags: markSideEffect(tracked, a)
|
||||
else:
|
||||
message(tracked.config, arg.info, warnProveInit, $arg)
|
||||
mergeLockLevels(tracked, n, op.lockLevel)
|
||||
var effectList = op.n[0]
|
||||
if a.kind == nkSym and a.sym.kind == skMethod:
|
||||
propagateEffects(tracked, n, a.sym)
|
||||
elif isNoEffectList(effectList):
|
||||
if isForwardedProc(a):
|
||||
propagateEffects(tracked, n, a.sym)
|
||||
elif isIndirectCall(a, tracked.owner):
|
||||
assumeTheWorst(tracked, n, op)
|
||||
gcsafeAndSideeffectCheck()
|
||||
else:
|
||||
mergeRaises(tracked, effectList[exceptionEffects], n)
|
||||
mergeTags(tracked, effectList[tagEffects], n)
|
||||
gcsafeAndSideeffectCheck()
|
||||
if a.kind != nkSym or a.sym.magic != mNBindSym:
|
||||
for i in 1..<n.len: trackOperandForIndirectCall(tracked, n[i], paramType(op, i), a)
|
||||
if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
|
||||
# may not look like an assignment, but it is:
|
||||
let arg = n[1]
|
||||
initVarViaNew(tracked, arg)
|
||||
if arg.typ.len != 0 and {tfRequiresInit} * arg.typ.lastSon.flags != {}:
|
||||
if a.sym.magic == mNewSeq and n[2].kind in {nkCharLit..nkUInt64Lit} and
|
||||
n[2].intVal == 0:
|
||||
# var s: seq[notnil]; newSeq(s, 0) is a special case!
|
||||
discard
|
||||
else:
|
||||
message(tracked.config, arg.info, warnProveInit, $arg)
|
||||
|
||||
# check required for 'nim check':
|
||||
if n[1].typ.len > 0:
|
||||
createTypeBoundOps(tracked, n[1].typ.lastSon, n.info)
|
||||
createTypeBoundOps(tracked, n[1].typ, n.info)
|
||||
# new(x, finalizer): Problem: how to move finalizer into 'createTypeBoundOps'?
|
||||
# check required for 'nim check':
|
||||
if n[1].typ.len > 0:
|
||||
createTypeBoundOps(tracked, n[1].typ.lastSon, n.info)
|
||||
createTypeBoundOps(tracked, n[1].typ, n.info)
|
||||
# new(x, finalizer): Problem: how to move finalizer into 'createTypeBoundOps'?
|
||||
|
||||
elif a.kind == nkSym and a.sym.magic in {mArrGet, mArrPut} and
|
||||
optStaticBoundsCheck in tracked.currOptions:
|
||||
checkBounds(tracked, n[1], n[2])
|
||||
elif a.kind == nkSym and a.sym.magic in {mArrGet, mArrPut} and
|
||||
optStaticBoundsCheck in tracked.currOptions:
|
||||
checkBounds(tracked, n[1], n[2])
|
||||
|
||||
if a.kind != nkSym or a.sym.magic != mRunnableExamples:
|
||||
for i in 0..<n.safeLen:
|
||||
track(tracked, n[i])
|
||||
|
||||
if a.kind == nkSym and a.sym.name.s.len > 0 and a.sym.name.s[0] == '=' and
|
||||
tracked.owner.kind != skMacro:
|
||||
var opKind = find(AttachedOpToStr, a.sym.name.s.normalize)
|
||||
if a.sym.name.s.normalize == "=": opKind = attachedAsgn.int
|
||||
if a.sym.name.s == "=": opKind = attachedAsgn.int
|
||||
if opKind != -1:
|
||||
# rebind type bounds operations after createTypeBoundOps call
|
||||
let t = n[1].typ.skipTypes({tyAlias, tyVar})
|
||||
@@ -820,9 +824,6 @@ proc trackCall(tracked: PEffects; n: PNode) =
|
||||
if op != nil:
|
||||
n[0].sym = op
|
||||
|
||||
if a.kind != nkSym or a.sym.magic != mRunnableExamples:
|
||||
for i in 0..<n.safeLen:
|
||||
track(tracked, n[i])
|
||||
if op != nil and op.kind == tyProc:
|
||||
for i in 1..<min(n.safeLen, op.len):
|
||||
case op[i].kind
|
||||
|
||||
@@ -435,7 +435,7 @@ proc semLowerLetVarCustomPragma(c: PContext, a: PNode, n: PNode): PNode =
|
||||
var b = a[0]
|
||||
if b.kind == nkPragmaExpr:
|
||||
if b[1].len != 1:
|
||||
# we could in future support pragmas w args eg: `var foo {.bar:"goo".} = expr`
|
||||
# we could in future support pragmas w args e.g.: `var foo {.bar:"goo".} = expr`
|
||||
return nil
|
||||
let nodePragma = b[1][0]
|
||||
# see: `singlePragma`
|
||||
@@ -477,7 +477,7 @@ proc semLowerLetVarCustomPragma(c: PContext, a: PNode, n: PNode): PNode =
|
||||
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
if n.len == 1:
|
||||
result = semLowerLetVarCustomPragma(c, n[0], n)
|
||||
if result!=nil: return result
|
||||
if result != nil: return result
|
||||
|
||||
var b: PNode
|
||||
result = copyNode(n)
|
||||
@@ -513,7 +513,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
def = fitNode(c, typ, def, def.info)
|
||||
#changeType(def.skipConv, typ, check=true)
|
||||
else:
|
||||
typ = def.typ.skipTypes({tyStatic}).skipIntLit
|
||||
typ = def.typ.skipTypes({tyStatic, tySink}).skipIntLit
|
||||
if typ.kind in tyUserTypeClasses and typ.isResolvedUserTypeClass:
|
||||
typ = typ.lastSon
|
||||
if hasEmpty(typ):
|
||||
@@ -738,7 +738,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
else:
|
||||
v.typ = iter[i]
|
||||
n[0][i] = newSymNode(v)
|
||||
if sfGenSym notin v.flags: addDecl(c, v)
|
||||
if sfGenSym notin v.flags and not isDiscardUnderscore(v): addDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
else:
|
||||
var v = symForVar(c, n[0])
|
||||
@@ -748,7 +748,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
# for an example:
|
||||
v.typ = iterBase
|
||||
n[0] = newSymNode(v)
|
||||
if sfGenSym notin v.flags: addDecl(c, v)
|
||||
if sfGenSym notin v.flags and not isDiscardUnderscore(v): addDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
else:
|
||||
localError(c.config, n.info, errWrongNumberOfVariables)
|
||||
@@ -1276,8 +1276,18 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
internalAssert c.config, st.lastSon.sym == nil
|
||||
incl st.flags, tfRefsAnonObj
|
||||
let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"),
|
||||
getCurrOwner(c), s.info)
|
||||
obj.ast = a
|
||||
getCurrOwner(c), s.info)
|
||||
let symNode = newSymNode(obj)
|
||||
obj.ast = a.shallowCopy
|
||||
case a[0].kind
|
||||
of nkSym: obj.ast[0] = symNode
|
||||
of nkPragmaExpr:
|
||||
obj.ast[0] = a[0].shallowCopy
|
||||
obj.ast[0][0] = symNode
|
||||
obj.ast[0][1] = a[0][1]
|
||||
else: assert(false)
|
||||
obj.ast[1] = a[1]
|
||||
obj.ast[2] = a[2][0]
|
||||
if sfPure in s.flags:
|
||||
obj.flags.incl sfPure
|
||||
obj.typ = st.lastSon
|
||||
@@ -1812,8 +1822,8 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
|
||||
let t = tt[col]
|
||||
if t != nil and t.kind == tyGenericInvocation:
|
||||
var x = skipTypes(t[0], {tyVar, tyLent, tyPtr, tyRef, tyGenericInst,
|
||||
tyGenericInvocation, tyGenericBody,
|
||||
tyAlias, tySink, tyOwned})
|
||||
tyGenericInvocation, tyGenericBody,
|
||||
tyAlias, tySink, tyOwned})
|
||||
if x.kind == tyObject and t.len-1 == n[genericParamsPos].len:
|
||||
foundObj = true
|
||||
x.methods.add((col,s))
|
||||
|
||||
@@ -86,6 +86,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
|
||||
a = nextOverloadIter(o, c, n)
|
||||
|
||||
proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
|
||||
result = copyNode(n)
|
||||
for i in 0..<n.len:
|
||||
var a = n[i]
|
||||
# If 'a' is an overloaded symbol, we used to use the first symbol
|
||||
@@ -99,16 +100,19 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
|
||||
let sc = symChoice(c, n, s, scClosed)
|
||||
if sc.kind == nkSym:
|
||||
toBind.incl(sc.sym.id)
|
||||
result.add sc
|
||||
else:
|
||||
for x in items(sc): toBind.incl(x.sym.id)
|
||||
for x in items(sc):
|
||||
toBind.incl(x.sym.id)
|
||||
result.add x
|
||||
else:
|
||||
illFormedAst(a, c.config)
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
|
||||
proc semMixinStmt(c: PContext, n: PNode, toMixin: var IntSet): PNode =
|
||||
result = copyNode(n)
|
||||
for i in 0..<n.len:
|
||||
toMixin.incl(considerQuotedIdent(c, n[i]).id)
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
result.add symChoice(c, n[i], nil, scForceOpen)
|
||||
|
||||
proc replaceIdentBySym(c: PContext; n: var PNode, s: PNode) =
|
||||
case n.kind
|
||||
|
||||
@@ -133,7 +133,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
e.typ = result
|
||||
e.position = int(counter)
|
||||
let symNode = newSymNode(e)
|
||||
if optNimV1Emulation notin c.config.globalOptions and identToReplace != nil:
|
||||
if optNimV1Emulation notin c.config.globalOptions and identToReplace != nil and
|
||||
c.config.cmd != cmdDoc: # A hack to produce documentation for enum fields.
|
||||
identToReplace[] = symNode
|
||||
if e.position == 0: hasNull = true
|
||||
if result.sym != nil and sfExported in result.sym.flags:
|
||||
@@ -158,7 +159,7 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
||||
var base = semTypeNode(c, n[1], nil)
|
||||
addSonSkipIntLit(result, base)
|
||||
if base.kind in {tyGenericInst, tyAlias, tySink}: base = lastSon(base)
|
||||
if base.kind != tyGenericParam:
|
||||
if base.kind notin {tyGenericParam, tyGenericInvocation}:
|
||||
if not isOrdinalType(base, allowEnumWithHoles = true):
|
||||
localError(c.config, n.info, errOrdinalTypeExpected)
|
||||
elif lengthOrd(c.config, base) > MaxSetElements:
|
||||
@@ -305,7 +306,7 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
|
||||
result = makeRangeWithStaticExpr(c, e)
|
||||
if c.inGenericContext > 0: result.flags.incl tfUnresolved
|
||||
elif e.kind in (nkCallKinds + {nkBracketExpr}) and hasUnresolvedArgs(c, e):
|
||||
if not isOrdinalType(e.typ):
|
||||
if not isOrdinalType(e.typ.skipTypes({tyStatic, tyAlias, tyGenericInst, tySink})):
|
||||
localError(c.config, n[1].info, errOrdinalTypeExpected)
|
||||
# This is an int returning call, depending on an
|
||||
# yet unknown generic param (see tgenericshardcases).
|
||||
@@ -840,7 +841,7 @@ proc addInheritedFields(c: PContext, check: var IntSet, pos: var int,
|
||||
addInheritedFields(c, check, pos, obj[0].skipGenericInvocation)
|
||||
addInheritedFieldsAux(c, check, pos, obj.n)
|
||||
|
||||
proc semObjectNode(c: PContext, n: PNode, prev: PType; isInheritable: bool): PType =
|
||||
proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType =
|
||||
if n.len == 0:
|
||||
return newConstraint(c, tyObject)
|
||||
var check = initIntSet()
|
||||
@@ -876,8 +877,9 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType; isInheritable: bool): PTy
|
||||
if n.kind != nkObjectTy: internalError(c.config, n.info, "semObjectNode")
|
||||
result = newOrPrevType(tyObject, prev, c)
|
||||
rawAddSon(result, realBase)
|
||||
if realBase == nil and isInheritable:
|
||||
if realBase == nil and tfInheritable in flags:
|
||||
result.flags.incl tfInheritable
|
||||
if tfAcyclic in flags: result.flags.incl tfAcyclic
|
||||
if result.n.isNil:
|
||||
result.n = newNodeI(nkRecList, n.info)
|
||||
else:
|
||||
@@ -902,8 +904,8 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
|
||||
let n = if n[0].kind == nkBracket: n[0] else: n
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
let body = n.lastSon
|
||||
var t = if prev != nil and body.kind == nkObjectTy and tfInheritable in prev.flags:
|
||||
semObjectNode(c, body, nil, isInheritable=true)
|
||||
var t = if prev != nil and body.kind == nkObjectTy:
|
||||
semObjectNode(c, body, nil, prev.flags)
|
||||
else:
|
||||
semTypeNode(c, body, nil)
|
||||
if t.kind == tyTypeDesc and tfUnresolved notin t.flags:
|
||||
@@ -1057,7 +1059,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
# disable the bindOnce behavior for the type class
|
||||
result = recurse(paramType.base, true)
|
||||
|
||||
of tyAlias, tyOwned:
|
||||
of tyAlias, tyOwned, tySink:
|
||||
result = recurse(paramType.base)
|
||||
|
||||
of tySequence, tySet, tyArray, tyOpenArray,
|
||||
@@ -1316,7 +1318,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
"' is only valid for macros and templates")
|
||||
# 'auto' as a return type does not imply a generic:
|
||||
elif r.kind == tyAnything:
|
||||
# 'p(): auto' and 'p(): expr' are equivalent, but the rest of the
|
||||
# 'p(): auto' and 'p(): untyped' are equivalent, but the rest of the
|
||||
# compiler is hardly aware of 'auto':
|
||||
r = newTypeS(tyUntyped, c)
|
||||
elif r.kind == tyStatic:
|
||||
@@ -1915,7 +1917,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
localError(c.config, n.info, "type expected, but got symbol '$1' of kind '$2'" %
|
||||
[s.name.s, substr($s.kind, 2)])
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
of nkObjectTy: result = semObjectNode(c, n, prev, isInheritable=false)
|
||||
of nkObjectTy: result = semObjectNode(c, n, prev, {})
|
||||
of nkTupleTy: result = semTuple(c, n, prev)
|
||||
of nkTupleClassTy: result = newConstraint(c, tyTuple)
|
||||
of nkTypeClassTy: result = semTypeClass(c, n, prev)
|
||||
|
||||
@@ -67,7 +67,7 @@ proc cacheTypeInst*(inst: PType) =
|
||||
gt.sym.typeInstCache.add(inst)
|
||||
|
||||
type
|
||||
LayeredIdTable* = ref object
|
||||
LayeredIdTable* {.acyclic.} = ref object
|
||||
topLayer*: TIdTable
|
||||
nextLayer*: LayeredIdTable
|
||||
|
||||
|
||||
@@ -1076,7 +1076,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
return typeRel(c, f, lastSon(aOrig), flags)
|
||||
|
||||
if a.kind == tyGenericInst and
|
||||
skipTypes(f, {tyVar, tyLent, tySink}).kind notin {
|
||||
skipTypes(f, {tyStatic, tyVar, tyLent, tySink}).kind notin {
|
||||
tyGenericBody, tyGenericInvocation,
|
||||
tyGenericInst, tyGenericParam} + tyTypeClasses:
|
||||
return typeRel(c, f, lastSon(a), flags)
|
||||
@@ -1237,8 +1237,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
if result < isGeneric: result = isNone
|
||||
else: discard
|
||||
of tyOpenArray, tyVarargs:
|
||||
# varargs[expr] is special too but handled earlier. So we only need to
|
||||
# handle varargs[stmt] which is the same as varargs[typed]:
|
||||
# varargs[untyped] is special too but handled earlier. So we only need to
|
||||
# handle varargs[typed]:
|
||||
if f.kind == tyVarargs:
|
||||
if tfVarargs in a.flags:
|
||||
return typeRel(c, f.base, a.lastSon, flags)
|
||||
@@ -1551,7 +1551,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
for i in 1..<f.len:
|
||||
let x = PType(idTableGet(c.bindings, genericBody[i-1]))
|
||||
if x == nil:
|
||||
discard "maybe fine (for eg. a==tyNil)"
|
||||
discard "maybe fine (for e.g. a==tyNil)"
|
||||
elif x.kind in {tyGenericInvocation, tyGenericParam}:
|
||||
internalError(c.c.graph.config, "wrong instantiated type!")
|
||||
else:
|
||||
@@ -2485,7 +2485,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var Int
|
||||
container = nil
|
||||
else:
|
||||
# we end up here if the argument can be converted into the varargs
|
||||
# formal (eg. seq[T] -> varargs[T]) but we have already instantiated
|
||||
# formal (e.g. seq[T] -> varargs[T]) but we have already instantiated
|
||||
# a container
|
||||
#assert arg.kind == nkHiddenStdConv # for 'nim check'
|
||||
# this assertion can be off
|
||||
|
||||
@@ -242,7 +242,7 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
else:
|
||||
typ.size = conf.target.ptrSize
|
||||
typ.align = int16(conf.target.ptrSize)
|
||||
of tyCString, tySequence, tyPtr, tyRef, tyVar, tyLent, tyOpenArray:
|
||||
of tyCString, tySequence, tyPtr, tyRef, tyVar, tyLent:
|
||||
let base = typ.lastSon
|
||||
if base == typ:
|
||||
# this is not the correct location to detect ``type A = ptr A``
|
||||
@@ -258,12 +258,16 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
|
||||
of tyArray:
|
||||
computeSizeAlign(conf, typ[1])
|
||||
let elemSize = typ[1].size
|
||||
let elemSize = typ[1].size
|
||||
let len = lengthOrd(conf, typ[0])
|
||||
if elemSize < 0:
|
||||
typ.size = elemSize
|
||||
typ.align = int16(elemSize)
|
||||
elif len < 0:
|
||||
typ.size = szUnknownSize
|
||||
typ.align = szUnknownSize
|
||||
else:
|
||||
typ.size = toInt64Checked(lengthOrd(conf, typ[0]) * int32(elemSize), szTooBigSize)
|
||||
typ.size = toInt64Checked(len * int32(elemSize), szTooBigSize)
|
||||
typ.align = typ[1].align
|
||||
|
||||
of tyUncheckedArray:
|
||||
@@ -277,14 +281,14 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
typ.size = 4 # use signed int32
|
||||
typ.align = 4
|
||||
else:
|
||||
let length = toInt64(lastOrd(conf, typ)) # BUGFIX: use lastOrd!
|
||||
if length + 1 < `shl`(1, 8):
|
||||
let lastOrd = toInt64(lastOrd(conf, typ)) # BUGFIX: use lastOrd!
|
||||
if lastOrd < `shl`(1, 8):
|
||||
typ.size = 1
|
||||
typ.align = 1
|
||||
elif length + 1 < `shl`(1, 16):
|
||||
elif lastOrd < `shl`(1, 16):
|
||||
typ.size = 2
|
||||
typ.align = 2
|
||||
elif length + 1 < `shl`(BiggestInt(1), 32):
|
||||
elif lastOrd < `shl`(BiggestInt(1), 32):
|
||||
typ.size = 4
|
||||
typ.align = 4
|
||||
else:
|
||||
|
||||
@@ -12,7 +12,7 @@ proc dataPointer*[T](a: T): pointer =
|
||||
## same as C++ `data` that works with std::string, std::vector etc.
|
||||
## Note: safe to use when a.len == 0 but whether the result is nil or not
|
||||
## is implementation defined for performance reasons.
|
||||
# this could be improved with ocmpiler support to avoid the `if`, eg in C++
|
||||
# this could be improved with ocmpiler support to avoid the `if`, e.g. in C++
|
||||
# `&a[0]` is well defined even if a.size() == 0
|
||||
when T is string | seq:
|
||||
if a.len == 0: nil else: cast[pointer](a[0].unsafeAddr)
|
||||
|
||||
@@ -966,7 +966,7 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||
of nkConstSection:
|
||||
# do not replace ``const c = 3`` with ``const 3 = 3``
|
||||
return transformConstSection(c, n)
|
||||
of nkTypeSection, nkTypeOfExpr:
|
||||
of nkTypeSection, nkTypeOfExpr, nkMixinStmt, nkBindStmt:
|
||||
# no need to transform type sections:
|
||||
return n
|
||||
of nkVarSection, nkLetSection:
|
||||
@@ -1001,6 +1001,11 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||
return n
|
||||
of nkExceptBranch:
|
||||
result = transformExceptBranch(c, n)
|
||||
of nkCheckedFieldExpr:
|
||||
result = transformSons(c, n)
|
||||
if result[0].kind != nkDotExpr:
|
||||
# simplfied beyond a dot expression --> simplify further.
|
||||
result = result[0]
|
||||
else:
|
||||
result = transformSons(c, n)
|
||||
when false:
|
||||
|
||||
@@ -211,6 +211,6 @@ proc stupidStmtListExpr*(n: PNode): bool =
|
||||
proc dontInlineConstant*(orig, cnst: PNode): bool {.inline.} =
|
||||
# symbols that expand to a complex constant (array, etc.) should not be
|
||||
# inlined, unless it's the empty array:
|
||||
result = orig.kind == nkSym and
|
||||
result = orig.kind != cnst.kind and
|
||||
cnst.kind in {nkCurly, nkPar, nkTupleConstr, nkBracket, nkObjConstr} and
|
||||
cnst.len > ord(cnst.kind == nkObjConstr)
|
||||
|
||||
@@ -52,7 +52,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||
result = nil
|
||||
if typ == nil: return nil
|
||||
if containsOrIncl(marker, typ.id): return nil
|
||||
var t = skipTypes(typ, abstractInst-{tyTypeDesc})
|
||||
var t = skipTypes(typ, abstractInst-{tyTypeDesc, tySink})
|
||||
case t.kind
|
||||
of tyVar, tyLent:
|
||||
if kind in {skProc, skFunc, skConst} and (views notin c.features):
|
||||
@@ -60,7 +60,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||
elif t.kind == tyLent and kind != skResult and (views notin c.features):
|
||||
result = t
|
||||
else:
|
||||
var t2 = skipTypes(t[0], abstractInst-{tyTypeDesc})
|
||||
var t2 = skipTypes(t[0], abstractInst-{tyTypeDesc, tySink})
|
||||
case t2.kind
|
||||
of tyVar, tyLent:
|
||||
if taHeap notin flags: result = t2 # ``var var`` is illegal on the heap
|
||||
@@ -70,6 +70,8 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||
of tyUncheckedArray:
|
||||
if kind != skParam and views notin c.features: result = t
|
||||
else: result = typeAllowedAux(marker, t2[0], kind, c, flags)
|
||||
of tySink:
|
||||
result = t
|
||||
else:
|
||||
if kind notin {skParam, skResult} and views notin c.features: result = t
|
||||
else: result = typeAllowedAux(marker, t2, kind, c, flags)
|
||||
@@ -125,12 +127,18 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||
result = t
|
||||
else:
|
||||
result = typeAllowedAux(marker, t[0], kind, c, flags+{taIsOpenArray})
|
||||
of tyVarargs, tySink:
|
||||
of tyVarargs:
|
||||
# you cannot nest openArrays/sinks/etc.
|
||||
if kind != skParam or taIsOpenArray in flags:
|
||||
result = t
|
||||
else:
|
||||
result = typeAllowedAux(marker, t[0], kind, c, flags+{taIsOpenArray})
|
||||
of tySink:
|
||||
# you cannot nest openArrays/sinks/etc.
|
||||
if kind != skParam or taIsOpenArray in flags or t[0].kind in {tySink, tyLent, tyVar}:
|
||||
result = t
|
||||
else:
|
||||
result = typeAllowedAux(marker, t[0], kind, c, flags)
|
||||
of tyUncheckedArray:
|
||||
if kind != skParam and taHeap notin flags:
|
||||
result = t
|
||||
|
||||
@@ -23,7 +23,7 @@ type
|
||||
preferTypeName,
|
||||
preferResolved, # fully resolved symbols
|
||||
preferMixed,
|
||||
# most useful, shows: symbol + resolved symbols if it differs, eg:
|
||||
# most useful, shows: symbol + resolved symbols if it differs, e.g.:
|
||||
# tuple[a: MyInt{int}, b: float]
|
||||
|
||||
proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
|
||||
@@ -73,7 +73,7 @@ const
|
||||
tyInferred, tySink, tyLent, tyOwned}
|
||||
# typedescX is used if we're sure tyTypeDesc should be included (or skipped)
|
||||
typedescPtrs* = abstractPtrs + {tyTypeDesc}
|
||||
typedescInst* = abstractInst + {tyTypeDesc, tyOwned}
|
||||
typedescInst* = abstractInst + {tyTypeDesc, tyOwned, tyUserTypeClass}
|
||||
|
||||
proc invalidGenericInst*(f: PType): bool =
|
||||
result = f.kind == tyGenericInst and lastSon(f) == nil
|
||||
@@ -365,13 +365,13 @@ proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool =
|
||||
if tfAcyclic in t.flags: return
|
||||
case t.kind
|
||||
of tyTuple, tyObject, tyRef, tySequence, tyArray, tyOpenArray, tyVarargs:
|
||||
if not containsOrIncl(marker, t.id):
|
||||
if t.id == startId:
|
||||
result = true
|
||||
elif not containsOrIncl(marker, t.id):
|
||||
for i in 0..<t.len:
|
||||
result = canFormAcycleAux(marker, t[i], startId)
|
||||
if result: return
|
||||
if t.n != nil: result = canFormAcycleNode(marker, t.n, startId)
|
||||
else:
|
||||
result = t.id == startId
|
||||
# Inheritance can introduce cyclic types, however this is not relevant
|
||||
# as the type that is passed to 'new' is statically known!
|
||||
# er but we use it also for the write barrier ...
|
||||
@@ -387,7 +387,8 @@ proc isFinal*(t: PType): bool =
|
||||
|
||||
proc canFormAcycle*(typ: PType): bool =
|
||||
var marker = initIntSet()
|
||||
result = canFormAcycleAux(marker, typ, typ.id)
|
||||
let t = skipTypes(typ, abstractInst+{tyOwned}-{tyTypeDesc})
|
||||
result = canFormAcycleAux(marker, t, t.id)
|
||||
|
||||
proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator,
|
||||
closure: RootRef): PType
|
||||
@@ -686,7 +687,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
if i < t.len - 1: result.add(", ")
|
||||
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: CallingConvToStr[t.callConv]
|
||||
var prag = if t.callConv == ccNimCall and tfExplicitCallConv notin t.flags: "" else: $t.callConv
|
||||
if tfNoSideEffect in t.flags:
|
||||
addSep(prag)
|
||||
prag.add("noSideEffect")
|
||||
@@ -733,8 +734,9 @@ proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||
if t.len > 0 and t[0] != nil:
|
||||
result = firstOrd(conf, t[0])
|
||||
else:
|
||||
assert(t.n[0].kind == nkSym)
|
||||
result = toInt128(t.n[0].sym.position)
|
||||
if t.n.len > 0:
|
||||
assert(t.n[0].kind == nkSym)
|
||||
result = toInt128(t.n[0].sym.position)
|
||||
of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tySink,
|
||||
tyStatic, tyInferred, tyUserTypeClasses, tyLent:
|
||||
result = firstOrd(conf, lastSon(t))
|
||||
@@ -790,8 +792,9 @@ proc lastOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||
of tyUInt64:
|
||||
result = toInt128(0xFFFFFFFFFFFFFFFF'u64)
|
||||
of tyEnum:
|
||||
assert(t.n[^1].kind == nkSym)
|
||||
result = toInt128(t.n[^1].sym.position)
|
||||
if t.n.len > 0:
|
||||
assert(t.n[^1].kind == nkSym)
|
||||
result = toInt128(t.n[^1].sym.position)
|
||||
of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tySink,
|
||||
tyStatic, tyInferred, tyUserTypeClasses, tyLent:
|
||||
result = lastOrd(conf, lastSon(t))
|
||||
|
||||
@@ -90,7 +90,7 @@ proc renderParamTypes(found: var seq[string], n: PNode) =
|
||||
## Recursive helper, adds to `found` any types, or keeps diving the AST.
|
||||
##
|
||||
## The normal `doc` generator doesn't include .typ information, so the
|
||||
## function won't render types for parameters with default values. The `doc2`
|
||||
## function won't render types for parameters with default values. The `doc`
|
||||
## generator does include the information.
|
||||
case n.kind
|
||||
of nkFormalParams:
|
||||
|
||||
@@ -45,6 +45,8 @@ proc `<`(a, b: AbstractTime): bool {.borrow.}
|
||||
proc inc(x: var AbstractTime; diff = 1) {.borrow.}
|
||||
proc dec(x: var AbstractTime; diff = 1) {.borrow.}
|
||||
|
||||
proc `$`(x: AbstractTime): string {.borrow.}
|
||||
|
||||
type
|
||||
SubgraphFlag = enum
|
||||
isMutated, # graph might be mutated
|
||||
@@ -55,6 +57,7 @@ type
|
||||
ownsData,
|
||||
preventCursor,
|
||||
isReassigned,
|
||||
isConditionallyReassigned,
|
||||
viewDoesMutate,
|
||||
viewBorrowsFromConst
|
||||
|
||||
@@ -96,6 +99,7 @@ type
|
||||
goals: set[Goal]
|
||||
unanalysableMutation: bool
|
||||
inAsgnSource, inConstructor, inNoSideEffectSection: int
|
||||
inConditional, inLoop: int
|
||||
owner: PSym
|
||||
config: ConfigRef
|
||||
|
||||
@@ -126,7 +130,7 @@ proc hasSideEffect*(c: var Partitions; info: var MutationInfo): bool =
|
||||
return true
|
||||
return false
|
||||
|
||||
template isConstParam(a): bool = a.kind == skParam and a.typ.kind != tyVar
|
||||
template isConstParam(a): bool = a.kind == skParam and a.typ.kind notin {tyVar, tySink}
|
||||
|
||||
proc variableId(c: Partitions; x: PSym): int =
|
||||
for i in 0 ..< c.s.len:
|
||||
@@ -397,6 +401,7 @@ proc allRoots(n: PNode; result: var seq[PSym]; followDotExpr = true) =
|
||||
proc destMightOwn(c: var Partitions; dest: var VarIndex; n: PNode) =
|
||||
## Analyse if 'n' is an expression that owns the data, if so mark 'dest'
|
||||
## with 'ownsData'.
|
||||
if n.typ == nil: return
|
||||
case n.kind
|
||||
of nkEmpty, nkCharLit..nkNilLit:
|
||||
# primitive literals including the empty are harmless:
|
||||
@@ -545,6 +550,9 @@ proc borrowingCall(c: var Partitions; destType: PType; n: PNode; i: int) =
|
||||
localError(c.config, n[i].info, "cannot determine the target of the borrow")
|
||||
|
||||
proc borrowingAsgn(c: var Partitions; dest, src: PNode) =
|
||||
proc mutableParameter(n: PNode): bool {.inline.} =
|
||||
result = n.kind == nkSym and n.sym.kind == skParam and n.sym.typ.kind == tyVar
|
||||
|
||||
if dest.kind == nkSym:
|
||||
if directViewType(dest.typ) != noView:
|
||||
borrowFrom(c, dest.sym, src)
|
||||
@@ -559,7 +567,11 @@ proc borrowingAsgn(c: var Partitions; dest, src: PNode) =
|
||||
if vid >= 0:
|
||||
c.s[vid].flags.incl viewDoesMutate
|
||||
of immutableView:
|
||||
localError(c.config, dest.info, "attempt to mutate a borrowed location from an immutable view")
|
||||
if dest.kind == nkBracketExpr and dest[0].kind == nkHiddenDeref and
|
||||
mutableParameter(dest[0][0]):
|
||||
discard "remains a mutable location anyhow"
|
||||
else:
|
||||
localError(c.config, dest.info, "attempt to mutate a borrowed location from an immutable view")
|
||||
of noView: discard "nothing to do"
|
||||
|
||||
proc containsPointer(t: PType): bool =
|
||||
@@ -584,33 +596,34 @@ proc deps(c: var Partitions; dest, src: PNode) =
|
||||
for s in sources:
|
||||
connect(c, t, s, dest.info)
|
||||
|
||||
if cursorInference in c.goals and src.kind != nkEmpty:
|
||||
if dest.kind == nkSym:
|
||||
let vid = variableId(c, dest.sym)
|
||||
if cursorInference in c.goals and src.kind != nkEmpty:
|
||||
let d = pathExpr(dest, c.owner)
|
||||
if d != nil and d.kind == nkSym:
|
||||
let vid = variableId(c, d.sym)
|
||||
if vid >= 0:
|
||||
destMightOwn(c, c.s[vid], src)
|
||||
for s in sources:
|
||||
if s == dest.sym:
|
||||
if s == d.sym:
|
||||
discard "assignments like: it = it.next are fine"
|
||||
elif {sfGlobal, sfThread} * s.flags != {} or hasDisabledAsgn(s.typ):
|
||||
# do not borrow from a global variable or from something with a
|
||||
# disabled assignment operator.
|
||||
c.s[vid].flags.incl preventCursor
|
||||
when explainCursors: echo "A not a cursor: ", dest.sym, " ", s
|
||||
when explainCursors: echo "A not a cursor: ", d.sym, " ", s
|
||||
else:
|
||||
let srcid = variableId(c, s)
|
||||
if srcid >= 0:
|
||||
if s.kind notin {skResult, skParam} and (
|
||||
c.s[srcid].aliveEnd < c.s[vid].aliveEnd):
|
||||
# you cannot borrow from a local that lives shorter than 'vid':
|
||||
when explainCursors: echo "B not a cursor ", dest.sym, " ", c.s[srcid].aliveEnd, " ", c.s[vid].aliveEnd
|
||||
when explainCursors: echo "B not a cursor ", d.sym, " ", c.s[srcid].aliveEnd, " ", c.s[vid].aliveEnd
|
||||
c.s[vid].flags.incl preventCursor
|
||||
elif {isReassigned, preventCursor} * c.s[srcid].flags != {}:
|
||||
# you cannot borrow from something that is re-assigned:
|
||||
when explainCursors: echo "C not a cursor ", dest.sym, " ", c.s[srcid].flags, " reassignedTo ", c.s[srcid].reassignedTo
|
||||
when explainCursors: echo "C not a cursor ", d.sym, " ", c.s[srcid].flags, " reassignedTo ", c.s[srcid].reassignedTo
|
||||
c.s[vid].flags.incl preventCursor
|
||||
elif c.s[srcid].reassignedTo != 0 and c.s[srcid].reassignedTo != dest.sym.id:
|
||||
when explainCursors: echo "D not a cursor ", dest.sym, " reassignedTo ", c.s[srcid].reassignedTo
|
||||
elif c.s[srcid].reassignedTo != 0 and c.s[srcid].reassignedTo != d.sym.id:
|
||||
when explainCursors: echo "D not a cursor ", d.sym, " reassignedTo ", c.s[srcid].reassignedTo
|
||||
c.s[vid].flags.incl preventCursor
|
||||
|
||||
const
|
||||
@@ -618,7 +631,8 @@ const
|
||||
nkTypeSection, nkProcDef, nkConverterDef,
|
||||
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
|
||||
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState, nkTypeOfExpr}
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
|
||||
nkTypeOfExpr, nkMixinStmt, nkBindStmt}
|
||||
|
||||
proc potentialMutationViaArg(c: var Partitions; n: PNode; callee: PType) =
|
||||
if constParameters in c.goals and tfNoSideEffect in callee.flags:
|
||||
@@ -737,6 +751,13 @@ proc traverse(c: var Partitions; n: PNode) =
|
||||
else:
|
||||
for child in n: traverse(c, child)
|
||||
|
||||
proc markAsReassigned(c: var Partitions; vid: int) {.inline.} =
|
||||
c.s[vid].flags.incl isReassigned
|
||||
if c.inConditional > 0 and c.inLoop > 0:
|
||||
# bug #17033: live ranges with loops and conditionals are too
|
||||
# complex for our current analysis, so we prevent the cursorfication.
|
||||
c.s[vid].flags.incl isConditionallyReassigned
|
||||
|
||||
proc computeLiveRanges(c: var Partitions; n: PNode) =
|
||||
# first pass: Compute live ranges for locals.
|
||||
# **Watch out!** We must traverse the tree like 'traverse' does
|
||||
@@ -766,7 +787,7 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
|
||||
if n[1].kind == nkSym and (c.s[vid].reassignedTo == 0 or c.s[vid].reassignedTo == n[1].sym.id):
|
||||
c.s[vid].reassignedTo = n[1].sym.id
|
||||
else:
|
||||
c.s[vid].flags.incl isReassigned
|
||||
markAsReassigned(c, vid)
|
||||
|
||||
of nkSym:
|
||||
dec c.abstractTime
|
||||
@@ -793,7 +814,7 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
|
||||
if not paramType.isCompileTimeOnly and paramType.kind == tyVar:
|
||||
let vid = variableId(c, it.sym)
|
||||
if vid >= 0:
|
||||
c.s[vid].flags.incl isReassigned
|
||||
markAsReassigned(c, vid)
|
||||
|
||||
of nkAddr, nkHiddenAddr:
|
||||
computeLiveRanges(c, n[0])
|
||||
@@ -811,7 +832,13 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
|
||||
# while cond:
|
||||
# mutate(graph)
|
||||
# connect(graph, cursorVar)
|
||||
inc c.inLoop
|
||||
for child in n: computeLiveRanges(c, child)
|
||||
inc c.inLoop
|
||||
of nkElifBranch, nkElifExpr, nkElse, nkOfBranch:
|
||||
inc c.inConditional
|
||||
for child in n: computeLiveRanges(c, child)
|
||||
dec c.inConditional
|
||||
else:
|
||||
for child in n: computeLiveRanges(c, child)
|
||||
|
||||
@@ -885,7 +912,8 @@ proc computeCursors*(s: PSym; n: PNode; config: ConfigRef) =
|
||||
var par = computeGraphPartitions(s, n, config, {cursorInference})
|
||||
for i in 0 ..< par.s.len:
|
||||
let v = addr(par.s[i])
|
||||
if v.flags * {ownsData, preventCursor} == {} and v.sym.kind notin {skParam, skResult} and
|
||||
if v.flags * {ownsData, preventCursor, isConditionallyReassigned} == {} and
|
||||
v.sym.kind notin {skParam, skResult} and
|
||||
v.sym.flags * {sfThread, sfGlobal} == {} and hasDestructor(v.sym.typ) and
|
||||
v.sym.typ.skipTypes({tyGenericInst, tyAlias}).kind != tyOwned:
|
||||
let rid = root(par, i)
|
||||
@@ -893,4 +921,4 @@ proc computeCursors*(s: PSym; n: PNode; config: ConfigRef) =
|
||||
discard "cannot cursor into a graph that is mutated"
|
||||
else:
|
||||
v.sym.flags.incl sfCursor
|
||||
#echo "this is now a cursor ", v.sym, " ", par.s[rid].flags, " ", config $ v.sym.info
|
||||
#echo "this is now a cursor ", v.sym, " ", par.s[rid].flags, " ", config $ v.sym.info
|
||||
@@ -765,7 +765,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
if regs[rb].node.kind == nkRefTy:
|
||||
regs[ra].node = regs[rb].node[0]
|
||||
elif not maybeHandlePtr(regs[rb].node, regs[ra], false):
|
||||
## eg: typ.kind = tyObject
|
||||
## e.g.: typ.kind = tyObject
|
||||
ensureKind(rkNode)
|
||||
regs[ra].node = regs[rb].node
|
||||
else:
|
||||
@@ -994,8 +994,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
let nb = regs[rb].node
|
||||
let nc = regs[rc].node
|
||||
if nb.kind != nc.kind: discard
|
||||
elif (nb == nc) or (nb.kind == nkNilLit): ret = true
|
||||
elif nb.kind == nkIntLit and nb.intVal == nc.intVal: # TODO: nkPtrLit
|
||||
elif (nb == nc) or (nb.kind == nkNilLit): ret = true # intentional
|
||||
elif (nb.kind in {nkSym, nkTupleConstr, nkClosure} and nb.typ.kind == tyProc) and sameConstant(nb, nc):
|
||||
ret = true
|
||||
# this also takes care of procvar's, represented as nkTupleConstr, e.g. (nil, nil)
|
||||
elif nb.kind == nkIntLit and nc.kind == nkIntLit and nb.intVal == nc.intVal: # TODO: nkPtrLit
|
||||
let tb = nb.getTyp
|
||||
let tc = nc.getTyp
|
||||
ret = tb.kind in PtrLikeKinds and tc.kind == tb.kind
|
||||
@@ -2078,6 +2081,7 @@ proc execute(c: PCtx, start: int): PNode =
|
||||
result = rawExecute(c, start, tos).regToNode
|
||||
|
||||
proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
|
||||
c.loopIterations = c.config.maxLoopIterationsVM
|
||||
if sym.kind in routineKinds:
|
||||
if sym.typ.len-1 != args.len:
|
||||
localError(c.config, sym.info,
|
||||
|
||||
@@ -265,7 +265,7 @@ type
|
||||
templInstCounter*: ref int # gives every template instantiation a unique ID, needed here for getAst
|
||||
|
||||
PStackFrame* = ref TStackFrame
|
||||
TStackFrame* = object
|
||||
TStackFrame* {.acyclic.} = object
|
||||
prc*: PSym # current prc; proc that is evaluated
|
||||
slots*: seq[TFullReg] # parameters passed to the proc + locals;
|
||||
# parameters come first
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# types that use the 'node' field; the reason is that slots are
|
||||
# re-used in a register based VM. Example:
|
||||
#
|
||||
#..code-block:: nim
|
||||
#.. code-block:: nim
|
||||
# let s = a & b # no matter what, create fresh node
|
||||
# s = a & b # no matter what, keep the node
|
||||
#
|
||||
@@ -99,7 +99,7 @@ proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
|
||||
inc i
|
||||
else:
|
||||
result.addf("\t$#\tr$#, $#", opc.toStr, x.regA, x.regBx-wordExcess)
|
||||
result.add("\t#")
|
||||
result.add("\t# ")
|
||||
result.add(debugInfo(c, c.debug[i]))
|
||||
result.add("\n")
|
||||
inc i
|
||||
@@ -247,6 +247,8 @@ proc freeTemp(c: PCtx; r: TRegister) =
|
||||
proc getTempRange(cc: PCtx; n: int; kind: TSlotKind): TRegister =
|
||||
# if register pressure is high, we re-use more aggressively:
|
||||
let c = cc.prc
|
||||
# we could also customize via the following (with proper caching in ConfigRef):
|
||||
# let highRegisterPressure = cc.config.getConfigVar("vm.highRegisterPressure", "40").parseInt
|
||||
if c.maxSlots >= HighRegisterPressure or c.maxSlots+n >= high(TRegister):
|
||||
for i in 0..c.maxSlots-n:
|
||||
if not c.slots[i].inUse:
|
||||
@@ -586,9 +588,6 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
|
||||
# varargs need 'opcSetType' for the FFI support:
|
||||
let fntyp = skipTypes(n[0].typ, abstractInst)
|
||||
for i in 0..<n.len:
|
||||
#if i > 0 and i < fntyp.len:
|
||||
# let paramType = fntyp.n[i]
|
||||
# if paramType.typ.isCompileTimeOnly: continue
|
||||
var r: TRegister = x+i
|
||||
c.gen(n[i], r, {gfIsParam})
|
||||
if i >= fntyp.len:
|
||||
@@ -684,6 +683,8 @@ proc genNewSeq(c: PCtx; n: PNode) =
|
||||
|
||||
proc genNewSeqOfCap(c: PCtx; n: PNode; dest: var TDest) =
|
||||
let t = n.typ
|
||||
if dest < 0:
|
||||
dest = c.getTemp(n.typ)
|
||||
let tmp = c.getTemp(n[1].typ)
|
||||
c.gABx(n, opcLdNull, dest, c.genType(t))
|
||||
c.gABx(n, opcLdImmInt, tmp, 0)
|
||||
@@ -900,6 +901,11 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
|
||||
c.gABx(n, opcSetType, dest, c.genType(dst))
|
||||
c.gABC(n, opcCastIntToPtr, dest, tmp)
|
||||
c.freeTemp(tmp)
|
||||
elif src.kind == tyNil and dst.kind in NilableTypes:
|
||||
# supports casting nil literals to NilableTypes in VM
|
||||
# see #16024
|
||||
if dest < 0: dest = c.getTemp(n[0].typ)
|
||||
genLit(c, n[1], dest)
|
||||
else:
|
||||
# todo: support cast from tyInt to tyRef
|
||||
globalError(c.config, n.info, "VM does not support 'cast' from " & $src.kind & " to " & $dst.kind)
|
||||
@@ -997,7 +1003,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
c.genNarrow(n[1], d)
|
||||
c.genAsgnPatch(n[1], d)
|
||||
c.freeTemp(d)
|
||||
of mOrd, mChr, mArrToSeq, mUnown, mIsolate: c.gen(n[1], dest)
|
||||
of mOrd, mChr, mArrToSeq, mUnown: c.gen(n[1], dest)
|
||||
of mIsolate:
|
||||
genCall(c, n, dest)
|
||||
of mNew, mNewFinalize:
|
||||
unused(c, n, dest)
|
||||
c.genNew(n)
|
||||
@@ -1121,7 +1129,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
c.freeTemp(d)
|
||||
of mSwap:
|
||||
unused(c, n, dest)
|
||||
c.gen(lowerSwap(c.graph, n, if c.prc == nil: c.module else: c.prc.sym))
|
||||
c.gen(lowerSwap(c.graph, n, if c.prc == nil or c.prc.sym == nil: c.module else: c.prc.sym))
|
||||
of mIsNil: genUnaryABC(c, n, dest, opcIsNil)
|
||||
of mParseBiggestFloat:
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
@@ -1511,14 +1519,14 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||
let tmp = c.genx(ri)
|
||||
c.preventFalseAlias(le[0], opcWrObj, objR, idx, tmp)
|
||||
c.freeTemp(tmp)
|
||||
c.freeTemp(idx)
|
||||
# c.freeTemp(idx) # BUGFIX, see nkDotExpr
|
||||
c.freeTemp(objR)
|
||||
of nkDotExpr:
|
||||
let dest = c.genx(le[0], {gfNode})
|
||||
let idx = genField(c, le[1])
|
||||
let tmp = c.genx(ri)
|
||||
c.preventFalseAlias(le, opcWrObj, dest, idx, tmp)
|
||||
c.freeTemp(idx)
|
||||
# c.freeTemp(idx) # BUGFIX: idx is an immediate (field position), not a register
|
||||
c.freeTemp(tmp)
|
||||
c.freeTemp(dest)
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
@@ -1926,33 +1934,26 @@ proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
|
||||
proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
c.gABx(n, opcLdNull, dest, c.genType(n.typ))
|
||||
# XXX x = (x.old, 22) produces wrong code ... stupid self assignments
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
if it.kind == nkExprColonExpr:
|
||||
let idx = genField(c, it[0])
|
||||
let tmp = c.genx(it[1])
|
||||
c.preventFalseAlias(it[1], opcWrObj,
|
||||
dest, idx, tmp)
|
||||
c.freeTemp(tmp)
|
||||
else:
|
||||
let tmp = c.genx(it)
|
||||
c.preventFalseAlias(it, opcWrObj, dest, i.TRegister, tmp)
|
||||
c.freeTemp(tmp)
|
||||
if n.typ.kind != tyTypeDesc:
|
||||
c.gABx(n, opcLdNull, dest, c.genType(n.typ))
|
||||
# XXX x = (x.old, 22) produces wrong code ... stupid self assignments
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
if it.kind == nkExprColonExpr:
|
||||
let idx = genField(c, it[0])
|
||||
let tmp = c.genx(it[1])
|
||||
c.preventFalseAlias(it[1], opcWrObj,
|
||||
dest, idx, tmp)
|
||||
c.freeTemp(tmp)
|
||||
else:
|
||||
let tmp = c.genx(it)
|
||||
c.preventFalseAlias(it, opcWrObj, dest, i.TRegister, tmp)
|
||||
c.freeTemp(tmp)
|
||||
|
||||
proc genProc*(c: PCtx; s: PSym): int
|
||||
|
||||
proc matches(s: PSym; x: string): bool =
|
||||
let y = x.split('.')
|
||||
var s = s
|
||||
for i in 1..y.len:
|
||||
if s == nil or (y[^i].cmpIgnoreStyle(s.name.s) != 0 and y[^i] != "*"):
|
||||
return false
|
||||
s = s.owner
|
||||
result = true
|
||||
|
||||
proc matches(s: PSym; y: varargs[string]): bool =
|
||||
var s = s
|
||||
for i in 1..y.len:
|
||||
if s == nil or (y[^i].cmpIgnoreStyle(s.name.s) != 0 and y[^i] != "*"):
|
||||
@@ -1980,6 +1981,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
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:
|
||||
globalError(c.config, n.info, "Closure iterators are not supported by VM!")
|
||||
if procIsCallback(c, s): discard
|
||||
elif importcCond(s): c.importcSym(n.info, s)
|
||||
genLit(c, n, dest)
|
||||
@@ -2013,11 +2016,11 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
elif s.kind == skMethod:
|
||||
localError(c.config, n.info, "cannot call method " & s.name.s &
|
||||
" at compile time")
|
||||
elif matches(s, "stdlib", "marshal", "to"):
|
||||
elif matches(s, "stdlib.marshal.to"):
|
||||
# XXX marshal load&store should not be opcodes, but use the
|
||||
# general callback mechanisms.
|
||||
genMarshalLoad(c, n, dest)
|
||||
elif matches(s, "stdlib", "marshal", "$$"):
|
||||
elif matches(s, "stdlib.marshal.$$"):
|
||||
genMarshalStore(c, n, dest)
|
||||
else:
|
||||
genCall(c, n, dest)
|
||||
@@ -2100,7 +2103,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
else:
|
||||
dest = tmp0
|
||||
of nkEmpty, nkCommentStmt, nkTypeSection, nkConstSection, nkPragma,
|
||||
nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt:
|
||||
nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt,
|
||||
nkMixinStmt, nkBindStmt:
|
||||
unused(c, n, dest)
|
||||
of nkStringToCString, nkCStringToString:
|
||||
gen(c, n[0], dest)
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
#import vmdeps, vm
|
||||
from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
|
||||
arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc,
|
||||
floor, ceil, `mod`
|
||||
floor, ceil, `mod`, cbrt, arcsinh, arccosh, arctanh, erf, erfc, gamma,
|
||||
lgamma
|
||||
|
||||
from os import getEnv, existsEnv, dirExists, fileExists, putEnv, walkDir, getAppFilename
|
||||
from md5 import getMD5
|
||||
@@ -147,6 +148,7 @@ proc registerAdditionalOps*(c: PCtx) =
|
||||
setResult a, c.config.projectPath.string
|
||||
|
||||
wrap1f_math(sqrt)
|
||||
wrap1f_math(cbrt)
|
||||
wrap1f_math(ln)
|
||||
wrap1f_math(log10)
|
||||
wrap1f_math(log2)
|
||||
@@ -155,6 +157,9 @@ proc registerAdditionalOps*(c: PCtx) =
|
||||
wrap1f_math(arccos)
|
||||
wrap1f_math(arcsin)
|
||||
wrap1f_math(arctan)
|
||||
wrap1f_math(arcsinh)
|
||||
wrap1f_math(arccosh)
|
||||
wrap1f_math(arctanh)
|
||||
wrap2f_math(arctan2)
|
||||
wrap1f_math(cos)
|
||||
wrap1f_math(cosh)
|
||||
@@ -167,6 +172,10 @@ proc registerAdditionalOps*(c: PCtx) =
|
||||
wrap1f_math(trunc)
|
||||
wrap1f_math(floor)
|
||||
wrap1f_math(ceil)
|
||||
wrap1f_math(erf)
|
||||
wrap1f_math(erfc)
|
||||
wrap1f_math(gamma)
|
||||
wrap1f_math(lgamma)
|
||||
|
||||
wrap1s(getMD5, md5op)
|
||||
|
||||
|
||||
@@ -15,78 +15,99 @@
|
||||
|
||||
from strutils import cmpIgnoreStyle
|
||||
|
||||
# Keywords must be kept sorted and within a range
|
||||
|
||||
type
|
||||
TSpecialWord* = enum
|
||||
wInvalid,
|
||||
wInvalid = "",
|
||||
wAddr = "addr", wAnd = "and", wAs = "as", wAsm = "asm",
|
||||
wBind = "bind", wBlock = "block", wBreak = "break", wCase = "case", wCast = "cast",
|
||||
wConcept = "concept", wConst = "const", wContinue = "continue", wConverter = "converter",
|
||||
wDefer = "defer", wDiscard = "discard", wDistinct = "distinct", wDiv = "div", wDo = "do",
|
||||
wElif = "elif", wElse = "else", wEnd = "end", wEnum = "enum", wExcept = "except",
|
||||
wExport = "export", wFinally = "finally", wFor = "for", wFrom = "from", wFunc = "func",
|
||||
wIf = "if", wImport = "import", wIn = "in", wInclude = "include", wInterface = "interface",
|
||||
wIs = "is", wIsnot = "isnot", wIterator = "iterator", wLet = "let", wMacro = "macro",
|
||||
wMethod = "method", wMixin = "mixin", wMod = "mod", wNil = "nil", wNot = "not", wNotin = "notin",
|
||||
wObject = "object", wOf = "of", wOr = "or", wOut = "out", wProc = "proc", wPtr = "ptr",
|
||||
wRaise = "raise", wRef = "ref", wReturn = "return", wShl = "shl", wShr = "shr", wStatic = "static",
|
||||
wTemplate = "template", wTry = "try", wTuple = "tuple", wType = "type", wUsing = "using",
|
||||
wVar = "var", wWhen = "when", wWhile = "while", wXor = "xor", wYield = "yield",
|
||||
|
||||
wAddr, wAnd, wAs, wAsm,
|
||||
wBind, wBlock, wBreak, wCase, wCast, wConcept, wConst,
|
||||
wContinue, wConverter, wDefer, wDiscard, wDistinct, wDiv, wDo,
|
||||
wElif, wElse, wEnd, wEnum, wExcept, wExport,
|
||||
wFinally, wFor, wFrom, wFunc, wIf, wImport, wIn,
|
||||
wInclude, wInterface, wIs, wIsnot, wIterator, wLet,
|
||||
wMacro, wMethod, wMixin, wMod, wNil,
|
||||
wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn,
|
||||
wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar,
|
||||
wWhen, wWhile, wXor, wYield,
|
||||
wColon = ":", wColonColon = "::", wEquals = "=", wDot = ".", wDotDot = "..",
|
||||
wStar = "*", wMinus = "-",
|
||||
wMagic = "magic", wThread = "thread", wFinal = "final", wProfiler = "profiler",
|
||||
wMemTracker = "memtracker", wObjChecks = "objchecks",
|
||||
wIntDefine = "intdefine", wStrDefine = "strdefine", wBoolDefine = "booldefine",
|
||||
wCursor = "cursor", wNoalias = "noalias",
|
||||
|
||||
wColon, wColonColon, wEquals, wDot, wDotDot,
|
||||
wStar, wMinus,
|
||||
wMagic, wThread, wFinal, wProfiler, wMemTracker, wObjChecks,
|
||||
wIntDefine, wStrDefine, wBoolDefine, wCursor, wNoalias,
|
||||
wImmediate = "immediate", wConstructor = "constructor", wDestructor = "destructor",
|
||||
wDelegator = "delegator", wOverride = "override", wImportCpp = "importcpp",
|
||||
wImportObjC = "importobjc", wImportCompilerProc = "importcompilerproc",
|
||||
wImportc = "importc", wImportJs = "importjs", wExportc = "exportc", wExportCpp = "exportcpp",
|
||||
wExportNims = "exportnims",
|
||||
wIncompleteStruct = "incompleteStruct", # deprecated
|
||||
wCompleteStruct = "completeStruct", wRequiresInit = "requiresInit", wAlign = "align",
|
||||
wNodecl = "nodecl", wPure = "pure", wSideEffect = "sideEffect", wHeader = "header",
|
||||
wNoSideEffect = "noSideEffect", wGcSafe = "gcsafe", wNoreturn = "noreturn",
|
||||
wNosinks = "nosinks", wMerge = "merge", wLib = "lib", wDynlib = "dynlib",
|
||||
wCompilerProc = "compilerproc", wCore = "core", wProcVar = "procvar",
|
||||
wBase = "base", wUsed = "used", wFatal = "fatal", wError = "error", wWarning = "warning",
|
||||
wHint = "hint", wWarningAsError = "warningAsError", wLine = "line", wPush = "push",
|
||||
wPop = "pop", wDefine = "define", wUndef = "undef", wLineDir = "lineDir",
|
||||
wStackTrace = "stackTrace", wLineTrace = "lineTrace", wLink = "link", wCompile = "compile",
|
||||
wLinksys = "linksys", wDeprecated = "deprecated", wVarargs = "varargs", wCallconv = "callconv",
|
||||
wDebugger = "debugger", wNimcall = "nimcall", wStdcall = "stdcall", wCdecl = "cdecl",
|
||||
wSafecall = "safecall", wSyscall = "syscall", wInline = "inline", wNoInline = "noinline",
|
||||
wFastcall = "fastcall", wThiscall = "thiscall", wClosure = "closure", wNoconv = "noconv",
|
||||
wOn = "on", wOff = "off", wChecks = "checks", wRangeChecks = "rangeChecks",
|
||||
wBoundChecks = "boundChecks", wOverflowChecks = "overflowChecks", wNilChecks = "nilChecks",
|
||||
wFloatChecks = "floatChecks", wNanChecks = "nanChecks", wInfChecks = "infChecks",
|
||||
wStyleChecks = "styleChecks", wStaticBoundchecks = "staticBoundChecks",
|
||||
wNonReloadable = "nonReloadable", wExecuteOnReload = "executeOnReload",
|
||||
|
||||
wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
|
||||
wImportCpp, wImportObjC,
|
||||
wImportCompilerProc,
|
||||
wImportc, wImportJs, wExportc, wExportCpp, wExportNims,
|
||||
wIncompleteStruct, # deprecated
|
||||
wCompleteStruct,
|
||||
wRequiresInit,
|
||||
wAlign, wNodecl, wPure, wSideEffect, wHeader,
|
||||
wNoSideEffect, wGcSafe, wNoreturn, wNosinks, wMerge, wLib, wDynlib,
|
||||
wCompilerProc, wCore, wProcVar, wBase, wUsed,
|
||||
wFatal, wError, wWarning, wHint, wWarningAsError, wLine, wPush, wPop, wDefine, wUndef,
|
||||
wLineDir, wStackTrace, wLineTrace, wLink, wCompile,
|
||||
wLinksys, wDeprecated, wVarargs, wCallconv, wDebugger,
|
||||
wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline,
|
||||
wFastcall, wThiscall, wClosure, wNoconv, wOn, wOff, wChecks, wRangeChecks,
|
||||
wBoundChecks, wOverflowChecks, wNilChecks,
|
||||
wFloatChecks, wNanChecks, wInfChecks, wStyleChecks, wStaticBoundchecks,
|
||||
wNonReloadable, wExecuteOnReload,
|
||||
wAssertions, wPatterns, wTrMacros, wSinkInference, wWarnings,
|
||||
wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
|
||||
wRequires, wEnsures, wInvariant, wAssume, wAssert,
|
||||
wDeadCodeElimUnused, # deprecated, dead code elim always happens
|
||||
wSafecode, wPackage, wNoForward, wReorder, wNoRewrite, wNoDestroy,
|
||||
wPragma,
|
||||
wCompileTime, wNoInit,
|
||||
wPassc, wPassl, wLocalPassc, wBorrow, wDiscardable,
|
||||
wFieldChecks,
|
||||
wSubsChar, wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto,
|
||||
wInjectStmt, wExperimental,
|
||||
wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
|
||||
wAsmNoStackFrame,
|
||||
wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks,
|
||||
wPartial, wExplain, wLiftLocals,
|
||||
wAssertions = "assertions", wPatterns = "patterns", wTrMacros = "trmacros",
|
||||
wSinkInference = "sinkInference", wWarnings = "warnings",
|
||||
wHints = "hints", wOptimization = "optimization", wRaises = "raises",
|
||||
wWrites = "writes", wReads = "reads", wSize = "size", wEffects = "effects", wTags = "tags",
|
||||
wRequires = "requires", wEnsures = "ensures", wInvariant = "invariant",
|
||||
wAssume = "assume", wAssert = "assert",
|
||||
wDeadCodeElimUnused = "deadCodeElim", # deprecated, dead code elim always happens
|
||||
wSafecode = "safecode", wPackage = "package", wNoForward = "noforward", wReorder = "reorder",
|
||||
wNoRewrite = "norewrite", wNoDestroy = "nodestroy", wPragma = "pragma",
|
||||
wCompileTime = "compileTime", wNoInit = "noinit", wPassc = "passc", wPassl = "passl",
|
||||
wLocalPassc = "localPassC", wBorrow = "borrow", wDiscardable = "discardable",
|
||||
wFieldChecks = "fieldChecks", wSubsChar = "subschar", wAcyclic = "acyclic",
|
||||
wShallow = "shallow", wUnroll = "unroll", wLinearScanEnd = "linearScanEnd",
|
||||
wComputedGoto = "computedGoto", wInjectStmt = "injectStmt", wExperimental = "experimental",
|
||||
wWrite = "write", wGensym = "gensym", wInject = "inject", wDirty = "dirty",
|
||||
wInheritable = "inheritable", wThreadVar = "threadvar", wEmit = "emit",
|
||||
wAsmNoStackFrame = "asmNoStackFrame", wImplicitStatic = "implicitStatic",
|
||||
wGlobal = "global", wCodegenDecl = "codegenDecl", wUnchecked = "unchecked",
|
||||
wGuard = "guard", wLocks = "locks", wPartial = "partial", wExplain = "explain",
|
||||
wLiftLocals = "liftlocals",
|
||||
|
||||
wAuto, wBool, wCatch, wChar, wClass, wCompl
|
||||
wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
|
||||
wExplicit, wExtern, wFalse, wFloat, wFriend,
|
||||
wGoto, wInt, wLong, wMutable, wNamespace, wNew, wOperator,
|
||||
wPrivate, wProtected, wPublic, wRegister, wReinterpret_cast, wRestrict,
|
||||
wShort, wSigned, wSizeof, wStatic_cast, wStruct, wSwitch,
|
||||
wThis, wThrow, wTrue, wTypedef, wTypeid, wTypeof, wTypename,
|
||||
wUnion, wPacked, wUnsigned, wVirtual, wVoid, wVolatile, wWchar_t,
|
||||
wAuto = "auto", wBool = "bool", wCatch = "catch", wChar = "char",
|
||||
wClass = "class", wCompl = "compl", wConst_cast = "const_cast", wDefault = "default",
|
||||
wDelete = "delete", wDouble = "double", wDynamic_cast = "dynamic_cast",
|
||||
wExplicit = "explicit", wExtern = "extern", wFalse = "false", wFloat = "float",
|
||||
wFriend = "friend", wGoto = "goto", wInt = "int", wLong = "long", wMutable = "mutable",
|
||||
wNamespace = "namespace", wNew = "new", wOperator = "operator", wPrivate = "private",
|
||||
wProtected = "protected", wPublic = "public", wRegister = "register",
|
||||
wReinterpret_cast = "reinterpret_cast", wRestrict = "restrict", wShort = "short",
|
||||
wSigned = "signed", wSizeof = "sizeof", wStatic_cast = "static_cast", wStruct = "struct",
|
||||
wSwitch = "switch", wThis = "this", wThrow = "throw", wTrue = "true", wTypedef = "typedef",
|
||||
wTypeid = "typeid", wTypeof = "typeof", wTypename = "typename",
|
||||
wUnion = "union", wPacked = "packed", wUnsigned = "unsigned", wVirtual = "virtual",
|
||||
wVoid = "void", wVolatile = "volatile", wWchar_t = "wchar_t",
|
||||
|
||||
wAlignas, wAlignof, wConstexpr, wDecltype, wNullptr, wNoexcept,
|
||||
wThread_local, wStatic_assert, wChar16_t, wChar32_t,
|
||||
wAlignas = "alignas", wAlignof = "alignof", wConstexpr = "constexpr", wDecltype = "decltype",
|
||||
wNullptr = "nullptr", wNoexcept = "noexcept",
|
||||
wThread_local = "thread_local", wStatic_assert = "static_assert",
|
||||
wChar16_t = "char16_t", wChar32_t = "char32_t",
|
||||
|
||||
wStdIn, wStdOut, wStdErr,
|
||||
wStdIn = "stdin", wStdOut = "stdout", wStdErr = "stderr",
|
||||
|
||||
wInOut, wByCopy, wByRef, wOneWay,
|
||||
wBitsize
|
||||
wInOut = "inout", wByCopy = "bycopy", wByRef = "byref", wOneWay = "oneway",
|
||||
wBitsize = "bitsize"
|
||||
|
||||
TSpecialWords* = set[TSpecialWord]
|
||||
|
||||
@@ -104,82 +125,8 @@ const
|
||||
wAsm, wBreak, wCase, wConst, wContinue, wDo, wElse, wEnum, wExport,
|
||||
wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile, wUsing}
|
||||
|
||||
specialWords*: array[TSpecialWord, string] = ["",
|
||||
"addr", "and", "as", "asm",
|
||||
"bind", "block", "break", "case", "cast",
|
||||
"concept", "const", "continue", "converter",
|
||||
"defer", "discard", "distinct", "div", "do",
|
||||
"elif", "else", "end", "enum", "except", "export",
|
||||
"finally", "for", "from", "func", "if",
|
||||
"import", "in", "include", "interface", "is", "isnot", "iterator",
|
||||
"let",
|
||||
"macro", "method", "mixin", "mod", "nil", "not", "notin",
|
||||
"object", "of", "or",
|
||||
"out", "proc", "ptr", "raise", "ref", "return",
|
||||
"shl", "shr", "static",
|
||||
"template", "try", "tuple", "type", "using", "var",
|
||||
"when", "while", "xor",
|
||||
"yield",
|
||||
|
||||
":", "::", "=", ".", "..",
|
||||
"*", "-",
|
||||
"magic", "thread", "final", "profiler", "memtracker", "objchecks",
|
||||
"intdefine", "strdefine", "booldefine", "cursor", "noalias",
|
||||
|
||||
"immediate", "constructor", "destructor", "delegator", "override",
|
||||
"importcpp", "importobjc",
|
||||
"importCompilerProc", "importc", "importjs", "exportc", "exportcpp", "exportnims",
|
||||
"incompleteStruct",
|
||||
"completeStruct",
|
||||
"requiresInit", "align", "nodecl", "pure", "sideEffect",
|
||||
"header", "noSideEffect", "gcsafe", "noreturn", "nosinks", "merge", "lib", "dynlib",
|
||||
"compilerproc", "core", "procvar", "base", "used",
|
||||
"fatal", "error", "warning", "hint", "warningAsError", "line",
|
||||
"push", "pop", "define", "undef", "lineDir", "stackTrace", "lineTrace",
|
||||
"link", "compile", "linksys", "deprecated", "varargs",
|
||||
"callconv", "debugger", "nimcall", "stdcall",
|
||||
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "thiscall", "closure",
|
||||
"noconv", "on", "off", "checks", "rangeChecks", "boundChecks",
|
||||
"overflowChecks", "nilChecks",
|
||||
"floatChecks", "nanChecks", "infChecks", "styleChecks", "staticBoundChecks",
|
||||
"nonReloadable", "executeOnReload",
|
||||
|
||||
"assertions", "patterns", "trmacros", "sinkinference", "warnings", "hints",
|
||||
"optimization", "raises", "writes", "reads", "size", "effects", "tags",
|
||||
"requires", "ensures", "invariant", "assume", "assert",
|
||||
"deadCodeElim", # deprecated, dead code elim always happens
|
||||
"safecode", "package", "noforward", "reorder", "norewrite", "nodestroy",
|
||||
"pragma",
|
||||
"compileTime", "noinit",
|
||||
"passc", "passl", "localPassC", "borrow", "discardable", "fieldChecks",
|
||||
"subschar", "acyclic", "shallow", "unroll", "linearScanEnd",
|
||||
"computedGoto", "injectStmt", "experimental",
|
||||
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
|
||||
"asmNoStackFrame", "implicitStatic", "global", "codegenDecl", "unchecked",
|
||||
"guard", "locks", "partial", "explain", "liftLocals",
|
||||
|
||||
"auto", "bool", "catch", "char", "class", "compl",
|
||||
"const_cast", "default", "delete", "double",
|
||||
"dynamic_cast", "explicit", "extern", "false",
|
||||
"float", "friend", "goto", "int", "long", "mutable",
|
||||
"namespace", "new", "operator",
|
||||
"private", "protected", "public", "register", "reinterpret_cast", "restrict",
|
||||
"short", "signed", "sizeof", "static_cast", "struct", "switch",
|
||||
"this", "throw", "true", "typedef", "typeid", "typeof",
|
||||
"typename", "union", "packed", "unsigned", "virtual", "void", "volatile",
|
||||
"wchar_t",
|
||||
|
||||
"alignas", "alignof", "constexpr", "decltype", "nullptr", "noexcept",
|
||||
"thread_local", "static_assert", "char16_t", "char32_t",
|
||||
|
||||
"stdin", "stdout", "stderr",
|
||||
|
||||
"inout", "bycopy", "byref", "oneway",
|
||||
"bitsize"
|
||||
]
|
||||
|
||||
proc findStr*(a: openArray[string], s: string): int =
|
||||
for i in low(a)..high(a):
|
||||
if cmpIgnoreStyle(a[i], s) == 0:
|
||||
proc findStr*[T:enum](a: Slice[T], s: string, default: T): T =
|
||||
for i in a:
|
||||
if cmpIgnoreStyle($i, s) == 0:
|
||||
return i
|
||||
result = - 1
|
||||
result = default
|
||||
|
||||
@@ -52,6 +52,7 @@ path="$lib/pure"
|
||||
nimblepath="$home/.nimble/pkgs/"
|
||||
@end
|
||||
|
||||
# Syncronize with compiler/commands.specialDefine
|
||||
@if danger or quick:
|
||||
obj_checks:off
|
||||
field_checks:off
|
||||
@@ -69,6 +70,7 @@ path="$lib/pure"
|
||||
@end
|
||||
@end
|
||||
|
||||
# Syncronize with compiler/commands.specialDefine
|
||||
@if release or danger:
|
||||
stacktrace:off
|
||||
excessiveStackTrace:off
|
||||
|
||||
@@ -57,13 +57,13 @@ $seeSrc
|
||||
# See doc.item for available substitution variables.
|
||||
doc.item.toc = """
|
||||
<li><a class="reference" href="#$itemSymOrIDEnc"
|
||||
title="$header_plain">$name<span class="attachedType">$attype</span></a></li>
|
||||
title="$header_plain">$name</a></li>
|
||||
"""
|
||||
|
||||
# This is used for TOC items which are grouped by the same name (e.g. procs).
|
||||
doc.item.tocTable = """
|
||||
<li><a class="reference" href="#$itemSymOrIDEnc"
|
||||
title="$header_plain">$itemSymOrID<span class="attachedType">$attype</span></a></li>
|
||||
title="$header_plain">$itemSymOrID</a></li>
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ Advanced options:
|
||||
produce hints or errors for Nim identifiers that
|
||||
do not adhere to Nim's official style guide
|
||||
https://nim-lang.org/docs/nep1.html
|
||||
--styleCheck:usages only enforce consistent spellings of identifiers,
|
||||
do not enforce the style on declarations
|
||||
--showAllMismatches:on|off
|
||||
show all mismatching candidates in overloading
|
||||
resolution
|
||||
@@ -71,7 +73,7 @@ Advanced options:
|
||||
--clibdir:DIR modify the linker library search path
|
||||
--clib:LIBNAME link an additional C library
|
||||
(you should omit platform-specific extensions)
|
||||
--project document the whole project (doc2)
|
||||
--project document the whole project (doc)
|
||||
--docRoot:path `nim doc --docRoot:/foo --project --outdir:docs /foo/sub/main.nim`
|
||||
generates: docs/sub/main.html
|
||||
if path == @pkg, will use nimble file enclosing dir
|
||||
@@ -81,9 +83,9 @@ Advanced options:
|
||||
if these are nonexistent, will use project path
|
||||
-b, --backend:c|cpp|js|objc sets backend to use with commands like `nim doc` or `nim r`
|
||||
--docCmd:cmd if `cmd == skip`, skips runnableExamples
|
||||
else, runs runnableExamples with given options, eg:
|
||||
else, runs runnableExamples with given options, e.g.:
|
||||
`--docCmd:"-d:foo --threads:on"`
|
||||
--docSeeSrcUrl:url activate 'see source' for doc and doc2 commands
|
||||
--docSeeSrcUrl:url activate 'see source' for doc command
|
||||
(see doc.item.seesrc in config/nimdoc.cfg)
|
||||
--docInternal also generate documentation for non-exported symbols
|
||||
--lineDir:on|off generation of #line directive on|off
|
||||
|
||||
@@ -3,7 +3,7 @@ API naming design
|
||||
=================
|
||||
|
||||
The API is designed to be **easy to use** and consistent. Ease of use is
|
||||
measured by the number of calls to achieve a concrete high level action.
|
||||
measured by the number of calls to achieve a concrete high-level action.
|
||||
|
||||
|
||||
Naming scheme
|
||||
|
||||
@@ -15,16 +15,16 @@ Introduction
|
||||
The `Nim Compiler User Guide <nimc.html>`_ documents the typical
|
||||
compiler invocation, using the ``compile`` or ``c`` command to transform a
|
||||
``.nim`` file into one or more ``.c`` files which are then compiled with the
|
||||
platform's C compiler into a static binary. However there are other commands
|
||||
to compile to C++, Objective-C or JavaScript. This document tries to
|
||||
platform's C compiler into a static binary. However, there are other commands
|
||||
to compile to C++, Objective-C, or JavaScript. This document tries to
|
||||
concentrate in a single place all the backend and interfacing options.
|
||||
|
||||
The Nim compiler supports mainly two backend families: the C, C++ and
|
||||
Objective-C targets and the JavaScript target. `The C like targets
|
||||
<#backends-the-c-like-targets>`_ creates source files which can be compiled
|
||||
<#backends-the-c-like-targets>`_ creates source files that can be compiled
|
||||
into a library or a final executable. `The JavaScript target
|
||||
<#backends-the-javascript-target>`_ can generate a ``.js`` file which you
|
||||
reference from an HTML file or create a `standalone nodejs program
|
||||
reference from an HTML file or create a `standalone Node.js program
|
||||
<http://nodejs.org>`_.
|
||||
|
||||
On top of generating libraries or standalone applications, Nim offers
|
||||
@@ -48,7 +48,7 @@ The most significant difference between these commands is that if you look
|
||||
into the ``nimcache`` directory you will find ``.c``, ``.cpp`` or ``.m``
|
||||
files, other than that all of them will produce a native binary for your
|
||||
project. This allows you to take the generated code and place it directly
|
||||
into a project using any of these languages. Here are some typical command
|
||||
into a project using any of these languages. Here are some typical command-
|
||||
line invocations::
|
||||
|
||||
$ nim c hallo.nim
|
||||
@@ -56,8 +56,8 @@ line invocations::
|
||||
$ nim objc hallo.nim
|
||||
|
||||
The compiler commands select the target backend, but if needed you can
|
||||
`specify additional switches for cross compilation
|
||||
<nimc.html#cross-compilation>`_ to select the target CPU, operative system
|
||||
`specify additional switches for cross-compilation
|
||||
<nimc.html#crossminuscompilation>`_ to select the target CPU, operative system
|
||||
or compiler/linker commands.
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ available. This includes:
|
||||
* OS-specific operations
|
||||
* threading, coroutines
|
||||
* some modules of the standard library
|
||||
* proper 64 bit integer arithmetic
|
||||
* proper 64-bit integer arithmetic
|
||||
|
||||
To compensate, the standard library has modules `catered to the JS backend
|
||||
<lib.html#pure-libraries-modules-for-js-backend>`_
|
||||
@@ -119,7 +119,7 @@ pragmas to call methods from classes.
|
||||
|
||||
Whenever you use any of these pragmas you need to integrate native code into
|
||||
your final binary. In the case of JavaScript this is no problem at all, the
|
||||
same html file which hosts the generated JavaScript will likely provide other
|
||||
same HTML file which hosts the generated JavaScript will likely provide other
|
||||
JavaScript functions which you are importing with ``importc``.
|
||||
|
||||
However, for the C like targets you need to link external code either
|
||||
@@ -167,7 +167,7 @@ With these two files in place, you can run ``nim c -r calculator.nim`` and
|
||||
the Nim compiler will compile the ``logic.c`` file in addition to
|
||||
``calculator.nim`` and link both into an executable, which outputs ``10`` when
|
||||
run. Another way to link the C file statically and get the same effect would
|
||||
be remove the line with the ``compile`` pragma and run the following typical
|
||||
be to remove the line with the ``compile`` pragma and run the following typical
|
||||
Unix commands::
|
||||
|
||||
$ gcc -c logic.c
|
||||
@@ -211,7 +211,7 @@ calculator.nim`` and open ``host.html`` in a browser. If the browser supports
|
||||
javascript, you should see the value ``10`` in the browser's console. Use the
|
||||
`dom module <dom.html>`_ for specific DOM querying and modification procs
|
||||
or take a look at `karax <https://github.com/pragmagic/karax>`_ for how to
|
||||
develop browser based applications.
|
||||
develop browser-based applications.
|
||||
|
||||
|
||||
Backend code calling Nim
|
||||
@@ -220,7 +220,7 @@ Backend code calling Nim
|
||||
Backend code can interface with Nim code exposed through the `exportc
|
||||
pragma <manual.html#foreign-function-interface-exportc-pragma>`_. The
|
||||
``exportc`` pragma is the *generic* way of making Nim symbols available to
|
||||
the backends. By default the Nim compiler will mangle all the Nim symbols to
|
||||
the backends. By default, the Nim compiler will mangle all the Nim symbols to
|
||||
avoid any name collision, so the most significant thing the ``exportc`` pragma
|
||||
does is maintain the Nim symbol name, or if specified, use an alternative
|
||||
symbol for the backend in case the symbol rules don't match.
|
||||
@@ -233,7 +233,7 @@ the compiler will assume certain types for the return value and parameters
|
||||
which will likely make your program crash at runtime.
|
||||
|
||||
The Nim compiler can generate a C interface header through the ``--header``
|
||||
command line switch. The generated header will contain all the exported
|
||||
command-line switch. The generated header will contain all the exported
|
||||
symbols and the ``NimMain`` proc which you need to call before any other
|
||||
Nim code.
|
||||
|
||||
@@ -322,8 +322,8 @@ from the previous section):
|
||||
Compile the Nim code to JavaScript with ``nim js -o:fib.js fib.nim`` and
|
||||
open ``mhost.html`` in a browser. If the browser supports javascript, you
|
||||
should see an alert box displaying the text ``Fib for 9 is 34``. As mentioned
|
||||
earlier, JavaScript doesn't require an initialisation call to ``NimMain`` or
|
||||
similar function and you can call the exported Nim proc directly.
|
||||
earlier, JavaScript doesn't require an initialization call to ``NimMain`` or
|
||||
a similar function and you can call the exported Nim proc directly.
|
||||
|
||||
|
||||
Nimcache naming logic
|
||||
@@ -333,15 +333,15 @@ The `nimcache`:idx: directory is generated during compilation and will hold
|
||||
either temporary or final files depending on your backend target. The default
|
||||
name for the directory depends on the used backend and on your OS but you can
|
||||
use the ``--nimcache`` `compiler switch
|
||||
<nimc.html#compiler-usage-command-line-switches>`_ to change it.
|
||||
<nimc.html#compiler-usage-commandminusline-switches>`_ to change it.
|
||||
|
||||
|
||||
Memory management
|
||||
=================
|
||||
|
||||
In the previous sections the ``NimMain()`` function reared its head. Since
|
||||
In the previous sections, the ``NimMain()`` function reared its head. Since
|
||||
JavaScript already provides automatic memory management, you can freely pass
|
||||
objects between the two language without problems. In C and derivate languages
|
||||
objects between the two languages without problems. In C and derivate languages
|
||||
you need to be careful about what you do and how you share memory. The
|
||||
previous examples only dealt with simple scalar values, but passing a Nim
|
||||
string to C, or reading back a C string in Nim already requires you to be
|
||||
@@ -355,7 +355,7 @@ The manual mentions that `Nim strings are implicitly convertible to
|
||||
cstrings <manual.html#types-cstring-type>`_ which makes interaction usually
|
||||
painless. Most C functions accepting a Nim string converted to a
|
||||
``cstring`` will likely not need to keep this string around and by the time
|
||||
they return the string won't be needed any more. However, for the rare cases
|
||||
they return the string won't be needed anymore. However, for the rare cases
|
||||
where a Nim string has to be preserved and made available to the C backend
|
||||
as a ``cstring``, you will need to manually prevent the string data from being
|
||||
freed with `GC_ref <system.html#GC_ref,string>`_ and `GC_unref
|
||||
@@ -388,7 +388,7 @@ to hand a Nim reference to C code, you will need to use `GC_ref
|
||||
<system.html#GC_ref,ref.T>`_ to mark the reference as used, so it does not get
|
||||
freed. And for the C backend you will need to expose the `GC_unref
|
||||
<system.html#GC_unref,ref.T>`_ proc to clean up this memory when it is not
|
||||
required any more.
|
||||
required anymore.
|
||||
|
||||
Again, if you are wrapping a library which *mallocs* and *frees* data
|
||||
structures, you need to expose the appropriate *free* function to Nim so
|
||||
@@ -424,4 +424,3 @@ leaks by calling
|
||||
.. code-block:: nim
|
||||
|
||||
system.tearDownForeignThreadGc()
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
===========
|
||||
Code owners
|
||||
===========
|
||||
|
||||
|
||||
Subsystems and code owners
|
||||
--------------------------
|
||||
|
||||
*Note*: This list is incomplete, in doubt dom96 is responsible for the standard
|
||||
library, araq is responsible for the compiler.
|
||||
|
||||
|
||||
Compiler
|
||||
~~~~~~~~
|
||||
|
||||
=========================== ======================================================
|
||||
subsystem owner(s)
|
||||
=========================== ======================================================
|
||||
Parsing, Lexing araq
|
||||
Renderer cooldome, araq
|
||||
Order of passes cooldome
|
||||
Semantic Checking araq
|
||||
Virtual machine jangko, GULPF, araq
|
||||
Sempass2: effects tracking cooldome, araq
|
||||
type system, concepts zahary
|
||||
transf cooldome, araq
|
||||
semfold constant folding araq
|
||||
template instantiation zahary, araq
|
||||
term rewriting macros cooldome, araq
|
||||
closure iterators yglukhov, araq
|
||||
lambda lifting yglukhov, araq
|
||||
c, cpp codegen lemonboy, araq
|
||||
js codegen yglukhov, lemonboy
|
||||
alias analysis araq
|
||||
dfa, writetracking araq
|
||||
parallel, multithreading araq
|
||||
incremental araq
|
||||
sizeof computations krux02
|
||||
Exception handling cooldome, araq
|
||||
=========================== ======================================================
|
||||
|
||||
|
||||
|
||||
Standard library
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
====================== ======================================================
|
||||
subsystem owner(s)
|
||||
====================== ======================================================
|
||||
async dom96
|
||||
strutils araq
|
||||
sequtils dom96, araq
|
||||
times GULPF
|
||||
os dom96, araq
|
||||
re araq
|
||||
nre flaviu
|
||||
math, fenv krux02, cooldome
|
||||
io dom96
|
||||
garbage collector araq
|
||||
Go garbage collector stefantalpalaru
|
||||
coroutines Rokas Kupstys
|
||||
collections GULPF
|
||||
parseopt araq
|
||||
json dom96
|
||||
====================== ======================================================
|
||||
@@ -8,11 +8,8 @@ Contributing
|
||||
Contributing happens via "Pull requests" (PR) on github. Every PR needs to be
|
||||
reviewed before it can be merged and the Continuous Integration should be green.
|
||||
|
||||
The PR has to be approved (and is often merged too) by one "code owner", either
|
||||
by the code owner who is responsible for the subsystem the PR belongs to or by
|
||||
two core developers or by Araq.
|
||||
The PR has to be approved by two core developers or by Araq.
|
||||
|
||||
See `codeowners <codeowners.html>`_ for more details.
|
||||
|
||||
|
||||
Writing tests
|
||||
@@ -43,13 +40,13 @@ Stdlib
|
||||
------
|
||||
|
||||
Each stdlib module (anything under ``lib/``, e.g. ``lib/pure/os.nim``) should
|
||||
preferably have a corresponding separate test file, eg `tests/stdlib/tos.nim`.
|
||||
preferably have a corresponding separate test file, e.g. `tests/stdlib/tos.nim`.
|
||||
The old convention was to add a ``when isMainModule:`` block in the source file,
|
||||
which only gets executed when the tester is building the file.
|
||||
|
||||
Each test should be in a separate ``block:`` statement, such that
|
||||
each has its own scope. Use boolean conditions and ``doAssert`` for the
|
||||
testing by itself, don't rely on echo statements or similar; in particular avoid
|
||||
testing by itself, don't rely on echo statements or similar; in particular, avoid
|
||||
things like `echo "done"`.
|
||||
|
||||
Sample test:
|
||||
@@ -69,9 +66,9 @@ Sample test:
|
||||
# doAssert with `not` can now be done as follows:
|
||||
doAssert not (1 == 2)
|
||||
|
||||
Always refer to a github issue using the following exact syntax: `bug #1234` as shown
|
||||
Always refer to a GitHub issue using the following exact syntax: `bug #1234` as shown
|
||||
above, so that it's consistent and easier to search or for tooling. Some browser
|
||||
extensions (eg https://github.com/sindresorhus/refined-github) will even turn those
|
||||
extensions (e.g. https://github.com/sindresorhus/refined-github) will even turn those
|
||||
in clickable links when it works.
|
||||
|
||||
Rationale for using a separate test file instead of `when isMainModule:` block:
|
||||
@@ -100,7 +97,7 @@ Possible keys are:
|
||||
|
||||
For a full spec, see here: ``testament/specs.nim``
|
||||
|
||||
An example for a test:
|
||||
An example of a test:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
@@ -162,7 +159,7 @@ Comparing tests
|
||||
|
||||
Test failures can be grepped using ``Failure:``.
|
||||
|
||||
The tester can compare two test runs. First, you need to create the
|
||||
The tester can compare two test runs. First, you need to create a
|
||||
reference test. You'll also need to the commit id, because that's what
|
||||
the tester needs to know in order to compare the two.
|
||||
|
||||
@@ -344,7 +341,7 @@ which for which ``nim doc`` ignores ``-d:release``).
|
||||
|
||||
.. _delegate_printing:
|
||||
Delegate printing to caller: return ``string`` instead of calling ``echo``
|
||||
rationale: it's more flexible (e.g. allows caller to call custom printing,
|
||||
rationale: it's more flexible (e.g. allows the caller to call custom printing,
|
||||
including prepending location info, writing to log files, etc).
|
||||
|
||||
.. code-block:: nim
|
||||
@@ -364,7 +361,7 @@ unless stack allocation is needed (e.g. for efficiency).
|
||||
.. _use_doAssert_not_echo:
|
||||
Tests (including in testament) should always prefer assertions over ``echo``,
|
||||
except when that's not possible. It's more precise, easier for readers and
|
||||
maintaners to where expected values refer to. See for example
|
||||
maintainers to where expected values refer to. See for example
|
||||
https://github.com/nim-lang/Nim/pull/9335 and https://forum.nim-lang.org/t/4089
|
||||
|
||||
.. code-block:: nim
|
||||
@@ -386,7 +383,7 @@ General commit rules
|
||||
stable releases" and the tag ``[backport:$VERSION]`` for backporting to the
|
||||
given $VERSION.
|
||||
|
||||
2. If you introduce changes which affect backwards compatibility,
|
||||
2. If you introduce changes which affect backward compatibility,
|
||||
make breaking changes, or have PR which is tagged as ``[feature]``,
|
||||
the changes should be mentioned in `the changelog
|
||||
<https://github.com/nim-lang/Nim/blob/devel/changelog.md>`_.
|
||||
@@ -404,7 +401,7 @@ General commit rules
|
||||
4. Changes should not introduce any trailing whitespace.
|
||||
|
||||
Always check your changes for whitespace errors using ``git diff --check``
|
||||
or add following ``pre-commit`` hook:
|
||||
or add the following ``pre-commit`` hook:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
@@ -416,7 +413,7 @@ General commit rules
|
||||
|
||||
``Fixes #123; refs #124``
|
||||
|
||||
indicates that issue ``#123`` is completely fixed (github may automatically
|
||||
indicates that issue ``#123`` is completely fixed (GitHub may automatically
|
||||
close it when the PR is committed), wheres issue ``#124`` is referenced
|
||||
(e.g.: partially fixed) and won't close the issue when committed.
|
||||
|
||||
@@ -431,7 +428,7 @@ General commit rules
|
||||
|
||||
7. Do not mix pure formatting changes (e.g. whitespace changes, nimpretty) or
|
||||
automated changes (e.g. nimfix) with other code changes: these should be in
|
||||
separate commits (and the merge on github should not squash these into 1).
|
||||
separate commits (and the merge on GitHub should not squash these into 1).
|
||||
|
||||
|
||||
Continuous Integration (CI)
|
||||
@@ -444,21 +441,40 @@ Continuous Integration (CI)
|
||||
<https://www.appveyor.com/docs/how-to/filtering-commits/#skip-directive-in-commit-message>`_
|
||||
and `Travis <https://docs.travis-ci.com/user/customizing-the-build/#skipping-a-build>`_.
|
||||
|
||||
2. Consider enabling CI (travis and appveyor) in your own Nim fork, and
|
||||
2. Consider enabling CI (azure, GitHub actions and builds.sr.ht) in your own Nim fork, and
|
||||
waiting for CI to be green in that fork (fixing bugs as needed) before
|
||||
opening your PR in original Nim repo, so as to reduce CI congestion. Same
|
||||
opening your PR in the original Nim repo, so as to reduce CI congestion. Same
|
||||
applies for updates on a PR: you can test commits on a separate private
|
||||
branch before updating the main PR.
|
||||
|
||||
Debugging CI failures, flaky tests, etc
|
||||
---------------------------------------
|
||||
|
||||
1. First check the CI logs and search for `FAIL` to find why CI failed; if the
|
||||
failure seems related to your PR, try to fix the code instead of restarting CI.
|
||||
|
||||
2. If CI failure seems unrelated to your PR, it could be caused by a flaky test.
|
||||
File a bug for it if it isn't already reported. A PR push (or opening/closing PR)
|
||||
will re-trigger all CI jobs (even successful ones, which can be wasteful). Instead,
|
||||
follow these instructions to only restart the jobs that failed:
|
||||
|
||||
* Azure: if on your own fork, it's possible from inside azure console
|
||||
(e.g. `dev.azure.com/username/username/_build/results?buildId=1430&view=results`) via `rerun failed jobs` on top.
|
||||
If either on you own fork or in Nim repo, it's possible from inside GitHub UI
|
||||
under checks tab, see https://github.com/timotheecour/Nim/issues/211#issuecomment-629751569
|
||||
* GitHub actions: under "Checks" tab, click "Re-run jobs" in the right.
|
||||
* builds.sr.ht: create a sourcehut account so you can restart a PR job as illustrated
|
||||
|
||||
|
||||
Code reviews
|
||||
------------
|
||||
|
||||
1. Whenever possible, use github's new 'Suggested change' in code reviews, which
|
||||
1. Whenever possible, use GitHub's new 'Suggested change' in code reviews, which
|
||||
saves time explaining the change or applying it; see also
|
||||
https://forum.nim-lang.org/t/4317
|
||||
|
||||
2. When reviewing large diffs that may involve code moving around, github's interface
|
||||
doesn't help much as it doesn't highlight moves. Instead you can use something
|
||||
2. When reviewing large diffs that may involve code moving around, GitHub's interface
|
||||
doesn't help much as it doesn't highlight moves. Instead, you can use something
|
||||
like this, see visual results `here <https://github.com/nim-lang/Nim/pull/10431#issuecomment-456968196>`_:
|
||||
|
||||
.. code-block:: sh
|
||||
@@ -466,7 +482,7 @@ Code reviews
|
||||
git fetch origin pull/10431/head && git checkout FETCH_HEAD
|
||||
git diff --color-moved-ws=allow-indentation-change --color-moved=blocks HEAD^
|
||||
|
||||
3. In addition, you can view github-like diffs locally to identify what was changed
|
||||
3. In addition, you can view GitHub-like diffs locally to identify what was changed
|
||||
within a code block using `diff-highlight` or `diff-so-fancy`, e.g.:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
@@ -25,7 +25,7 @@ move semantics and destructors work in Nim.
|
||||
Motivating example
|
||||
==================
|
||||
|
||||
With the language mechanisms described here a custom seq could be
|
||||
With the language mechanisms described here, a custom seq could be
|
||||
written as:
|
||||
|
||||
.. code-block:: nim
|
||||
@@ -88,7 +88,7 @@ Lifetime-tracking hooks
|
||||
=======================
|
||||
|
||||
The memory management for Nim's standard ``string`` and ``seq`` types as
|
||||
well as other standard collections is performed via so called
|
||||
well as other standard collections is performed via so-called
|
||||
"Lifetime-tracking hooks" or "type-bound operators". There are 3 different
|
||||
hooks for each (generic or concrete) object type ``T`` (``T`` can also be a
|
||||
``distinct`` type) that are called implicitly by the compiler.
|
||||
@@ -128,13 +128,13 @@ The general pattern in ``=destroy`` looks like:
|
||||
------------
|
||||
|
||||
A `=sink` hook moves an object around, the resources are stolen from the source
|
||||
and passed to the destination. It is ensured that source's destructor does
|
||||
not free the resources afterwards by setting the object to its default value
|
||||
and passed to the destination. It is ensured that the source's destructor does
|
||||
not free the resources afterward by setting the object to its default value
|
||||
(the value the object's state started in). Setting an object ``x`` back to its
|
||||
default value is written as ``wasMoved(x)``. When not provided the compiler
|
||||
is using a combination of `=destroy` and `copyMem` instead. This is efficient
|
||||
hence users rarely need to implement their own `=sink` operator, it is enough to
|
||||
provide `=destroy` and `=copy`, compiler will take care about the rest.
|
||||
provide `=destroy` and `=copy`, compiler will take care of the rest.
|
||||
|
||||
The prototype of this hook for a type ``T`` needs to be:
|
||||
|
||||
@@ -184,14 +184,20 @@ The general pattern in ``=copy`` looks like:
|
||||
|
||||
|
||||
The ``=copy`` proc can be marked with the ``{.error.}`` pragma. Then any assignment
|
||||
that otherwise would lead to a copy is prevented at compile-time.
|
||||
that otherwise would lead to a copy is prevented at compile-time. This looks like:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
proc `=copy`(dest: var T; source: T) {.error.}
|
||||
|
||||
but a custom error message (e.g., ``{.error: "custom error".}``) will not be emitted
|
||||
by the compiler. Notice that there is no ``=`` before the ``{.error.}`` pragma.
|
||||
|
||||
Move semantics
|
||||
==============
|
||||
|
||||
A "move" can be regarded as an optimized copy operation. If the source of the
|
||||
copy operation is not used afterwards, the copy can be replaced by a move. This
|
||||
copy operation is not used afterward, the copy can be replaced by a move. This
|
||||
document uses the notation ``lastReadOf(x)`` to describe that ``x`` is not
|
||||
used afterwards. This property is computed by a static control flow analysis
|
||||
but can also be enforced by using ``system.move`` explicitly.
|
||||
@@ -218,7 +224,7 @@ Sink parameters
|
||||
===============
|
||||
|
||||
To move a variable into a collection usually ``sink`` parameters are involved.
|
||||
A location that is passed to a ``sink`` parameter should not be used afterwards.
|
||||
A location that is passed to a ``sink`` parameter should not be used afterward.
|
||||
This is ensured by a static analysis over a control flow graph. If it cannot be
|
||||
proven to be the last usage of the location, a copy is done instead and this
|
||||
copy is then passed to the sink parameter.
|
||||
@@ -232,7 +238,7 @@ without any further overloads and ``put`` might not take ownership of ``k`` if
|
||||
not a linear type system.
|
||||
|
||||
The employed static analysis is limited and only concerned with local variables;
|
||||
however object and tuple fields are treated as separate entities:
|
||||
however, object and tuple fields are treated as separate entities:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
@@ -509,7 +515,7 @@ to avoid this overhead:
|
||||
In fact, ``.cursor`` more generally prevents object construction/destruction pairs
|
||||
and so can also be useful in other contexts. The alternative solution would be to
|
||||
use raw pointers (``ptr``) instead which is more cumbersome and also more dangerous
|
||||
for Nim's evolution: Later on the compiler can try to prove ``.cursor`` annotations
|
||||
for Nim's evolution: Later on, the compiler can try to prove ``.cursor`` annotations
|
||||
to be safe, but for ``ptr`` the compiler has to remain silent about possible
|
||||
problems.
|
||||
|
||||
@@ -522,7 +528,7 @@ a form of copy elision.
|
||||
|
||||
To see how and when we can do that, think about this question: In `dest = src` when
|
||||
do we really have to *materialize* the full copy? - Only if `dest` or `src` are mutated
|
||||
afterwards. If `dest` is a local variable that is simple to analyse. And if `src` is a
|
||||
afterward. If `dest` is a local variable that is simple to analyze. And if `src` is a
|
||||
location derived from a formal parameter, we also know it is not mutated! In other
|
||||
words, we do a compile-time copy-on-write analysis.
|
||||
|
||||
@@ -547,9 +553,9 @@ other words, a copy ``x = y`` is implemented
|
||||
as ``x[0] = y[0]; x[1] = y[1]; ...``, likewise for ``=sink`` and ``=destroy``.
|
||||
|
||||
Other value-based compound types like ``object`` and ``array`` are handled
|
||||
correspondingly. For ``object`` however, the compiler generated hooks
|
||||
correspondingly. For ``object`` however, the compiler-generated hooks
|
||||
can be overridden. This can also be important to use an alternative traversal
|
||||
of the involved datastructure that is more efficient or in order to avoid
|
||||
of the involved data structure that is more efficient or in order to avoid
|
||||
deep recursions.
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Introduction
|
||||
This document describes the `documentation generation tools`:idx: built into
|
||||
the `Nim compiler <nimc.html>`_, which can generate HTML and JSON output
|
||||
from input .nim files and projects, as well as HTML and LaTeX from input RST
|
||||
(reStructuredText) files. The output documentation will include module
|
||||
(reStructuredText) files. The output documentation will include the module
|
||||
dependencies (``import``), any top-level documentation comments (##), and
|
||||
exported symbols (*), including procedures, types, and variables.
|
||||
|
||||
@@ -107,7 +107,7 @@ Document Types
|
||||
HTML
|
||||
----
|
||||
|
||||
Generation of HTML documents is done via the ``doc`` command. This command
|
||||
The generation of HTML documents is done via the ``doc`` command. This command
|
||||
takes either a single .nim file, outputting a single .html file with the same
|
||||
base filename, or multiple .nim files, outputting multiple .html files and,
|
||||
optionally, an index file.
|
||||
@@ -121,15 +121,15 @@ Partial Output::
|
||||
...
|
||||
|
||||
The full output can be seen here: `docgen_sample.html <docgen_sample.html>`_.
|
||||
It runs after semantic checking, and includes pragmas attached implicitly by the
|
||||
It runs after semantic checking and includes pragmas attached implicitly by the
|
||||
compiler.
|
||||
|
||||
|
||||
JSON
|
||||
----
|
||||
|
||||
Generation of JSON documents is done via the ``jsondoc`` command. This command
|
||||
takes in a .nim file, and outputs a .json file with the same base filename. Note
|
||||
The generation of JSON documents is done via the ``jsondoc`` command. This command
|
||||
takes in a .nim file and outputs a .json file with the same base filename. Note
|
||||
that this tool is built off of the ``doc`` command (previously ``doc2``), and
|
||||
contains the same information.
|
||||
|
||||
@@ -153,8 +153,8 @@ Output::
|
||||
]
|
||||
}
|
||||
|
||||
Similarly to the old ``doc`` command the old ``jsondoc`` command has been
|
||||
renamed ``jsondoc0``.
|
||||
Similarly to the old ``doc`` command, the old ``jsondoc`` command has been
|
||||
renamed to ``jsondoc0``.
|
||||
|
||||
The ``jsondoc0`` command::
|
||||
nim jsondoc0 sample
|
||||
@@ -193,12 +193,12 @@ Index switch
|
||||
------------
|
||||
|
||||
::
|
||||
nim doc2 --index:on filename.nim
|
||||
nim doc --index:on filename.nim
|
||||
|
||||
This will generate an index of all the exported symbols in the input Nim
|
||||
module, and put it into a neighboring file with the extension of ``.idx``. The
|
||||
index file is line oriented (newlines have to be escaped). Each line
|
||||
represents a tab separated record of several columns, the first two mandatory,
|
||||
index file is line-oriented (newlines have to be escaped). Each line
|
||||
represents a tab-separated record of several columns, the first two mandatory,
|
||||
the rest optional. See the `Index (idx) file format`_ section for details.
|
||||
|
||||
Once index files have been generated for one or more modules, the Nim
|
||||
@@ -210,7 +210,7 @@ See source switch
|
||||
-----------------
|
||||
|
||||
::
|
||||
nim doc2 --git.url:<url> filename.nim
|
||||
nim doc --git.url:<url> filename.nim
|
||||
|
||||
With the ``git.url`` switch the *See source* hyperlink will appear below each
|
||||
documented item in your source code pointing to the implementation of that
|
||||
@@ -231,7 +231,7 @@ You can edit ``config/nimdoc.cfg`` and modify the ``doc.item.seesrc`` value with
|
||||
|
||||
In the case of Nim's own documentation, the ``commit`` value is just a commit
|
||||
hash to append to a formatted URL to https://github.com/nim-lang/Nim. The
|
||||
``tools/nimweb.nim`` helper queries the current git commit hash during doc
|
||||
``tools/nimweb.nim`` helper queries the current git commit hash during the doc
|
||||
generation, but since you might be working on an unpublished repository, it
|
||||
also allows specifying a ``githash`` value in ``web/website.ini`` to force a
|
||||
specific commit in the output.
|
||||
@@ -260,10 +260,10 @@ HTML anchor generation
|
||||
======================
|
||||
|
||||
When you run the ``rst2html`` command, all sections in the RST document will
|
||||
get an anchor you can hyperlink to. Usually you can guess the anchor lower
|
||||
casing the section title and replacing spaces with dashes, and in any case you
|
||||
can get it from the table of contents. But when you run the ``doc`` or ``doc2``
|
||||
commands to generate API documentation, some symbol get one or two anchors at
|
||||
get an anchor you can hyperlink to. Usually, you can guess the anchor lower
|
||||
casing the section title and replacing spaces with dashes, and in any case, you
|
||||
can get it from the table of contents. But when you run the ``doc``
|
||||
command to generate API documentation, some symbol get one or two anchors at
|
||||
the same time: a numerical identifier, or a plain name plus a complex name.
|
||||
|
||||
The numerical identifier is just a random number. The number gets assigned
|
||||
@@ -274,20 +274,20 @@ numbers may shuffle around.
|
||||
The plain name of a symbol is a simplified version of its fully exported
|
||||
signature. Variables or constants have the same plain name symbol as their
|
||||
complex name. The plain name for procs, templates, and other callable types
|
||||
will be their unquoted value after removing parameters, return types and
|
||||
pragmas. The plain name allows short and nice linking of symbols which works
|
||||
will be their unquoted value after removing parameters, return types, and
|
||||
pragmas. The plain name allows short and nice linking of symbols that works
|
||||
unless you have a module with collisions due to overloading.
|
||||
|
||||
If you hyperlink a plain name symbol and there are other matches on the same
|
||||
HTML file, most browsers will go to the first one. To differentiate the rest,
|
||||
you will need to use the complex name. A complex name for a callable type is
|
||||
made up from several parts:
|
||||
made up of several parts:
|
||||
|
||||
(**plain symbol**)(**.type**),(**first param**)?(**,param type**)\*
|
||||
|
||||
The first thing to note is that all callable types have at least a comma, even
|
||||
if they don't have any parameters. If there are parameters, they are
|
||||
represented by their types and will be comma separated. To the plain symbol a
|
||||
represented by their types and will be comma-separated. To the plain symbol a
|
||||
suffix may be added depending on the type of the callable:
|
||||
|
||||
------------- --------------
|
||||
@@ -337,15 +337,15 @@ references so they can be later concatenated into a big index file with
|
||||
`mergeIndexes() <rstgen.html#mergeIndexes,string>`_. This section documents
|
||||
the file format in detail.
|
||||
|
||||
Index files are line oriented and tab separated (newline and tab characters
|
||||
have to be escaped). Each line represents a record with at least two fields,
|
||||
Index files are line-oriented and tab-separated (newline and tab characters
|
||||
have to be escaped). Each line represents a record with at least two fields
|
||||
but can have up to four (additional columns are ignored). The content of these
|
||||
columns is:
|
||||
|
||||
1. Mandatory term being indexed. Terms can include quoting according to
|
||||
Nim's rules (e.g. \`^\`).
|
||||
2. Base filename plus anchor hyperlink (e.g. ``algorithm.html#*,int,SortOrder``).
|
||||
3. Optional human readable string to display as hyperlink. If the value is not
|
||||
3. Optional human-readable string to display as a hyperlink. If the value is not
|
||||
present or is the empty string, the hyperlink will be rendered
|
||||
using the term. Prefix whitespace indicates that this entry is
|
||||
not for an API symbol but for a TOC entry.
|
||||
@@ -361,14 +361,14 @@ human reading.
|
||||
To differentiate both types (documents and APIs), the index generator will add
|
||||
to the index of documents an entry with the title of the document. Since the
|
||||
title is the topmost element, it will be added with a second field containing
|
||||
just the filename without any HTML anchor. By convention this entry without
|
||||
just the filename without any HTML anchor. By convention, this entry without
|
||||
anchor is the *title entry*, and since entries in the index file are added as
|
||||
they are scanned, the title entry will be the first line. The title for APIs
|
||||
is not present because it can be generated concatenating the name of the file
|
||||
to the word **Module**.
|
||||
|
||||
Normal symbols are added to the index with surrounding whitespaces removed. An
|
||||
exception to this are table of content (TOC) entries. TOC entries are added to
|
||||
exception to this are the table of content (TOC) entries. TOC entries are added to
|
||||
the index file with their third column having as much prefix spaces as their
|
||||
level is in the TOC (at least 1 character). The prefix whitespace helps to
|
||||
filter TOC entries from API or text symbols. This is important because the
|
||||
@@ -379,14 +379,14 @@ final index, and TOC entries found in ``.nim`` files are discarded.
|
||||
Additional resources
|
||||
====================
|
||||
|
||||
`Nim Compiler User Guide <nimc.html#compiler-usage-command-line-switches>`_
|
||||
`Nim Compiler User Guide <nimc.html#compiler-usage-commandminusline-switches>`_
|
||||
|
||||
`RST Quick Reference
|
||||
<http://docutils.sourceforge.net/docs/user/rst/quickref.html>`_
|
||||
|
||||
The output for HTML and LaTeX comes from the ``config/nimdoc.cfg`` and
|
||||
``config/nimdoc.tex.cfg`` configuration files. You can add and modify these
|
||||
files to your project to change the look of docgen output.
|
||||
files to your project to change the look of the docgen output.
|
||||
|
||||
You can import the `packages/docutils/rstgen module <rstgen.html>`_ in your
|
||||
programs if you want to reuse the compiler's documentation generation procs.
|
||||
|
||||
@@ -19,7 +19,7 @@ General Guidelines
|
||||
.. code-block:: nim
|
||||
|
||||
proc someproc*(s: string, foo: int) =
|
||||
## Use single backticks for inline code, eg: `s` or `someExpr(true)`.
|
||||
## Use single backticks for inline code, e.g.: `s` or `someExpr(true)`.
|
||||
## Use a backlash to follow with alphanumeric char: `int8`\s are great.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ Whenever an example of usage would be helpful to the user, you should include on
|
||||
doAssert addThree(3, 125, 6) == -122
|
||||
result = x +% y +% z
|
||||
|
||||
The commands ``nim doc`` and ``nim doc2`` will then correctly syntax highlight the Nim code within the documentation.
|
||||
The command ``nim doc`` will then correctly syntax highlight the Nim code within the documentation.
|
||||
|
||||
Types
|
||||
-----
|
||||
|
||||
@@ -13,8 +13,8 @@ Introduction
|
||||
|
||||
This document describes the usage of the *DrNim* tool. DrNim combines
|
||||
the Nim frontend with the `Z3 <https://github.com/Z3Prover/z3>`_ proof
|
||||
engine in order to allow verify / validate software written in Nim.
|
||||
DrNim's command line options are the same as the Nim compiler's.
|
||||
engine, in order to allow verify/validate software written in Nim.
|
||||
DrNim's command-line options are the same as the Nim compiler's.
|
||||
|
||||
|
||||
DrNim currently only checks the sections of your code that are marked
|
||||
@@ -140,8 +140,8 @@ Example: insertionSort
|
||||
swap a[t], a[t-1]
|
||||
dec t
|
||||
|
||||
Unfortunately the invariants required to prove this code correct take more
|
||||
code than the imperative instructions. However this effort can be compensated
|
||||
Unfortunately, the invariants required to prove that this code is correct take more
|
||||
code than the imperative instructions. However, this effort can be compensated
|
||||
by the fact that the result needs very little testing. Be aware though that
|
||||
DrNim only proves that after ``insertionSort`` this condition holds::
|
||||
|
||||
|
||||
42
doc/gc.rst
42
doc/gc.rst
@@ -26,8 +26,8 @@ To choose the memory management strategy use the ``--gc:`` switch.
|
||||
|
||||
- ``--gc:refc``. This is the default GC. It's a
|
||||
deferred reference counting based garbage collector
|
||||
with a simple Mark&Sweep backup GC in order to collect cycles. Heaps are thread local.
|
||||
- ``--gc:markAndSweep``. Simple Mark-And-Sweep based garbage collector. Heaps are thread local.
|
||||
with a simple Mark&Sweep backup GC in order to collect cycles. Heaps are thread-local.
|
||||
- ``--gc:markAndSweep``. Simple Mark-And-Sweep based garbage collector. Heaps are thread-local.
|
||||
- ``--gc:boehm``. Boehm based garbage collector, it offers a shared heap.
|
||||
- ``--gc:go``. Go's garbage collector, useful for interoperability with Go. Offers a shared heap.
|
||||
- ``--gc:arc``. Plain reference counting with
|
||||
@@ -35,11 +35,11 @@ To choose the memory management strategy use the ``--gc:`` switch.
|
||||
It offers deterministic performance for `hard realtime`:idx: systems. Reference cycles
|
||||
cause memory leaks, beware.
|
||||
|
||||
- ``--gc:orc``. Same as ``-gc:arc`` but adds a cycle collector based on "trial deletion".
|
||||
Unfortunately that makes its performance profile hard to reason about so it is less
|
||||
useful for hard realtime systems.
|
||||
- ``--gc:orc``. Same as ``--gc:arc`` but adds a cycle collector based on "trial deletion".
|
||||
Unfortunately, that makes its performance profile hard to reason about so it is less
|
||||
useful for hard real-time systems.
|
||||
|
||||
- ``--gc:none``. No memory management strategy nor garbage collector. Allocated memory is
|
||||
- ``--gc:none``. No memory management strategy nor a garbage collector. Allocated memory is
|
||||
simply never freed. You should use ``--gc:arc`` instead.
|
||||
|
||||
|
||||
@@ -71,10 +71,10 @@ The cycle collector can be en-/disabled independently from the other parts of
|
||||
the garbage collector with ``GC_enableMarkAndSweep`` and ``GC_disableMarkAndSweep``.
|
||||
|
||||
|
||||
Soft realtime support
|
||||
Soft real-time support
|
||||
---------------------
|
||||
|
||||
To enable realtime support, the symbol `useRealtimeGC`:idx: needs to be
|
||||
To enable real-time support, the symbol `useRealtimeGC`:idx: needs to be
|
||||
defined via ``--define:useRealtimeGC`` (you can put this into your config
|
||||
file as well).
|
||||
With this switch the garbage collector supports the following operations:
|
||||
@@ -85,7 +85,7 @@ With this switch the garbage collector supports the following operations:
|
||||
|
||||
The unit of the parameters ``maxPauseInUs`` and ``us`` is microseconds.
|
||||
|
||||
These two procs are the two modus operandi of the realtime garbage collector:
|
||||
These two procs are the two modus operandi of the real-time garbage collector:
|
||||
|
||||
(1) GC_SetMaxPause Mode
|
||||
|
||||
@@ -98,21 +98,25 @@ These two procs are the two modus operandi of the realtime garbage collector:
|
||||
(2) GC_step Mode
|
||||
|
||||
This allows the garbage collector to perform some work for up to ``us`` time.
|
||||
This is useful to call in a main loop to ensure the garbage collector can do its work.
|
||||
This is useful to call in the main loop to ensure the garbage collector can do its work.
|
||||
To bind all garbage collector activity to a ``GC_step`` call,
|
||||
deactivate the garbage collector with ``GC_disable`` at program startup.
|
||||
If ``strongAdvice`` is set to ``true``,
|
||||
then the garbage collector will be forced to perform collection cycle.
|
||||
then the garbage collector will be forced to perform the collection cycle.
|
||||
Otherwise, the garbage collector may decide not to do anything,
|
||||
if there is not much garbage to collect.
|
||||
You may also specify the current stack size via ``stackSize`` parameter.
|
||||
It can improve performance, when you know that there are no unique Nim
|
||||
references below certain point on the stack. Make sure the size you specify
|
||||
is greater than the potential worst case size.
|
||||
It can improve performance when you know that there are no unique Nim references
|
||||
below a certain point on the stack. Make sure the size you specify is greater
|
||||
than the potential worst-case size.
|
||||
|
||||
These procs provide a "best effort" realtime guarantee; in particular the
|
||||
It can improve performance when you know that there are no unique Nim
|
||||
references below a certain point on the stack. Make sure the size you specify
|
||||
is greater than the potential worst-case size.
|
||||
|
||||
These procs provide a "best effort" real-time guarantee; in particular the
|
||||
cycle collector is not aware of deadlines. Deactivate it to get more
|
||||
predictable realtime behaviour. Tests show that a 1ms max pause
|
||||
predictable real-time behaviour. Tests show that a 1ms max pause
|
||||
time will be met in almost all cases on modern CPUs (with the cycle collector
|
||||
disabled).
|
||||
|
||||
@@ -120,14 +124,14 @@ disabled).
|
||||
Time measurement with garbage collectors
|
||||
----------------------------------------
|
||||
|
||||
The garbage collectors's way of measuring time uses
|
||||
The garbage collectors' way of measuring time uses
|
||||
(see ``lib/system/timers.nim`` for the implementation):
|
||||
|
||||
1) ``QueryPerformanceCounter`` and ``QueryPerformanceFrequency`` on Windows.
|
||||
2) ``mach_absolute_time`` on Mac OS X.
|
||||
3) ``gettimeofday`` on Posix systems.
|
||||
|
||||
As such it supports a resolution of nanoseconds internally; however the API
|
||||
As such it supports a resolution of nanoseconds internally; however, the API
|
||||
uses microseconds for convenience.
|
||||
|
||||
Define the symbol ``reportMissedDeadlines`` to make the
|
||||
@@ -174,7 +178,7 @@ Heap dump
|
||||
The heap dump feature is still in its infancy, but it already proved
|
||||
useful for us, so it might be useful for you. To get a heap dump, compile
|
||||
with ``-d:nimTypeNames`` and call ``dumpNumberOfInstances`` at a strategic place in your program.
|
||||
This produces a list of used types in your program and for every type
|
||||
This produces a list of the used types in your program and for every type
|
||||
the total amount of object instances for this type as well as the total
|
||||
amount of bytes these instances take up. This list is currently unsorted!
|
||||
You need to use external shell script hacking to sort it.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user