mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-01 11:23:40 +00:00
Compare commits
84 Commits
v2.0.12
...
version-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10564f25b3 | ||
|
|
fbc7e54e95 | ||
|
|
7f3dbd5656 | ||
|
|
71f3e100b6 | ||
|
|
d2cb099e44 | ||
|
|
7e51e48cac | ||
|
|
19c89622ca | ||
|
|
b1d9af4d5f | ||
|
|
c467532484 | ||
|
|
114d0b8bdc | ||
|
|
f8ce7ddd6d | ||
|
|
cd6dbbd7f3 | ||
|
|
acac0bc1f2 | ||
|
|
82f3a57612 | ||
|
|
7e589bcbe4 | ||
|
|
dbed9310ba | ||
|
|
9524edec60 | ||
|
|
574db65396 | ||
|
|
e2bf3a6f70 | ||
|
|
6f2dbc105e | ||
|
|
63151568b4 | ||
|
|
4610c2b314 | ||
|
|
d01002d8f8 | ||
|
|
bc2fa6fe32 | ||
|
|
41637db18f | ||
|
|
b7eefc31d8 | ||
|
|
5df3bf467e | ||
|
|
ac44139084 | ||
|
|
ac882ea696 | ||
|
|
56f9559c69 | ||
|
|
c08c32a1ed | ||
|
|
03491904a0 | ||
|
|
57f84c5376 | ||
|
|
1df4debbf1 | ||
|
|
1ff69eae17 | ||
|
|
4fa122eb44 | ||
|
|
53782b1404 | ||
|
|
cafe1284ac | ||
|
|
e2ae7d5f43 | ||
|
|
772ebe6715 | ||
|
|
32c99651fc | ||
|
|
2eac7941ff | ||
|
|
cedcb7881d | ||
|
|
117b913458 | ||
|
|
bf4de6a394 | ||
|
|
86f1a2785a | ||
|
|
c7d057d7f9 | ||
|
|
8f44c40b6b | ||
|
|
76935b4c34 | ||
|
|
30abe60cda | ||
|
|
14dfabb230 | ||
|
|
5fb4662ab1 | ||
|
|
535556875e | ||
|
|
95fa7f0f12 | ||
|
|
6bcb078476 | ||
|
|
5c58e7d201 | ||
|
|
5327498547 | ||
|
|
d84d41dc95 | ||
|
|
693b35b59f | ||
|
|
c1bb144fdc | ||
|
|
1f38c3cea8 | ||
|
|
f45ca4fdf4 | ||
|
|
5cbc7a6d1b | ||
|
|
56e7c75e03 | ||
|
|
d51236e9cc | ||
|
|
4d0d848235 | ||
|
|
8859f1ddf7 | ||
|
|
0e2b34ce35 | ||
|
|
ba516c8eb5 | ||
|
|
009a5b0684 | ||
|
|
c786415eef | ||
|
|
33dc54c573 | ||
|
|
6a1d1a8c2b | ||
|
|
0c426e7875 | ||
|
|
4e1b5ee702 | ||
|
|
3a334e09ea | ||
|
|
dbe9c724a0 | ||
|
|
9620d206b9 | ||
|
|
9e5cdc43a6 | ||
|
|
1778b8354a | ||
|
|
f6f72722bb | ||
|
|
90993aeff6 | ||
|
|
15e5ddc675 | ||
|
|
9f43f9fa6e |
2
.github/workflows/ci_bench.yml
vendored
2
.github/workflows/ci_bench.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
os: [ubuntu-24.04]
|
||||
cpu: [amd64]
|
||||
name: '${{ matrix.os }}'
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
2
.github/workflows/ci_docs.yml
vendored
2
.github/workflows/ci_docs.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
target: [linux, windows, osx]
|
||||
include:
|
||||
- target: linux
|
||||
os: ubuntu-20.04
|
||||
os: ubuntu-22.04
|
||||
- target: windows
|
||||
os: windows-2019
|
||||
- target: osx
|
||||
|
||||
76
.github/workflows/ci_gcc14.yml
vendored
Normal file
76
.github/workflows/ci_gcc14.yml
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
name: GCC 14
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- 'devel'
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04]
|
||||
cpu: [amd64]
|
||||
name: '${{ matrix.os }}'
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60 # refs bug #18178
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: 'Install node.js 20.x'
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
- name: 'Install dependencies (Linux amd64)'
|
||||
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
|
||||
run: |
|
||||
sudo apt update -qq
|
||||
sudo apt remove needrestart
|
||||
DEBIAN_FRONTEND='noninteractive' \
|
||||
sudo apt install --no-install-recommends -yq \
|
||||
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev \
|
||||
valgrind libc6-dbg libblas-dev xorg-dev
|
||||
- name: 'Install dependencies (Linux amd64 gcc 14)'
|
||||
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
|
||||
run: |
|
||||
sudo add-apt-repository universe
|
||||
sudo apt update -qq
|
||||
sudo apt install -y gcc-14 g++-14 libpcre3 liblapack-dev
|
||||
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 60 --slave /usr/bin/g++ g++ /usr/bin/g++-14
|
||||
- name: 'Install dependencies (macOS)'
|
||||
if: runner.os == 'macOS'
|
||||
run: brew install boehmgc make sfml gtk+3
|
||||
- name: 'Install dependencies (Windows)'
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
. ci/funs.sh
|
||||
nimInternalInstallDepsWindows
|
||||
echo_run echo "${{ github.workspace }}/dist/mingw64/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'Add build binaries to PATH'
|
||||
shell: bash
|
||||
run: echo "${{ github.workspace }}/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'NIM_TESTAMENT_DISABLE_SSL'
|
||||
shell: bash
|
||||
run: echo "NIM_TESTAMENT_DISABLE_SSL=1" >> $GITHUB_ENV
|
||||
|
||||
- name: 'System information'
|
||||
shell: bash
|
||||
run: . ci/funs.sh && nimCiSystemInfo
|
||||
|
||||
- name: 'Build csourcesAny'
|
||||
shell: bash
|
||||
run: . ci/funs.sh && nimBuildCsourcesIfNeeded CC=gcc ucpu='${{ matrix.cpu }}'
|
||||
|
||||
- name: 'koch, Run CI'
|
||||
shell: bash
|
||||
run: . ci/funs.sh && nimInternalBuildKochAndRunCI
|
||||
2
.github/workflows/ci_packages.yml
vendored
2
.github/workflows/ci_packages.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-13]
|
||||
os: [ubuntu-22.04, macos-13]
|
||||
cpu: [amd64]
|
||||
batch: ["allowed_failures", "0_3", "1_3", "2_3"] # list of `index_num`
|
||||
name: '${{ matrix.os }} (batch: ${{ matrix.batch }})'
|
||||
|
||||
17
.github/workflows/ci_publish.yml
vendored
17
.github/workflows/ci_publish.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
os: [ubuntu-22.04]
|
||||
cpu: [amd64]
|
||||
name: '${{ matrix.os }}'
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -21,10 +21,10 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: 'Install node.js 20.x'
|
||||
- name: 'Install node.js'
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
node-version: ''
|
||||
|
||||
- name: 'Install dependencies (Linux amd64)'
|
||||
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
|
||||
@@ -34,17 +34,6 @@ jobs:
|
||||
sudo apt-fast install --no-install-recommends -yq \
|
||||
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev \
|
||||
valgrind libc6-dbg libblas-dev xorg-dev
|
||||
- name: 'Install dependencies (macOS)'
|
||||
if: runner.os == 'macOS'
|
||||
run: brew install boehmgc make sfml gtk+3
|
||||
- name: 'Install dependencies (Windows)'
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
. ci/funs.sh
|
||||
nimInternalInstallDepsWindows
|
||||
echo_run echo "${{ github.workspace }}/dist/mingw64/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: 'Add build binaries to PATH'
|
||||
shell: bash
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
Linux_amd64:
|
||||
vmImage: 'ubuntu-20.04'
|
||||
vmImage: 'ubuntu-24.04'
|
||||
CPU: amd64
|
||||
# regularly breaks, refs bug #17325
|
||||
# Linux_i386:
|
||||
@@ -36,16 +36,16 @@ jobs:
|
||||
CPU: amd64
|
||||
NIM_COMPILE_TO_CPP: true
|
||||
Windows_amd64_batch0_3:
|
||||
vmImage: 'windows-2019'
|
||||
vmImage: 'windows-2025'
|
||||
CPU: amd64
|
||||
# see also: `NIM_TEST_PACKAGES`
|
||||
NIM_TESTAMENT_BATCH: "0_3"
|
||||
Windows_amd64_batch1_3:
|
||||
vmImage: 'windows-2019'
|
||||
vmImage: 'windows-2025'
|
||||
CPU: amd64
|
||||
NIM_TESTAMENT_BATCH: "1_3"
|
||||
Windows_amd64_batch2_3:
|
||||
vmImage: 'windows-2019'
|
||||
vmImage: 'windows-2025'
|
||||
CPU: amd64
|
||||
NIM_TESTAMENT_BATCH: "2_3"
|
||||
|
||||
@@ -80,10 +80,12 @@ jobs:
|
||||
- bash: |
|
||||
set -e
|
||||
. ci/funs.sh
|
||||
echo_run sudo apt-fast update -qq
|
||||
echo_run sudo add-apt-repository universe
|
||||
echo_run sudo apt-get update -qq
|
||||
DEBIAN_FRONTEND='noninteractive' \
|
||||
echo_run sudo apt-fast install --no-install-recommends -yq \
|
||||
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev valgrind libc6-dbg
|
||||
echo_run sudo apt-get install --no-install-recommends -yq \
|
||||
gcc-14 g++-14 libpcre3 liblapack-dev libpcre3 liblapack-dev libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev valgrind libc6-dbg
|
||||
echo_run sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 60 --slave /usr/bin/g++ g++ /usr/bin/g++-14
|
||||
displayName: 'Install dependencies (amd64 Linux)'
|
||||
condition: and(succeeded(), eq(variables['skipci'], 'false'), eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'amd64'))
|
||||
|
||||
@@ -100,12 +102,12 @@ jobs:
|
||||
Pin-Priority: 1001
|
||||
EOF
|
||||
|
||||
# echo_run sudo apt-fast update -qq
|
||||
echo_run sudo apt-fast update -qq || echo "failed, see bug #17343"
|
||||
# echo_run sudo apt-get update -qq
|
||||
echo_run sudo apt-get update -qq || echo "failed, see bug #17343"
|
||||
# `:i386` (e.g. in `libffi-dev:i386`) is needed otherwise you may get:
|
||||
# `could not load: libffi.so` during dynamic loading.
|
||||
DEBIAN_FRONTEND='noninteractive' \
|
||||
echo_run sudo apt-fast install --no-install-recommends --allow-downgrades -yq \
|
||||
echo_run sudo apt-get install --no-install-recommends --allow-downgrades -yq \
|
||||
g++-multilib gcc-multilib libcurl4-openssl-dev:i386 libgc-dev:i386 \
|
||||
libsdl1.2-dev:i386 libsfml-dev:i386 libglib2.0-dev:i386 libffi-dev:i386
|
||||
|
||||
|
||||
@@ -24,6 +24,6 @@ if not exist %nim_csources% (
|
||||
cd ..
|
||||
copy /y bin\nim.exe %nim_csources%
|
||||
)
|
||||
bin\nim.exe c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch
|
||||
koch boot -d:release --skipUserCfg --skipParentCfg --hints:off
|
||||
koch tools --skipUserCfg --skipParentCfg --hints:off
|
||||
bin\nim.exe c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch
|
||||
koch boot -d:release --skipUserCfg --skipParentCfg --hints:off
|
||||
koch tools --skipUserCfg --skipParentCfg --hints:off
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
slots when enlarging a sequence.
|
||||
- Added `hasDefaultValue` to `std/typetraits` to check if a type has a valid default value.
|
||||
- Added Viewport API for the JavaScript targets in the `dom` module.
|
||||
- Added `toSinglyLinkedRing` and `toDoublyLinkedRing` to `std/lists` to convert from `openArray`s.
|
||||
- ORC: To be enabled via `nimOrcStats` there is a new API called `GC_orcStats` that can be used to query how many
|
||||
objects the cyclic collector did free. If the number is zero that is a strong indicator that you can use `--mm:arc`
|
||||
instead of `--mm:orc`.
|
||||
- A `$` template is provided for `Path` in `std/paths`.
|
||||
|
||||
[//]: # "Deprecations:"
|
||||
|
||||
|
||||
@@ -2362,7 +2362,7 @@ proc genWasMoved(p: BProc; n: PNode) =
|
||||
|
||||
proc genMove(p: BProc; n: PNode; d: var TLoc) =
|
||||
var a: TLoc
|
||||
initLocExpr(p, n[1].skipAddr, a)
|
||||
initLocExpr(p, n[1].skipAddr, a, {lfEnforceDeref})
|
||||
if n.len == 4:
|
||||
# generated by liftdestructors:
|
||||
var src: TLoc
|
||||
@@ -3118,16 +3118,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
of nkObjConstr: genObjConstr(p, n, d)
|
||||
of nkCast: genCast(p, n, d)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, d)
|
||||
of nkHiddenAddr:
|
||||
if n[0].kind == nkDerefExpr:
|
||||
# addr ( deref ( x )) --> x
|
||||
var x = n[0][0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
x.typ = n.typ
|
||||
expr(p, x, d)
|
||||
return
|
||||
genAddr(p, n, d)
|
||||
of nkAddr: genAddr(p, n, d)
|
||||
of nkAddr, nkHiddenAddr: genAddr(p, n, d)
|
||||
of nkBracketExpr: genBracketExpr(p, n, d)
|
||||
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, d)
|
||||
of nkDotExpr: genRecordField(p, n, d)
|
||||
@@ -3312,8 +3303,12 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
isConst: bool, info: TLineInfo) =
|
||||
case obj.kind
|
||||
of nkRecList:
|
||||
let isUnion = tfUnion in t.flags
|
||||
for it in obj.sons:
|
||||
getNullValueAux(p, t, it, constOrNil, result, count, isConst, info)
|
||||
if isUnion:
|
||||
# generate only 1 field for default value of union
|
||||
return
|
||||
of nkRecCase:
|
||||
getNullValueAux(p, t, obj[0], constOrNil, result, count, isConst, info)
|
||||
var res = ""
|
||||
|
||||
@@ -18,7 +18,7 @@ proc registerTraverseProc(p: BProc, v: PSym) =
|
||||
var traverseProc = ""
|
||||
if p.config.selectedGC in {gcMarkAndSweep, gcHooks, gcRefc} and
|
||||
optOwnedRefs notin p.config.globalOptions and
|
||||
containsGarbageCollectedRef(v.loc.t):
|
||||
containsManagedMemory(v.loc.t):
|
||||
# we register a specialized marked proc here; this has the advantage
|
||||
# that it works out of the box for thread local storage then :-)
|
||||
traverseProc = genTraverseProcForGlobal(p.module, v, v.info)
|
||||
|
||||
@@ -768,6 +768,8 @@ proc fillObjectFields*(m: BModule; typ: PType) =
|
||||
# this fact here.
|
||||
var check = initIntSet()
|
||||
discard getRecordFields(m, typ, check)
|
||||
if typ.baseClass != nil:
|
||||
fillObjectFields(m, typ.baseClass.skipTypes(skipPtrs))
|
||||
|
||||
proc mangleDynLibProc(sym: PSym): Rope
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ type
|
||||
|
||||
const
|
||||
nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
|
||||
nkCommentStmt, nkMixinStmt, nkBindStmt} + procDefs
|
||||
nkCommentStmt, nkMixinStmt, nkBindStmt, nkTypeOfExpr} + procDefs
|
||||
|
||||
proc newStateAccess(ctx: var Ctx): PNode =
|
||||
if ctx.stateVarSym.isNil:
|
||||
|
||||
@@ -452,6 +452,11 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
|
||||
proc cFileSpecificOptions(conf: ConfigRef; nimname, fullNimFile: string): string =
|
||||
result = conf.compileOptions
|
||||
|
||||
if (conf.cCompiler == ccGcc or conf.cCompiler == ccCLang) and
|
||||
conf.selectedGC == gcRefc:
|
||||
# bug #10625
|
||||
addOpt(result, "-fno-omit-frame-pointer")
|
||||
|
||||
for option in conf.compileOptionsCmd:
|
||||
if strutils.find(result, option, 0) < 0:
|
||||
addOpt(result, option)
|
||||
|
||||
@@ -795,15 +795,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
result = passCopyToSink(n, c, s)
|
||||
elif n.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure, nkNilLit} +
|
||||
nkCallKinds + nkLiterals:
|
||||
if n.kind in nkCallKinds and n[0].kind == nkSym:
|
||||
if n[0].sym.magic == mEnsureMove:
|
||||
inc c.inEnsureMove
|
||||
result = p(n[1], c, s, sinkArg)
|
||||
dec c.inEnsureMove
|
||||
else:
|
||||
result = p(n, c, s, consumed)
|
||||
else:
|
||||
result = p(n, c, s, consumed)
|
||||
result = p(n, c, s, consumed)
|
||||
elif ((n.kind == nkSym and isSinkParam(n.sym)) or isAnalysableFieldAccess(n, c.owner)) and
|
||||
isLastRead(n, c, s) and not (n.kind == nkSym and isCursor(n)):
|
||||
# Sinked params can be consumed only once. We need to reset the memory
|
||||
@@ -878,12 +870,6 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
if mode == normal and (isRefConstr or hasCustomDestructor(c, t)):
|
||||
result = ensureDestruction(result, n, c, s)
|
||||
of nkCallKinds:
|
||||
if n[0].kind == nkSym and n[0].sym.magic == mEnsureMove:
|
||||
inc c.inEnsureMove
|
||||
result = p(n[1], c, s, sinkArg)
|
||||
dec c.inEnsureMove
|
||||
return
|
||||
|
||||
let inSpawn = c.inSpawn
|
||||
if n[0].kind == nkSym and n[0].sym.magic == mSpawn:
|
||||
c.inSpawn.inc
|
||||
@@ -900,13 +886,19 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
isDangerous = true
|
||||
|
||||
result = shallowCopy(n)
|
||||
for i in 1..<n.len:
|
||||
if i < L and isCompileTimeOnly(parameters[i]):
|
||||
result[i] = n[i]
|
||||
elif i < L and (isSinkTypeForParam(parameters[i]) or inSpawn > 0):
|
||||
result[i] = p(n[i], c, s, sinkArg)
|
||||
else:
|
||||
result[i] = p(n[i], c, s, normal)
|
||||
|
||||
if n[0].kind == nkSym and n[0].sym.magic == mEnsureMove:
|
||||
inc c.inEnsureMove
|
||||
result[1] = p(n[1], c, s, sinkArg)
|
||||
dec c.inEnsureMove
|
||||
else:
|
||||
for i in 1..<n.len:
|
||||
if i < L and isCompileTimeOnly(parameters[i]):
|
||||
result[i] = n[i]
|
||||
elif i < L and (isSinkTypeForParam(parameters[i]) or inSpawn > 0):
|
||||
result[i] = p(n[i], c, s, sinkArg)
|
||||
else:
|
||||
result[i] = p(n[i], c, s, normal)
|
||||
|
||||
when false:
|
||||
if isDangerous:
|
||||
|
||||
@@ -1519,15 +1519,8 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
else: internalError(p.config, n[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')')
|
||||
of nkObjDownConv:
|
||||
gen(p, n[0], r)
|
||||
of nkHiddenDeref:
|
||||
of nkHiddenDeref, nkDerefExpr:
|
||||
gen(p, n[0], r)
|
||||
of nkDerefExpr:
|
||||
var x = n[0]
|
||||
if n.kind == nkHiddenAddr:
|
||||
x = n[0][0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
x.typ = n.typ
|
||||
gen(p, x, r)
|
||||
of nkHiddenAddr:
|
||||
gen(p, n[0], r)
|
||||
of nkConv:
|
||||
|
||||
@@ -39,7 +39,7 @@ template asink*(t: PType): PSym = getAttachedOp(c.g, t, attachedSink)
|
||||
|
||||
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
|
||||
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
info: TLineInfo; idgen: IdGenerator; isDistinct = false): PSym
|
||||
info: TLineInfo; idgen: IdGenerator): PSym
|
||||
|
||||
proc createTypeBoundOps*(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo;
|
||||
idgen: IdGenerator)
|
||||
@@ -217,17 +217,38 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool,
|
||||
fillBodyObj(c, n[0], body, x, y, enforceDefaultOp = false)
|
||||
c.filterDiscriminator = oldfilterDiscriminator
|
||||
of nkRecList:
|
||||
for t in items(n): fillBodyObj(c, t, body, x, y, enforceDefaultOp, enforceWasMoved)
|
||||
# destroys in reverse order #24719
|
||||
if c.kind == attachedDestructor:
|
||||
for i in countdown(n.len-1, 0):
|
||||
fillBodyObj(c, n[i], body, x, y, enforceDefaultOp, enforceWasMoved)
|
||||
else:
|
||||
for t in items(n): fillBodyObj(c, t, body, x, y, enforceDefaultOp, enforceWasMoved)
|
||||
else:
|
||||
illFormedAstLocal(n, c.g.config)
|
||||
|
||||
proc fillBodyObjTImpl(c: var TLiftCtx; t: PType, body, x, y: PNode) =
|
||||
if t.len > 0 and t[0] != nil:
|
||||
let obj = newNodeIT(nkHiddenSubConv, c.info, t[0])
|
||||
obj.add newNodeI(nkEmpty, c.info)
|
||||
obj.add x
|
||||
fillBody(c, skipTypes(t[0], abstractPtrs), body, obj, y)
|
||||
fillBodyObj(c, t.n, body, x, y, enforceDefaultOp = false)
|
||||
template fillBase =
|
||||
if t.len > 0 and t[0] != nil:
|
||||
let dest = newNodeIT(nkHiddenSubConv, c.info, t[0])
|
||||
dest.add newNodeI(nkEmpty, c.info)
|
||||
dest.add x
|
||||
var src = y
|
||||
if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink}:
|
||||
src = newNodeIT(nkHiddenSubConv, c.info, t[0])
|
||||
src.add newNodeI(nkEmpty, c.info)
|
||||
src.add y
|
||||
|
||||
fillBody(c, skipTypes(t[0], abstractPtrs), body, dest, src)
|
||||
template fillFields =
|
||||
fillBodyObj(c, t.n, body, x, y, enforceDefaultOp = false)
|
||||
|
||||
if c.kind == attachedDestructor:
|
||||
# destroys in reverse order #24719
|
||||
fillFields()
|
||||
fillBase()
|
||||
else:
|
||||
fillBase()
|
||||
fillFields()
|
||||
|
||||
proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
|
||||
var hasCase = isCaseObj(t.n)
|
||||
@@ -1036,9 +1057,7 @@ proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
|
||||
assert typ.kind == tyDistinct
|
||||
let baseType = typ[0]
|
||||
if getAttachedOp(g, baseType, kind) == nil:
|
||||
# TODO: fixme `isDistinct` is a fix for #23552; remove it after
|
||||
# `-d:nimPreviewNonVarDestructor` becomes the default
|
||||
discard produceSym(g, c, baseType, kind, info, idgen, isDistinct = true)
|
||||
discard produceSym(g, c, baseType, kind, info, idgen)
|
||||
result = getAttachedOp(g, baseType, kind)
|
||||
setAttachedOp(g, idgen.module, typ, kind, result)
|
||||
|
||||
@@ -1077,7 +1096,7 @@ proc symDupPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttache
|
||||
incl result.flags, sfGeneratedOp
|
||||
|
||||
proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
|
||||
info: TLineInfo; idgen: IdGenerator; isDiscriminant = false; isDistinct = false): PSym =
|
||||
info: TLineInfo; idgen: IdGenerator; isDiscriminant = false): PSym =
|
||||
if kind == attachedDup:
|
||||
return symDupPrototype(g, typ, owner, kind, info, idgen)
|
||||
|
||||
@@ -1087,7 +1106,7 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
|
||||
let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"),
|
||||
idgen, result, info)
|
||||
if kind == attachedDestructor and g.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and
|
||||
((g.config.isDefined("nimPreviewNonVarDestructor") and not isDiscriminant) or (typ.kind in {tyRef, tyString, tySequence} and not isDistinct)):
|
||||
((g.config.isDefined("nimPreviewNonVarDestructor") and not isDiscriminant) or (typ.kind in {tyRef, tyString, tySequence})):
|
||||
dest.typ = typ
|
||||
else:
|
||||
dest.typ = makeVarType(typ.owner, typ, idgen)
|
||||
@@ -1129,13 +1148,13 @@ proc genTypeFieldCopy(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add newAsgnStmt(xx, yy)
|
||||
|
||||
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
info: TLineInfo; idgen: IdGenerator; isDistinct = false): PSym =
|
||||
info: TLineInfo; idgen: IdGenerator): PSym =
|
||||
if typ.kind == tyDistinct:
|
||||
return produceSymDistinctType(g, c, typ, kind, info, idgen)
|
||||
|
||||
result = getAttachedOp(g, typ, kind)
|
||||
if result == nil:
|
||||
result = symPrototype(g, typ, typ.owner, kind, info, idgen, isDistinct = isDistinct)
|
||||
result = symPrototype(g, typ, typ.owner, kind, info, idgen)
|
||||
|
||||
var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType: typ, idgen: idgen,
|
||||
fn: result)
|
||||
@@ -1179,6 +1198,8 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
result.ast[pragmasPos].add newTree(nkExprColonExpr,
|
||||
newIdentNode(g.cache.getIdent("raises"), info), newNodeI(nkBracket, info))
|
||||
|
||||
if kind == attachedDestructor:
|
||||
incl result.options, optQuirky
|
||||
completePartialOp(g, idgen.module, typ, kind, result)
|
||||
|
||||
|
||||
|
||||
@@ -1295,8 +1295,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
pragmaProposition(c, it)
|
||||
of wEnsures:
|
||||
pragmaEnsures(c, it)
|
||||
of wEnforceNoRaises, wQuirky:
|
||||
of wEnforceNoRaises:
|
||||
sym.flags.incl sfNeverRaises
|
||||
of wQuirky:
|
||||
sym.flags.incl sfNeverRaises
|
||||
if sym.kind in {skProc, skMethod, skConverter, skFunc, skIterator}:
|
||||
sym.options.incl optQuirky
|
||||
of wSystemRaisesDefect:
|
||||
sym.flags.incl sfSystemRaisesDefect
|
||||
of wVirtual:
|
||||
|
||||
@@ -557,8 +557,16 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||
of nkIfExpr:
|
||||
result = lsub(g, n[0][0]) + lsub(g, n[0][1]) + lsons(g, n, 1) +
|
||||
len("if_:_")
|
||||
of nkElifExpr: result = lsons(g, n) + len("_elif_:_")
|
||||
of nkElseExpr: result = lsub(g, n[0]) + len("_else:_") # type descriptions
|
||||
of nkElifExpr, nkElifBranch:
|
||||
if isEmptyType(n[1].typ):
|
||||
result = lsons(g, n) + len("elif_:_")
|
||||
else:
|
||||
result = lsons(g, n) + len("_elif_:_")
|
||||
of nkElseExpr, nkElse:
|
||||
if isEmptyType(n[0].typ):
|
||||
result = lsub(g, n[0]) + len("else:_")
|
||||
else:
|
||||
result = lsub(g, n[0]) + len("_else:_") # type descriptions
|
||||
of nkTypeOfExpr: result = (if n.len > 0: lsub(g, n[0]) else: 0)+len("typeof()")
|
||||
of nkRefTy: result = (if n.len > 0: lsub(g, n[0])+1 else: 0) + len("ref")
|
||||
of nkPtrTy: result = (if n.len > 0: lsub(g, n[0])+1 else: 0) + len("ptr")
|
||||
@@ -601,8 +609,6 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||
of nkCommentStmt: result = n.comment.len
|
||||
of nkOfBranch: result = lcomma(g, n, 0, - 2) + lsub(g, lastSon(n)) + len("of_:_")
|
||||
of nkImportAs: result = lsub(g, n[0]) + len("_as_") + lsub(g, n[1])
|
||||
of nkElifBranch: result = lsons(g, n) + len("elif_:_")
|
||||
of nkElse: result = lsub(g, n[0]) + len("else:_")
|
||||
of nkFinally: result = lsub(g, n[0]) + len("finally:_")
|
||||
of nkGenericParams: result = lcomma(g, n) + 2
|
||||
of nkFormalParams:
|
||||
@@ -1459,15 +1465,30 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
|
||||
putWithSpace(g, tkColon, ":")
|
||||
if n.len > 0: gsub(g, n[0], 1)
|
||||
gsons(g, n, emptyContext, 1)
|
||||
of nkElifExpr:
|
||||
putWithSpace(g, tkElif, " elif")
|
||||
gcond(g, n[0])
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gsub(g, n, 1)
|
||||
of nkElseExpr:
|
||||
put(g, tkElse, " else")
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gsub(g, n, 0)
|
||||
of nkElifExpr, nkElifBranch:
|
||||
if isEmptyType(n[1].typ):
|
||||
optNL(g)
|
||||
putWithSpace(g, tkElif, "elif")
|
||||
gsub(g, n, 0)
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gcoms(g)
|
||||
gstmts(g, n[1], c)
|
||||
else:
|
||||
putWithSpace(g, tkElif, " elif")
|
||||
gcond(g, n[0])
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gsub(g, n, 1)
|
||||
of nkElseExpr, nkElse:
|
||||
if isEmptyType(n[0].typ):
|
||||
optNL(g)
|
||||
put(g, tkElse, "else")
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gcoms(g)
|
||||
gstmts(g, n[0], c)
|
||||
else:
|
||||
put(g, tkElse, " else")
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gsub(g, n, 0)
|
||||
of nkTypeOfExpr:
|
||||
put(g, tkType, "typeof")
|
||||
put(g, tkParLe, "(")
|
||||
@@ -1729,19 +1750,6 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
|
||||
of nkMixinStmt:
|
||||
putWithSpace(g, tkMixin, "mixin")
|
||||
gcomma(g, n, c)
|
||||
of nkElifBranch:
|
||||
optNL(g)
|
||||
putWithSpace(g, tkElif, "elif")
|
||||
gsub(g, n, 0)
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gcoms(g)
|
||||
gstmts(g, n[1], c)
|
||||
of nkElse:
|
||||
optNL(g)
|
||||
put(g, tkElse, "else")
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gcoms(g)
|
||||
gstmts(g, n[0], c)
|
||||
of nkFinally, nkDefer:
|
||||
optNL(g)
|
||||
if n.kind == nkFinally:
|
||||
|
||||
@@ -662,7 +662,8 @@ proc semResolvedCall(c: PContext, x: TCandidate,
|
||||
instGenericConvertersSons(c, result, x)
|
||||
markConvertersUsed(c, result)
|
||||
result[0] = newSymNode(finalCallee, getCallLineInfo(result[0]))
|
||||
result.typ = finalCallee.typ[0]
|
||||
if finalCallee.magic notin {mArrGet, mArrPut}:
|
||||
result.typ = finalCallee.typ[0]
|
||||
updateDefaultParams(result)
|
||||
|
||||
proc canDeref(n: PNode): bool {.inline.} =
|
||||
|
||||
@@ -1345,7 +1345,9 @@ proc readTypeParameter(c: PContext, typ: PType,
|
||||
# This seems semantically correct and then we'll be able
|
||||
# to return the section symbol directly here
|
||||
let foundType = makeTypeDesc(c, def[2].typ)
|
||||
return newSymNode(copySym(def[0].sym, c.idgen).linkTo(foundType), info)
|
||||
let s = copySym(def[0].sym, c.idgen)
|
||||
s.typ = foundType
|
||||
return newSymNode(s, info)
|
||||
|
||||
of nkConstSection:
|
||||
for def in statement:
|
||||
@@ -1370,7 +1372,9 @@ proc readTypeParameter(c: PContext, typ: PType,
|
||||
return c.graph.emptyNode
|
||||
else:
|
||||
let foundTyp = makeTypeDesc(c, rawTyp)
|
||||
return newSymNode(copySym(tParam.sym, c.idgen).linkTo(foundTyp), info)
|
||||
let s = copySym(tParam.sym, c.idgen)
|
||||
s.typ = foundTyp
|
||||
return newSymNode(s, info)
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1850,6 +1854,8 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
|
||||
else:
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
result = newNodeIT(nkHiddenAddr, n.info, if n.typ.kind in {tyVar, tyLent}: n.typ else: makePtrType(c, n.typ))
|
||||
if n.typ.kind in {tyVar, tyLent}:
|
||||
n.typ = n.typ.elementType
|
||||
result.add(n)
|
||||
|
||||
proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
||||
|
||||
@@ -757,7 +757,8 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
of nkCast:
|
||||
var a = getConstExpr(m, n[1], idgen, g)
|
||||
if a == nil: return
|
||||
if n.typ != nil and n.typ.kind in NilableTypes:
|
||||
if n.typ != nil and n.typ.kind in NilableTypes and
|
||||
not (n.typ.kind == tyProc and a.typ.kind == tyProc):
|
||||
# we allow compile-time 'cast' for pointer types:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
|
||||
@@ -577,7 +577,8 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
else:
|
||||
body = getBody(c.graph, s)
|
||||
else: body = n[bodyPos]
|
||||
n[bodyPos] = semGenericStmtScope(c, body, flags, ctx)
|
||||
let bodyFlags = if n.kind == nkTemplateDef: flags + {withinMixin} else: flags
|
||||
n[bodyPos] = semGenericStmtScope(c, body, bodyFlags, ctx)
|
||||
closeScope(c)
|
||||
of nkPragma, nkPragmaExpr: discard
|
||||
of nkExprColonExpr, nkExprEqExpr:
|
||||
|
||||
@@ -51,6 +51,7 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) =
|
||||
of nkObjConstr:
|
||||
let x = t.skipTypes(abstractPtrs)
|
||||
n.typ = t
|
||||
n[0].typ = t
|
||||
for i in 1..<n.len:
|
||||
var j = i-1
|
||||
let field = x.ithField(j)
|
||||
|
||||
@@ -11,7 +11,7 @@ import
|
||||
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
||||
wordrecg, strutils, options, guards, lineinfos, semfold, semdata,
|
||||
modulegraphs, varpartitions, typeallowed, nilcheck, errorhandling, tables,
|
||||
semstrictfuncs
|
||||
semstrictfuncs, lowerings
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
@@ -89,10 +89,11 @@ const
|
||||
errXCannotBeAssignedTo = "'$1' cannot be assigned to"
|
||||
errLetNeedsInit = "'let' symbol requires an initialization"
|
||||
|
||||
proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo) =
|
||||
if typ == nil or sfGeneratedOp in tracked.owner.flags:
|
||||
proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo; explicit = false) =
|
||||
if typ == nil or (sfGeneratedOp in tracked.owner.flags and not explicit):
|
||||
# don't create type bound ops for anything in a function with a `nodestroy` pragma
|
||||
# bug #21987
|
||||
# unless this is an explicit call, bug #24626
|
||||
return
|
||||
when false:
|
||||
let realType = typ.skipTypes(abstractInst)
|
||||
@@ -177,6 +178,7 @@ proc varDecl(a: PEffects; n: PNode) {.inline.} =
|
||||
proc skipHiddenDeref(n: PNode): PNode {.inline.} =
|
||||
result = if n.kind == nkHiddenDeref: n[0] else: n
|
||||
|
||||
|
||||
proc initVar(a: PEffects, n: PNode; volatileCheck: bool) =
|
||||
let n = skipHiddenDeref(n)
|
||||
if n.kind != nkSym: return
|
||||
@@ -925,10 +927,17 @@ proc trackCall(tracked: PEffects; n: PNode) =
|
||||
# rebind type bounds operations after createTypeBoundOps call
|
||||
let t = n[1].typ.skipTypes({tyAlias, tyVar})
|
||||
if a.sym != getAttachedOp(tracked.graph, t, TTypeAttachedOp(opKind)):
|
||||
createTypeBoundOps(tracked, t, n.info)
|
||||
createTypeBoundOps(tracked, t, n.info, explicit = true)
|
||||
let op = getAttachedOp(tracked.graph, t, TTypeAttachedOp(opKind))
|
||||
if op != nil:
|
||||
n[0].sym = op
|
||||
if TTypeAttachedOp(opKind) == attachedDestructor and
|
||||
op.typ.len == 2 and op.typ.firstParamType.kind != tyVar:
|
||||
if n[1].kind == nkSym and n[1].sym.kind == skParam and
|
||||
n[1].typ.kind == tyVar:
|
||||
n[1] = genDeref(n[1])
|
||||
else:
|
||||
n[1] = skipAddr(n[1])
|
||||
|
||||
if op != nil and op.kind == tyProc:
|
||||
for i in 1..<min(n.safeLen, op.len):
|
||||
@@ -1144,7 +1153,12 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
let last = lastSon(child)
|
||||
track(tracked, last)
|
||||
of nkCaseStmt: trackCase(tracked, n)
|
||||
of nkWhen, nkIfStmt, nkIfExpr: trackIf(tracked, n)
|
||||
of nkWhen: # This should be a "when nimvm" node.
|
||||
let oldState = tracked.init.len
|
||||
track(tracked, n[0][1])
|
||||
tracked.init.setLen(oldState)
|
||||
track(tracked, n[1][0])
|
||||
of nkIfStmt, nkIfExpr: trackIf(tracked, n)
|
||||
of nkBlockStmt, nkBlockExpr: trackBlock(tracked, n[1])
|
||||
of nkWhileStmt:
|
||||
# 'while true' loop?
|
||||
|
||||
@@ -780,6 +780,24 @@ proc makeVarTupleSection(c: PContext, n, a, def: PNode, typ: PType, symkind: TSy
|
||||
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
var b: PNode
|
||||
result = copyNode(n)
|
||||
|
||||
# transform var x, y = 12 into var x = 12; var y = 12
|
||||
# bug #18104; transformation should be finished before templates expansion
|
||||
# TODO: move warnings for tuple here
|
||||
var transformed = copyNode(n)
|
||||
for i in 0..<n.len:
|
||||
var a = n[i]
|
||||
if a.kind == nkIdentDefs and a.len > 3 and a[^1].kind != nkEmpty:
|
||||
for j in 0..<a.len-2:
|
||||
var b = newNodeI(nkIdentDefs, a.info)
|
||||
b.add a[j]
|
||||
b.add a[^2]
|
||||
b.add copyTree(a[^1])
|
||||
transformed.add b
|
||||
else:
|
||||
transformed.add a
|
||||
let n = transformed
|
||||
|
||||
for i in 0..<n.len:
|
||||
var a = n[i]
|
||||
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
|
||||
@@ -1701,6 +1719,17 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
|
||||
# check the style here after the pragmas have been processed:
|
||||
styleCheckDef(c, s)
|
||||
# compute the type's size and check for illegal recursions:
|
||||
if a[0].kind == nkPragmaExpr:
|
||||
let pragmas = a[0][1]
|
||||
for i in 0 ..< pragmas.len:
|
||||
if pragmas[i].kind == nkExprColonExpr and
|
||||
pragmas[i][0].kind == nkIdent and
|
||||
whichKeyword(pragmas[i][0].ident) == wSize:
|
||||
if s.typ.kind != tyEnum and sfImportc notin s.flags:
|
||||
# EventType* {.size: sizeof(uint32).} = enum
|
||||
# AtomicFlag* {.importc: "atomic_flag", header: "<stdatomic.h>", size: 1.} = object
|
||||
localError(c.config, pragmas[i].info, "size pragma only allowed for enum types and imported types")
|
||||
|
||||
if a[1].kind == nkEmpty:
|
||||
var x = a[2]
|
||||
if x.kind in nkCallKinds and nfSem in x.flags:
|
||||
@@ -2253,6 +2282,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
of nkEmpty:
|
||||
s = newSym(kind, c.cache.idAnon, c.idgen, c.getCurrOwner, n.info)
|
||||
s.flags.incl sfUsed
|
||||
s.flags.incl sfGenSym
|
||||
n[namePos] = newSymNode(s)
|
||||
of nkSym:
|
||||
s = n[namePos].sym
|
||||
|
||||
@@ -66,7 +66,12 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
|
||||
# for instance 'nextTry' is both in tables.nim and astalgo.nim ...
|
||||
if not isField or sfGenSym notin s.flags:
|
||||
result = newSymNode(s, info)
|
||||
markUsed(c, info, s)
|
||||
if isField:
|
||||
# possibly not final field sym
|
||||
incl(s.flags, sfUsed)
|
||||
markOwnerModuleAsUsed(c, s)
|
||||
else:
|
||||
markUsed(c, info, s)
|
||||
onUse(info, s)
|
||||
else:
|
||||
result = n
|
||||
|
||||
@@ -228,6 +228,22 @@ proc isRecursiveType(t: PType, cycleDetector: var IntSet): bool =
|
||||
else:
|
||||
return false
|
||||
|
||||
proc annotateClosureConv(n: PNode) =
|
||||
case n.kind
|
||||
of {nkNone..nkNilLit}:
|
||||
discard
|
||||
of nkTupleConstr:
|
||||
if n.typ.kind == tyProc and n.typ.callConv == ccClosure and
|
||||
n[0].typ.kind == tyProc and n[0].typ.callConv != ccClosure:
|
||||
# restores `transf.generateThunk`
|
||||
n[0] = newTreeIT(nkHiddenSubConv, n[0].info, n.typ,
|
||||
newNodeI(nkEmpty, n[0].info), n[0])
|
||||
n.transitionSonsKind(nkClosure)
|
||||
n.flags.incl nfTransf
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
annotateClosureConv(n[i])
|
||||
|
||||
proc fitDefaultNode(c: PContext, n: PNode): PType =
|
||||
inc c.inStaticContext
|
||||
let expectedType = if n[^2].kind != nkEmpty: semTypeNode(c, n[^2], nil) else: nil
|
||||
@@ -243,6 +259,7 @@ proc fitDefaultNode(c: PContext, n: PNode): PType =
|
||||
# `changeType` to infer types for constant values
|
||||
# that's also the reason why we don't use `semExpr` to check
|
||||
# the type since two overlapping error messages might be produced
|
||||
annotateClosureConv(n)
|
||||
result = n[^1].typ
|
||||
else:
|
||||
result = n[^1].typ
|
||||
|
||||
@@ -578,6 +578,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||
result.kind = tyUserTypeClassInst
|
||||
|
||||
of tyGenericBody:
|
||||
if cl.allowMetaTypes: return
|
||||
localError(
|
||||
cl.c.config,
|
||||
cl.info,
|
||||
@@ -651,7 +652,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||
|
||||
for i in 0..<result.len:
|
||||
if result[i] != nil:
|
||||
if result[i].kind == tyGenericBody:
|
||||
if result[i].kind == tyGenericBody and not cl.allowMetaTypes:
|
||||
localError(cl.c.config, if t.sym != nil: t.sym.info else: cl.info,
|
||||
"cannot instantiate '" &
|
||||
typeToString(result[i], preferDesc) &
|
||||
|
||||
@@ -379,6 +379,7 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
|
||||
else: result = t
|
||||
of tyGenericParam, tyAnything, tyConcept:
|
||||
result = t
|
||||
if c.isNoCall: return
|
||||
while true:
|
||||
result = PType(idTableGet(c.bindings, t))
|
||||
if result == nil:
|
||||
@@ -1220,10 +1221,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
|
||||
of tyFromExpr:
|
||||
if c.c.inGenericContext > 0:
|
||||
# generic type bodies can sometimes compile call expressions
|
||||
# prevent expressions with unresolved types from
|
||||
# being passed as parameters
|
||||
return isNone
|
||||
if not c.isNoCall:
|
||||
# generic type bodies can sometimes compile call expressions
|
||||
# prevent expressions with unresolved types from
|
||||
# being passed as parameters
|
||||
return isNone
|
||||
else:
|
||||
# Foo[templateCall(T)] shouldn't fail early if Foo has a constraint
|
||||
# and we can't evaluate `templateCall(T)` yet
|
||||
return isGeneric
|
||||
else: discard
|
||||
case f.kind
|
||||
of tyEnum:
|
||||
@@ -1743,9 +1749,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
let target = f[0]
|
||||
let targetKind = target.kind
|
||||
var effectiveArgType = reduceToBase(a)
|
||||
# the skipped child of tyBuiltInTypeClass can be structured differently,
|
||||
# newConstraint constructs them with no children
|
||||
let typeClassArg = effectiveArgType.kind == tyBuiltInTypeClass
|
||||
effectiveArgType = effectiveArgType.skipTypes({tyBuiltInTypeClass})
|
||||
if targetKind == effectiveArgType.kind:
|
||||
if effectiveArgType.isEmptyContainer:
|
||||
if not typeClassArg and effectiveArgType.isEmptyContainer:
|
||||
return isNone
|
||||
if targetKind == tyProc:
|
||||
if target.flags * {tfIterator} != effectiveArgType.flags * {tfIterator}:
|
||||
|
||||
@@ -107,6 +107,13 @@ proc transformSons(c: PTransf, n: PNode, noConstFold = false): PNode =
|
||||
for i in 0..<n.len:
|
||||
result[i] = transform(c, n[i], noConstFold)
|
||||
|
||||
proc transformSonsAfterType(c: PTransf, n: PNode, noConstFold = false): PNode =
|
||||
result = newTransNode(n)
|
||||
assert n.len != 0
|
||||
result[0] = copyTree(n[0])
|
||||
for i in 1..<n.len:
|
||||
result[i] = transform(c, n[i], noConstFold)
|
||||
|
||||
proc newAsgnStmt(c: PTransf, kind: TNodeKind, le: PNode, ri: PNode; isFirstWrite: bool): PNode =
|
||||
result = newTransNode(kind, ri.info, 2)
|
||||
result[0] = le
|
||||
@@ -497,7 +504,17 @@ proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds, isAddr = false)
|
||||
elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
|
||||
result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
|
||||
else:
|
||||
if n[0].kind in kinds:
|
||||
if n[0].kind in kinds and
|
||||
not (n[0][0].kind == nkSym and n[0][0].sym.kind == skForVar and
|
||||
n[0][0].typ.skipTypes(abstractVar).kind == tyTuple
|
||||
) and not (n[0][0].kind == nkSym and n[0][0].sym.kind == skParam and
|
||||
n.typ.kind == tyVar and
|
||||
n.typ.skipTypes(abstractVar).kind == tyOpenArray and
|
||||
n[0][0].typ.skipTypes(abstractVar).kind == tyString) and
|
||||
not (isAddr and n.typ.kind == tyVar and n[0][0].typ.kind == tyRef and
|
||||
n[0][0].kind == nkObjConstr)
|
||||
: # elimination is harmful to `for tuple unpack` because of newTupleAccess
|
||||
# it is also harmful to openArrayLoc (var openArray) for strings
|
||||
# addr ( deref ( x )) --> x
|
||||
result = n[0][0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
@@ -825,9 +842,18 @@ proc transformArrayAccess(c: PTransf, n: PNode): PNode =
|
||||
if n[0].kind == nkSym and n[0].sym.kind == skType:
|
||||
result = n
|
||||
else:
|
||||
result = newTransNode(n)
|
||||
for i in 0..<n.len:
|
||||
result[i] = transform(c, skipConv(n[i]))
|
||||
result = transformSons(c, n)
|
||||
if n.len >= 2 and result[1].kind in {nkChckRange, nkChckRange64} and
|
||||
n[1].kind in {nkHiddenStdConv, nkHiddenSubConv}:
|
||||
# implicit conversion, was transformed into range check
|
||||
# remove in favor of index check if conversion to array index type
|
||||
# has to be done here because the array index type needs to be relaxed
|
||||
# i.e. a uint32 index can implicitly convert to range[0..3] but not int
|
||||
let arr = skipTypes(n[0].typ, abstractVarRange)
|
||||
if arr.kind == tyArray and
|
||||
firstOrd(c.graph.config, arr) == getOrdValue(result[1][1]) and
|
||||
lastOrd(c.graph.config, arr) == getOrdValue(result[1][2]):
|
||||
result[1] = result[1].skipConv
|
||||
|
||||
proc getMergeOp(n: PNode): PSym =
|
||||
case n.kind
|
||||
@@ -1035,9 +1061,7 @@ proc transform(c: PTransf, n: PNode, noConstFold = false): PNode =
|
||||
of nkBreakStmt: result = transformBreak(c, n)
|
||||
of nkCallKinds:
|
||||
result = transformCall(c, n)
|
||||
of nkHiddenAddr:
|
||||
result = transformAddrDeref(c, n, {nkHiddenDeref}, isAddr = true)
|
||||
of nkAddr:
|
||||
of nkAddr, nkHiddenAddr:
|
||||
result = transformAddrDeref(c, n, {nkDerefExpr, nkHiddenDeref}, isAddr = true)
|
||||
of nkDerefExpr:
|
||||
result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
|
||||
@@ -1050,6 +1074,9 @@ proc transform(c: PTransf, n: PNode, noConstFold = false): PNode =
|
||||
result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
result = transformConv(c, n)
|
||||
of nkObjConstr, nkCast:
|
||||
# don't try to transform type node
|
||||
result = transformSonsAfterType(c, n)
|
||||
of nkDiscardStmt:
|
||||
result = n
|
||||
if n[0].kind != nkEmpty:
|
||||
|
||||
@@ -213,8 +213,7 @@ 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 != cnst.kind and
|
||||
cnst.kind in {nkCurly, nkPar, nkTupleConstr, nkBracket, nkObjConstr} and
|
||||
result = cnst.kind in {nkCurly, nkPar, nkTupleConstr, nkBracket, nkObjConstr} and
|
||||
cnst.len > ord(cnst.kind == nkObjConstr)
|
||||
|
||||
proc isRunnableExamples*(n: PNode): bool =
|
||||
|
||||
@@ -1226,16 +1226,16 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||
b = skipTypes(b[^1], {tyAlias})
|
||||
assert(a != nil)
|
||||
assert(b != nil)
|
||||
if a.kind != b.kind:
|
||||
case c.cmp
|
||||
of dcEq: return false
|
||||
of dcEqIgnoreDistinct:
|
||||
a = a.skipTypes({tyDistinct, tyGenericInst})
|
||||
b = b.skipTypes({tyDistinct, tyGenericInst})
|
||||
if a.kind != b.kind: return false
|
||||
of dcEqOrDistinctOf:
|
||||
a = a.skipTypes({tyDistinct, tyGenericInst})
|
||||
if a.kind != b.kind: return false
|
||||
case c.cmp
|
||||
of dcEq:
|
||||
if a.kind != b.kind: return false
|
||||
of dcEqIgnoreDistinct:
|
||||
a = a.skipTypes({tyDistinct, tyGenericInst})
|
||||
b = b.skipTypes({tyDistinct, tyGenericInst})
|
||||
if a.kind != b.kind: return false
|
||||
of dcEqOrDistinctOf:
|
||||
a = a.skipTypes({tyDistinct, tyGenericInst})
|
||||
if a.kind != b.kind: return false
|
||||
|
||||
#[
|
||||
The following code should not run in the case either side is an generic alias,
|
||||
@@ -1243,11 +1243,12 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||
objects ie `type A[T] = SomeObject`
|
||||
]#
|
||||
# this is required by tunique_type but makes no sense really:
|
||||
if tyDistinct notin {x.kind, y.kind} and x.kind == tyGenericInst and IgnoreTupleFields notin c.flags:
|
||||
if c.cmp == dcEq and x.kind == tyGenericInst and
|
||||
IgnoreTupleFields notin c.flags and tyDistinct != y.kind:
|
||||
let
|
||||
lhs = x.skipGenericAlias
|
||||
rhs = y.skipGenericAlias
|
||||
if rhs.kind != tyGenericInst or lhs.base != rhs.base:
|
||||
if rhs.kind != tyGenericInst or lhs.base != rhs.base or rhs.kidsLen != lhs.kidsLen:
|
||||
return false
|
||||
for i in 1..<lhs.len - 1:
|
||||
let ff = rhs[i]
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
import semmacrosanity
|
||||
import
|
||||
std/[strutils, tables, parseutils],
|
||||
std/[strutils, tables, intsets, parseutils],
|
||||
msgs, vmdef, vmgen, nimsets, types,
|
||||
parser, vmdeps, idents, trees, renderer, options, transf,
|
||||
gorgeimpl, lineinfos, btrees, macrocacheimpl,
|
||||
@@ -1837,7 +1837,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen)
|
||||
else:
|
||||
stackTrace(c, tos, pc, "node has no type")
|
||||
else:
|
||||
of 3:
|
||||
# getTypeImpl opcode:
|
||||
ensureKind(rkNode)
|
||||
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
||||
@@ -1846,6 +1846,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen)
|
||||
else:
|
||||
stackTrace(c, tos, pc, "node has no type")
|
||||
else:
|
||||
# getTypeInstSkipAlias opcode:
|
||||
ensureKind(rkNode)
|
||||
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
||||
regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.typ, c.debug[pc], c.idgen, skipAlias = true)
|
||||
elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
|
||||
regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen, skipAlias = true)
|
||||
else:
|
||||
stackTrace(c, tos, pc, "node has no type")
|
||||
of opcNGetSize:
|
||||
decodeBImm(rkInt)
|
||||
let n = regs[rb].node
|
||||
@@ -2375,8 +2384,11 @@ proc evalConstExprAux(module: PSym; idgen: IdGenerator;
|
||||
setupGlobalCtx(module, g, idgen)
|
||||
var c = PCtx g.vm
|
||||
let oldMode = c.mode
|
||||
let oldLocals = c.locals
|
||||
c.mode = mode
|
||||
c.locals = initIntSet()
|
||||
let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
|
||||
c.locals = oldLocals
|
||||
if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info)
|
||||
assert c.code[start].opcode != opcEof
|
||||
when debugEchoCode: c.echoCode start
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
## This module contains the type definitions for the new evaluation engine.
|
||||
## An instruction is 1-3 int32s in memory, it is a register based VM.
|
||||
|
||||
import std/[tables, strutils]
|
||||
import std/[tables, strutils, intsets]
|
||||
|
||||
import ast, idents, options, modulegraphs, lineinfos
|
||||
|
||||
@@ -270,6 +270,7 @@ type
|
||||
templInstCounter*: ref int # gives every template instantiation a unique ID, needed here for getAst
|
||||
vmstateDiff*: seq[(PSym, PNode)] # we remember the "diff" to global state here (feature for IC)
|
||||
procToCodePos*: Table[int, int]
|
||||
locals*: IntSet
|
||||
|
||||
PStackFrame* = ref TStackFrame
|
||||
TStackFrame* {.acyclic.} = object
|
||||
|
||||
@@ -40,7 +40,7 @@ proc atomicTypeX(s: PSym; info: TLineInfo): PNode =
|
||||
result.info = info
|
||||
|
||||
proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator;
|
||||
inst=false; allowRecursionX=false): PNode
|
||||
inst=false; allowRecursionX=false; skipAlias = false): PNode
|
||||
|
||||
proc mapTypeToBracketX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo;
|
||||
idgen: IdGenerator;
|
||||
@@ -68,7 +68,7 @@ proc objectNode(cache: IdentCache; n: PNode; idgen: IdGenerator): PNode =
|
||||
|
||||
proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
idgen: IdGenerator;
|
||||
inst=false; allowRecursionX=false): PNode =
|
||||
inst=false; allowRecursionX=false; skipAlias = false): PNode =
|
||||
var allowRecursion = allowRecursionX
|
||||
template atomicType(name, m): untyped = atomicTypeX(cache, name, m, t, info, idgen)
|
||||
template atomicType(s): untyped = atomicTypeX(s, info)
|
||||
@@ -89,7 +89,8 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
id
|
||||
template newIdentDefs(s): untyped = newIdentDefs(s, s.typ)
|
||||
|
||||
if inst and not allowRecursion and t.sym != nil:
|
||||
if inst and not allowRecursion and t.sym != nil and
|
||||
not (skipAlias and t.kind == tyAlias):
|
||||
# getTypeInst behavior: return symbol
|
||||
return atomicType(t.sym)
|
||||
|
||||
@@ -122,7 +123,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
if t.base != nil:
|
||||
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
||||
result.add atomicType("typeDesc", mTypeDesc)
|
||||
result.add mapTypeToAst(t.base, info)
|
||||
result.add mapTypeToAstX(cache, t.base, info, idgen, inst, skipAlias = skipAlias)
|
||||
else:
|
||||
result = atomicType("typeDesc", mTypeDesc)
|
||||
of tyGenericInvocation:
|
||||
@@ -151,7 +152,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
else:
|
||||
result = mapTypeToAst(t.lastSon, info)
|
||||
of tyAlias:
|
||||
result = mapTypeToAstX(cache, t.lastSon, info, idgen, inst, allowRecursion)
|
||||
result = mapTypeToAstX(cache, t.lastSon, info, idgen, inst, allowRecursion, skipAlias = skipAlias)
|
||||
of tyOrdinal:
|
||||
result = mapTypeToAst(t.lastSon, info)
|
||||
of tyDistinct:
|
||||
@@ -316,8 +317,9 @@ proc opMapTypeToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGene
|
||||
|
||||
# the "Inst" version includes generic parameters in the resulting type tree
|
||||
# and also tries to look like the corresponding Nim type declaration
|
||||
proc opMapTypeInstToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator): PNode =
|
||||
result = mapTypeToAstX(cache, t, info, idgen, inst=true, allowRecursionX=false)
|
||||
proc opMapTypeInstToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator; skipAlias = false): PNode =
|
||||
# skipAlias: skips aliases and typedesc
|
||||
result = mapTypeToAstX(cache, t, info, idgen, inst=true, allowRecursionX=false, skipAlias = skipAlias)
|
||||
|
||||
# the "Impl" version includes generic parameters in the resulting type tree
|
||||
# and also tries to look like the corresponding Nim type implementation
|
||||
|
||||
@@ -698,6 +698,9 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
||||
let dest = c.genx(le, {gfNodeAddr})
|
||||
c.gABC(le, opcWrDeref, dest, 0, value)
|
||||
c.freeTemp(dest)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
if sameBackendType(le.typ, le[1].typ):
|
||||
genAsgnPatch(c, le[1], value)
|
||||
else:
|
||||
discard
|
||||
|
||||
@@ -866,7 +869,7 @@ proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
|
||||
genBinaryABC(c, n, dest, opc)
|
||||
c.genNarrow(n, dest)
|
||||
|
||||
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
|
||||
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest, flags: TGenFlags = {}; opc=opcConv) =
|
||||
let t2 = n.typ.skipTypes({tyDistinct})
|
||||
let targ2 = arg.typ.skipTypes({tyDistinct})
|
||||
|
||||
@@ -878,7 +881,7 @@ proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
|
||||
return true
|
||||
|
||||
if implicitConv():
|
||||
gen(c, arg, dest)
|
||||
gen(c, arg, dest, flags)
|
||||
return
|
||||
|
||||
let tmp = c.genx(arg)
|
||||
@@ -1040,7 +1043,7 @@ proc whichAsgnOpc(n: PNode; requiresCopy = true): TOpcode =
|
||||
else:
|
||||
(if requiresCopy: opcAsgnComplex else: opcFastAsgnComplex)
|
||||
|
||||
proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMagic) =
|
||||
case m
|
||||
of mAnd: c.genAndOr(n, opcFJmp, dest)
|
||||
of mOr: c.genAndOr(n, opcTJmp, dest)
|
||||
@@ -1179,7 +1182,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and size < 8):
|
||||
c.gABC(n, opcNarrowU, dest, TRegister(size*8))
|
||||
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
|
||||
genConv(c, n, n[1], dest)
|
||||
genConv(c, n, n[1], dest, flags)
|
||||
of mEqStr: genBinaryABC(c, n, dest, opcEqStr)
|
||||
of mEqCString: genBinaryABC(c, n, dest, opcEqCString)
|
||||
of mLeStr: genBinaryABC(c, n, dest, opcLeStr)
|
||||
@@ -1321,7 +1324,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
of "getType": 0
|
||||
of "typeKind": 1
|
||||
of "getTypeInst": 2
|
||||
else: 3 # "getTypeImpl"
|
||||
of "getTypeImpl": 3 # "getTypeImpl"
|
||||
else: 4 # getTypeInstSkipAlias
|
||||
c.gABC(n, opcNGetType, dest, tmp, rc)
|
||||
c.freeTemp(tmp)
|
||||
#genUnaryABC(c, n, dest, opcNGetType)
|
||||
@@ -1556,6 +1560,7 @@ proc checkCanEval(c: PCtx; n: PNode) =
|
||||
# are in the right scope:
|
||||
if sfGenSym in s.flags and c.prc.sym == nil: discard
|
||||
elif s.kind == skParam and s.typ.kind == tyTypeDesc: discard
|
||||
elif s.kind in {skVar, skLet} and s.id in c.locals: discard
|
||||
else: cannotEval(c, n)
|
||||
elif s.kind in {skProc, skFunc, skConverter, skMethod,
|
||||
skIterator} and sfForward in s.flags:
|
||||
@@ -1645,6 +1650,9 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||
c.freeTemp(cc)
|
||||
else:
|
||||
gen(c, ri, dest)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
if sameBackendType(le.typ, le[1].typ):
|
||||
genAsgn(c, le[1], ri, requiresCopy)
|
||||
else:
|
||||
let dest = c.genx(le, {gfNodeAddr})
|
||||
genAsgn(c, dest, ri, requiresCopy)
|
||||
@@ -1942,7 +1950,7 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||
c.gen(lowerTupleUnpacking(c.graph, a, c.idgen, c.getOwner))
|
||||
elif a[0].kind == nkSym:
|
||||
let s = a[0].sym
|
||||
checkCanEval(c, a[0])
|
||||
c.locals.incl(s.id)
|
||||
if s.isGlobal:
|
||||
let runtimeAccessToCompileTime = c.mode == emRepl and
|
||||
sfCompileTime in s.flags and s.position > 0
|
||||
@@ -2007,7 +2015,7 @@ proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
c.gABx(n, opcLdNull, dest, c.genType(n.typ))
|
||||
|
||||
let intType = getSysType(c.graph, n.info, tyInt)
|
||||
let seqType = n.typ.skipTypes(abstractVar-{tyTypeDesc})
|
||||
let seqType = n.typ.skipTypes(abstractVar+{tyStatic}-{tyTypeDesc})
|
||||
if seqType.kind == tySequence:
|
||||
var tmp = c.getTemp(intType)
|
||||
c.gABx(n, opcLdImmInt, tmp, n.len)
|
||||
@@ -2155,7 +2163,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
if n[0].kind == nkSym:
|
||||
let s = n[0].sym
|
||||
if s.magic != mNone:
|
||||
genMagic(c, n, dest, s.magic)
|
||||
genMagic(c, n, dest, flags, s.magic)
|
||||
elif s.kind == skMethod:
|
||||
localError(c.config, n.info, "cannot call method " & s.name.s &
|
||||
" at compile time")
|
||||
@@ -2212,11 +2220,11 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
unused(c, n, dest)
|
||||
gen(c, n[0])
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
genConv(c, n, n[1], dest)
|
||||
genConv(c, n, n[1], dest, flags)
|
||||
of nkObjDownConv:
|
||||
genConv(c, n, n[0], dest)
|
||||
genConv(c, n, n[0], dest, flags)
|
||||
of nkObjUpConv:
|
||||
genConv(c, n, n[0], dest)
|
||||
genConv(c, n, n[0], dest, flags)
|
||||
of nkVarSection, nkLetSection:
|
||||
unused(c, n, dest)
|
||||
genVarSection(c, n)
|
||||
@@ -2249,7 +2257,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
of nkPar, nkClosure, nkTupleConstr: genTupleConstr(c, n, dest)
|
||||
of nkCast:
|
||||
if allowCast in c.features:
|
||||
genConv(c, n, n[1], dest, opcCast)
|
||||
genConv(c, n, n[1], dest, flags, opcCast)
|
||||
else:
|
||||
genCastIntFloat(c, n, dest)
|
||||
of nkTypeOfExpr:
|
||||
|
||||
@@ -5096,22 +5096,22 @@ caught by reference. Example:
|
||||
proc fn() =
|
||||
let a = initRuntimeError("foo")
|
||||
doAssert $a.what == "foo"
|
||||
var b: cstring
|
||||
var b = ""
|
||||
try: raise initRuntimeError("foo2")
|
||||
except CStdException as e:
|
||||
doAssert e is CStdException
|
||||
b = e.what()
|
||||
doAssert $b == "foo2"
|
||||
b = $e.what()
|
||||
doAssert b == "foo2"
|
||||
|
||||
try: raise initStdException()
|
||||
except CStdException: discard
|
||||
|
||||
try: raise initRuntimeError("foo3")
|
||||
except CRuntimeError as e:
|
||||
b = e.what()
|
||||
b = $e.what()
|
||||
except CStdException:
|
||||
doAssert false
|
||||
doAssert $b == "foo3"
|
||||
doAssert b == "foo3"
|
||||
|
||||
fn()
|
||||
```
|
||||
|
||||
17
koch.nim
17
koch.nim
@@ -11,13 +11,13 @@
|
||||
|
||||
const
|
||||
# examples of possible values for repos: Head, ea82b54
|
||||
NimbleStableCommit = "46e2ae13eeb95619a371a74d16efc5aff30ea371" # 0.16.2
|
||||
NimbleStableCommit = "6a2486b597132340ea7422b078c769b58f21d16d" # 0.20.0
|
||||
AtlasStableCommit = "5faec3e9a33afe99a7d22377dd1b45a5391f5504"
|
||||
ChecksumsStableCommit = "bd9bf4eaea124bf8d01e08f92ac1b14c6879d8d3"
|
||||
ChecksumsStableCommit = "f8f6bd34bfa3fe12c64b919059ad856a96efcba0" # 2.0.1
|
||||
SatStableCommit = "faf1617f44d7632ee9601ebc13887644925dcc01"
|
||||
|
||||
# examples of possible values for fusion: #head, #ea82b54, 1.2.3
|
||||
FusionStableHash = "#372ee4313827ef9f2ea388840f7d6b46c2b1b014"
|
||||
FusionStableHash = "#562467452b32cb7a97410ea177f083e6d8405734"
|
||||
HeadHash = "#head"
|
||||
when not defined(windows):
|
||||
const
|
||||
@@ -156,13 +156,12 @@ proc bundleNimbleExe(latest: bool, args: string) =
|
||||
let commit = if latest: "HEAD" else: NimbleStableCommit
|
||||
cloneDependency(distDir, "https://github.com/nim-lang/nimble.git",
|
||||
commit = commit, allowBundled = true)
|
||||
cloneDependency(distDir / "nimble" / distDir, "https://github.com/nim-lang/checksums.git",
|
||||
commit = ChecksumsStableCommit, allowBundled = true) # or copy it from dist?
|
||||
cloneDependency(distDir / "nimble" / distDir, "https://github.com/nim-lang/sat.git",
|
||||
commit = SatStableCommit, allowBundled = true)
|
||||
# installer.ini expects it under $nim/bin
|
||||
updateSubmodules(distDir / "nimble", allowBundled = true)
|
||||
nimCompile("dist/nimble/src/nimble.nim",
|
||||
options = "-d:release -d:nimNimbleBootstrap --mm:refc --noNimblePath " & args)
|
||||
options = "-d:release --mm:refc --noNimblePath " & args)
|
||||
const zippyTests = "dist/nimble/vendor/zippy/tests"
|
||||
if dirExists(zippyTests):
|
||||
removeDir(zippyTests)
|
||||
|
||||
proc bundleAtlasExe(latest: bool, args: string) =
|
||||
let commit = if latest: "HEAD" else: AtlasStableCommit
|
||||
|
||||
@@ -1574,10 +1574,13 @@ proc extractTypeImpl(n: NimNode): NimNode =
|
||||
result = n[2]
|
||||
else: error("Invalid node to retrieve type implementation of: " & $n.kind)
|
||||
|
||||
|
||||
proc getTypeInstSkipAlias(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
|
||||
|
||||
proc customPragmaNode(n: NimNode): NimNode =
|
||||
expectKind(n, {nnkSym, nnkDotExpr, nnkBracketExpr, nnkTypeOfExpr, nnkType, nnkCheckedFieldExpr})
|
||||
let
|
||||
typ = n.getTypeInst()
|
||||
|
||||
let typ = n.getTypeInstSkipAlias()
|
||||
|
||||
if typ.kind == nnkBracketExpr and typ.len > 1 and typ[1].kind == nnkProcTy:
|
||||
return typ[1][1]
|
||||
|
||||
@@ -215,6 +215,11 @@ when defined(osx): # 2001 POSIX evidently does not concern Apple
|
||||
# present size & has no good reason to call this unless it is growing.
|
||||
if fcntl(a1, F_PREALLOCATE, fst.addr) != cint(-1): ftruncate(a1, a2 + a3)
|
||||
else: cint(-1)
|
||||
elif defined(openbsd):
|
||||
proc posix_fallocate*(a1: cint, a2, a3: Off): cint =
|
||||
# above assumption: "has no good reason to call this unless it is growing."
|
||||
# man ftruncate "it will be extended as if by writing bytes with the value zero."
|
||||
return ftruncate(a1, a2 + a3)
|
||||
else:
|
||||
proc posix_fallocate*(a1: cint, a2, a3: Off): cint {.
|
||||
importc, header: "<fcntl.h>".}
|
||||
@@ -503,7 +508,7 @@ proc pthread_spin_unlock*(a1: ptr Pthread_spinlock): cint {.
|
||||
proc pthread_testcancel*() {.importc, header: "<pthread.h>".}
|
||||
|
||||
|
||||
proc exitnow*(code: int) {.importc: "_exit", header: "<unistd.h>".}
|
||||
proc exitnow*(code: cint) {.importc: "_exit", header: "<unistd.h>", noreturn.}
|
||||
proc access*(a1: cstring, a2: cint): cint {.importc, header: "<unistd.h>".}
|
||||
proc alarm*(a1: cint): cint {.importc, header: "<unistd.h>".}
|
||||
proc chdir*(a1: cstring): cint {.importc, header: "<unistd.h>".}
|
||||
@@ -1095,7 +1100,21 @@ proc setprotoent*(a1: cint) {.importc, header: "<netdb.h>".}
|
||||
proc setservent*(a1: cint) {.importc, header: "<netdb.h>".}
|
||||
|
||||
when not defined(lwip):
|
||||
proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: int): cint {.
|
||||
# Linux and Haiku emulate SVR4, which used unsigned long.
|
||||
# Meanwhile, BSD derivatives had used unsigned int; we will use this
|
||||
# for the else case, because it is more widely cloned than SVR4's
|
||||
# behavior.
|
||||
when defined(linux) or defined(haiku):
|
||||
type
|
||||
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
|
||||
elif defined(zephyr):
|
||||
type
|
||||
Tnfds* = distinct cint
|
||||
else:
|
||||
type
|
||||
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cuint
|
||||
|
||||
proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: cint): cint {.
|
||||
importc, header: "<poll.h>", sideEffect.}
|
||||
|
||||
proc realpath*(name, resolved: cstring): cstring {.
|
||||
|
||||
@@ -519,8 +519,6 @@ type
|
||||
events*: cshort ## The input event flags (see below).
|
||||
revents*: cshort ## The output event flags (see below).
|
||||
|
||||
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
|
||||
|
||||
var
|
||||
errno* {.importc, header: "<errno.h>".}: cint ## error variable
|
||||
h_errno* {.importc, header: "<netdb.h>".}: cint
|
||||
|
||||
@@ -563,8 +563,6 @@ type
|
||||
events*: cshort ## The input event flags (see below).
|
||||
revents*: cshort ## The output event flags (see below).
|
||||
|
||||
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
|
||||
|
||||
var
|
||||
errno* {.importc, header: "<errno.h>".}: cint ## error variable
|
||||
h_errno* {.importc, header: "<netdb.h>".}: cint
|
||||
|
||||
@@ -125,7 +125,7 @@ type
|
||||
Dev* {.importc: "dev_t", header: "<sys/types.h>".} = int32
|
||||
Fsblkcnt* {.importc: "fsblkcnt_t", header: "<sys/types.h>".} = int
|
||||
Fsfilcnt* {.importc: "fsfilcnt_t", header: "<sys/types.h>".} = int
|
||||
Gid* {.importc: "gid_t", header: "<sys/types.h>".} = int32
|
||||
Gid* {.importc: "gid_t", header: "<sys/types.h>".} = uint32
|
||||
Id* {.importc: "id_t", header: "<sys/types.h>".} = int
|
||||
Ino* {.importc: "ino_t", header: "<sys/types.h>".} = int
|
||||
Key* {.importc: "key_t", header: "<sys/types.h>".} = int
|
||||
@@ -167,7 +167,7 @@ type
|
||||
Trace_event_set* {.importc: "trace_event_set_t",
|
||||
header: "<sys/types.h>".} = int
|
||||
Trace_id* {.importc: "trace_id_t", header: "<sys/types.h>".} = int
|
||||
Uid* {.importc: "uid_t", header: "<sys/types.h>".} = int32
|
||||
Uid* {.importc: "uid_t", header: "<sys/types.h>".} = uint32
|
||||
Useconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int
|
||||
|
||||
Utsname* {.importc: "struct utsname",
|
||||
@@ -462,9 +462,9 @@ type
|
||||
header: "<netinet/in.h>".} = object ## struct sockaddr_in6
|
||||
sin6_family*: TSa_Family ## AF_INET6.
|
||||
sin6_port*: InPort ## Port number.
|
||||
sin6_flowinfo*: int32 ## IPv6 traffic class and flow information.
|
||||
sin6_flowinfo*: uint32 ## IPv6 traffic class and flow information.
|
||||
sin6_addr*: In6Addr ## IPv6 address.
|
||||
sin6_scope_id*: int32 ## Set of interfaces for a scope.
|
||||
sin6_scope_id*: uint32 ## Set of interfaces for a scope.
|
||||
|
||||
Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final,
|
||||
header: "<netinet/in.h>".} = object ## struct ipv6_mreq
|
||||
@@ -491,7 +491,7 @@ type
|
||||
## alternative network names, terminated by a
|
||||
## null pointer.
|
||||
n_addrtype*: cint ## The address type of the network.
|
||||
n_net*: int32 ## The network number, in host byte order.
|
||||
n_net*: uint32 ## The network number, in host byte order.
|
||||
|
||||
Protoent* {.importc: "struct protoent", pure, final,
|
||||
header: "<netdb.h>".} = object ## struct protoent
|
||||
@@ -529,8 +529,6 @@ type
|
||||
events*: cshort ## The input event flags (see below).
|
||||
revents*: cshort ## The output event flags (see below).
|
||||
|
||||
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
|
||||
|
||||
var
|
||||
errno* {.importc, header: "<errno.h>".}: cint ## error variable
|
||||
h_errno* {.importc, header: "<netdb.h>".}: cint
|
||||
|
||||
@@ -484,8 +484,6 @@ type
|
||||
events*: cshort ## The input event flags (see below).
|
||||
revents*: cshort ## The output event flags (see below).
|
||||
|
||||
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
|
||||
|
||||
var
|
||||
errno* {.importc, header: "<errno.h>".}: cint ## error variable
|
||||
h_errno* {.importc, header: "<netdb.h>".}: cint
|
||||
|
||||
@@ -134,7 +134,7 @@ type
|
||||
Dev* {.importc: "dev_t", header: "<sys/types.h>".} = int32
|
||||
Fsblkcnt* {.importc: "fsblkcnt_t", header: "<sys/types.h>".} = int
|
||||
Fsfilcnt* {.importc: "fsfilcnt_t", header: "<sys/types.h>".} = int
|
||||
Gid* {.importc: "gid_t", header: "<sys/types.h>".} = int32
|
||||
Gid* {.importc: "gid_t", header: "<sys/types.h>".} = uint32
|
||||
Id* {.importc: "id_t", header: "<sys/types.h>".} = int
|
||||
Ino* {.importc: "ino_t", header: "<sys/types.h>".} = int
|
||||
Key* {.importc: "key_t", header: "<sys/types.h>".} = int
|
||||
@@ -171,7 +171,7 @@ type
|
||||
Trace_event_set* {.importc: "trace_event_set_t",
|
||||
header: "<sys/types.h>".} = int
|
||||
Trace_id* {.importc: "trace_id_t", header: "<sys/types.h>".} = int
|
||||
Uid* {.importc: "uid_t", header: "<sys/types.h>".} = int32
|
||||
Uid* {.importc: "uid_t", header: "<sys/types.h>".} = uint32
|
||||
Useconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int
|
||||
|
||||
Utsname* {.importc: "struct utsname",
|
||||
@@ -446,9 +446,9 @@ type
|
||||
header: "<netinet/in.h>".} = object ## struct sockaddr_in6
|
||||
sin6_family*: TSa_Family ## AF_INET6.
|
||||
sin6_port*: InPort ## Port number.
|
||||
sin6_flowinfo*: int32 ## IPv6 traffic class and flow information.
|
||||
sin6_flowinfo*: uint32 ## IPv6 traffic class and flow information.
|
||||
sin6_addr*: In6Addr ## IPv6 address.
|
||||
sin6_scope_id*: int32 ## Set of interfaces for a scope.
|
||||
sin6_scope_id*: uint32 ## Set of interfaces for a scope.
|
||||
|
||||
Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final,
|
||||
header: "<netinet/in.h>".} = object ## struct ipv6_mreq
|
||||
@@ -475,7 +475,7 @@ type
|
||||
## alternative network names, terminated by a
|
||||
## null pointer.
|
||||
n_addrtype*: cint ## The address type of the network.
|
||||
n_net*: int32 ## The network number, in host byte order.
|
||||
n_net*: uint32 ## The network number, in host byte order.
|
||||
|
||||
Protoent* {.importc: "struct protoent", pure, final,
|
||||
header: "<netdb.h>".} = object ## struct protoent
|
||||
@@ -513,8 +513,6 @@ type
|
||||
events*: cshort ## The input event flags (see below).
|
||||
revents*: cshort ## The output event flags (see below).
|
||||
|
||||
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
|
||||
|
||||
var
|
||||
errno* {.importc, header: "<errno.h>".}: cint ## error variable
|
||||
h_errno* {.importc, header: "<netdb.h>".}: cint
|
||||
|
||||
@@ -604,13 +604,6 @@ when not defined(lwip):
|
||||
events*: cshort ## The input event flags (see below).
|
||||
revents*: cshort ## The output event flags (see below).
|
||||
|
||||
when defined(zephyr):
|
||||
type
|
||||
Tnfds* = distinct culong
|
||||
else:
|
||||
type
|
||||
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
|
||||
|
||||
var
|
||||
errno* {.importc, header: "<errno.h>".}: cint ## error variable
|
||||
h_errno* {.importc, header: "<netdb.h>".}: cint
|
||||
|
||||
@@ -231,7 +231,7 @@ proc selectInto*[T](s: Selector[T], timeout: int,
|
||||
verifySelectParams(timeout)
|
||||
|
||||
s.withPollLock():
|
||||
let count = posix.poll(addr(s.pollfds[0]), Tnfds(s.pollcnt), timeout)
|
||||
let count = posix.poll(addr(s.pollfds[0]), Tnfds(s.pollcnt), cint(timeout))
|
||||
if count < 0:
|
||||
result = 0
|
||||
let err = osLastError()
|
||||
|
||||
@@ -211,7 +211,7 @@ when defined(nimHasStyleChecks):
|
||||
when defined(posix) and not defined(lwip):
|
||||
from posix import TPollfd, POLLIN, POLLPRI, POLLOUT, POLLWRBAND, Tnfds
|
||||
|
||||
template monitorPollEvent(x: var SocketHandle, y: cint, timeout: int): int =
|
||||
template monitorPollEvent(x: var SocketHandle, y, timeout: cint): int =
|
||||
var tpollfd: TPollfd
|
||||
tpollfd.fd = cast[cint](x)
|
||||
tpollfd.events = y
|
||||
@@ -222,14 +222,14 @@ proc timeoutRead(fd: var SocketHandle, timeout = 500): int =
|
||||
var fds = @[fd]
|
||||
selectRead(fds, timeout)
|
||||
else:
|
||||
monitorPollEvent(fd, POLLIN or POLLPRI, timeout)
|
||||
monitorPollEvent(fd, POLLIN or POLLPRI, cint(timeout))
|
||||
|
||||
proc timeoutWrite(fd: var SocketHandle, timeout = 500): int =
|
||||
when defined(windows) or defined(lwip):
|
||||
var fds = @[fd]
|
||||
selectWrite(fds, timeout)
|
||||
else:
|
||||
monitorPollEvent(fd, POLLOUT or POLLWRBAND, timeout)
|
||||
monitorPollEvent(fd, POLLOUT or POLLWRBAND, cint(timeout))
|
||||
|
||||
proc socketError*(socket: Socket, err: int = -1, async = false,
|
||||
lastError = (-1).OSErrorCode,
|
||||
@@ -2040,8 +2040,10 @@ proc dial*(address: string, port: Port,
|
||||
if success:
|
||||
result = newSocket(lastFd, domain, sockType, protocol, buffered)
|
||||
elif lastError != 0.OSErrorCode:
|
||||
lastFd.close()
|
||||
raiseOSError(lastError)
|
||||
else:
|
||||
lastFd.close()
|
||||
raise newException(IOError, "Couldn't resolve address: " & address)
|
||||
|
||||
proc connect*(socket: Socket, address: string,
|
||||
|
||||
@@ -514,7 +514,6 @@ proc parseSaturatedNatural*(s: openArray[char], b: var int): int {.
|
||||
proc rawParseUInt(s: openArray[char], b: var BiggestUInt): int =
|
||||
var
|
||||
res = 0.BiggestUInt
|
||||
prev = 0.BiggestUInt
|
||||
i = 0
|
||||
if i < s.len - 1 and s[i] == '-' and s[i + 1] in {'0'..'9'}:
|
||||
integerOutOfRangeError()
|
||||
@@ -522,8 +521,11 @@ proc rawParseUInt(s: openArray[char], b: var BiggestUInt): int =
|
||||
if i < s.len and s[i] in {'0'..'9'}:
|
||||
b = 0
|
||||
while i < s.len and s[i] in {'0'..'9'}:
|
||||
prev = res
|
||||
res = res * 10 + (ord(s[i]) - ord('0')).BiggestUInt
|
||||
if res > BiggestUInt.high div 10: # Highest value that you can multiply 10 without overflow
|
||||
integerOutOfRangeError()
|
||||
res = res * 10
|
||||
let prev = res
|
||||
res += (ord(s[i]) - ord('0')).BiggestUInt
|
||||
if prev > res:
|
||||
integerOutOfRangeError()
|
||||
inc(i)
|
||||
|
||||
@@ -19,9 +19,8 @@ template volatileLoad*[T](src: ptr T): T =
|
||||
when defined(js):
|
||||
src[]
|
||||
else:
|
||||
var res: T
|
||||
{.emit: [res, " = (*(", typeof(src[]), " volatile*)", src, ");"].}
|
||||
res
|
||||
result = default(T)
|
||||
{.emit: [result, " = (*(", typeof(src[]), " volatile*)", src, ");"].}
|
||||
|
||||
template volatileStore*[T](dest: ptr T, val: T) =
|
||||
## Generates a volatile store into the container `dest` of the value
|
||||
|
||||
@@ -25,6 +25,9 @@ export ReadDirEffect, WriteDirEffect
|
||||
type
|
||||
Path* = distinct string
|
||||
|
||||
template `$`*(x: Path): string =
|
||||
string(x)
|
||||
|
||||
func `==`*(x, y: Path): bool {.inline.} =
|
||||
## Compares two paths.
|
||||
##
|
||||
|
||||
@@ -2054,12 +2054,14 @@ when not defined(js):
|
||||
proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] =
|
||||
## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be
|
||||
## of length `len`.
|
||||
if a == nil: return @[]
|
||||
newSeq(result, len)
|
||||
for i in 0..len-1: result[i] = $a[i]
|
||||
|
||||
proc cstringArrayToSeq*(a: cstringArray): seq[string] =
|
||||
## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be
|
||||
## terminated by `nil`.
|
||||
if a == nil: return @[]
|
||||
var L = 0
|
||||
while a[L] != nil: inc(L)
|
||||
result = cstringArrayToSeq(a, L)
|
||||
@@ -2074,7 +2076,7 @@ when not defined(js) and declared(alloc0) and declared(dealloc):
|
||||
let x = cast[ptr UncheckedArray[string]](a)
|
||||
for i in 0 .. a.high:
|
||||
result[i] = cast[cstring](alloc0(x[i].len+1))
|
||||
copyMem(result[i], addr(x[i][0]), x[i].len)
|
||||
copyMem(result[i], x[i].cstring, x[i].len)
|
||||
|
||||
proc deallocCStringArray*(a: cstringArray) =
|
||||
## Frees a NULL terminated cstringArray.
|
||||
|
||||
@@ -14,6 +14,8 @@ at offset 0 then. The ``ref`` object header is independent from the
|
||||
runtime type and only contains a reference count.
|
||||
]#
|
||||
|
||||
{.push raises: [].}
|
||||
|
||||
when defined(gcOrc):
|
||||
const
|
||||
rcIncrement = 0b10000 # so that lowest 4 bits are not touched
|
||||
@@ -72,6 +74,9 @@ else:
|
||||
template count(x: Cell): untyped =
|
||||
x.rc shr rcShift
|
||||
|
||||
when not defined(nimHasQuirky):
|
||||
{.pragma: quirky.}
|
||||
|
||||
proc nimNewObj(size, alignment: int): pointer {.compilerRtl.} =
|
||||
let hdrSize = align(sizeof(RefHeader), alignment)
|
||||
let s = size + hdrSize
|
||||
@@ -173,7 +178,7 @@ proc nimRawDispose(p: pointer, alignment: int) {.compilerRtl.} =
|
||||
template `=dispose`*[T](x: owned(ref T)) = nimRawDispose(cast[pointer](x), T.alignOf)
|
||||
#proc dispose*(x: pointer) = nimRawDispose(x)
|
||||
|
||||
proc nimDestroyAndDispose(p: pointer) {.compilerRtl, raises: [].} =
|
||||
proc nimDestroyAndDispose(p: pointer) {.compilerRtl, quirky, raises: [].} =
|
||||
let rti = cast[ptr PNimTypeV2](p)
|
||||
if rti.destructor != nil:
|
||||
cast[DestructorProc](rti.destructor)(p)
|
||||
@@ -236,3 +241,5 @@ template tearDownForeignThreadGc* =
|
||||
|
||||
proc isObjDisplayCheck(source: PNimTypeV2, targetDepth: int16, token: uint32): bool {.compilerRtl, inl.} =
|
||||
result = targetDepth <= source.depth and source.display[targetDepth] == token
|
||||
|
||||
{.pop.} # raises: []
|
||||
|
||||
@@ -252,12 +252,12 @@ iterator elementsExcept(t, s: CellSet): PCell {.inline.} =
|
||||
var r = t.head
|
||||
while r != nil:
|
||||
let ss = cellSetGet(s, r.key)
|
||||
var i:uint = 0
|
||||
var i = 0'u
|
||||
while int(i) <= high(r.bits):
|
||||
var w = r.bits[i]
|
||||
if ss != nil:
|
||||
w = w and not ss.bits[i]
|
||||
var j:uint = 0
|
||||
var j = 0'u
|
||||
while w != 0:
|
||||
if (w and 1) != 0:
|
||||
yield cast[PCell]((r.key shl PageShift) or
|
||||
|
||||
@@ -10,7 +10,7 @@ const
|
||||
## is the minor number of Nim's version.
|
||||
## Odd for devel, even for releases.
|
||||
|
||||
NimPatch* {.intdefine.}: int = 12
|
||||
NimPatch* {.intdefine.}: int = 17
|
||||
## is the patch number of Nim's version.
|
||||
## Odd for devel, even for releases.
|
||||
|
||||
|
||||
@@ -62,8 +62,8 @@ const
|
||||
colorMask = 0b011
|
||||
|
||||
type
|
||||
TraceProc = proc (p, env: pointer) {.nimcall, benign.}
|
||||
DisposeProc = proc (p: pointer) {.nimcall, benign.}
|
||||
TraceProc = proc (p, env: pointer) {.nimcall, benign, raises: [].}
|
||||
DisposeProc = proc (p: pointer) {.nimcall, benign, raises: [].}
|
||||
|
||||
template color(c): untyped = c.rc and colorMask
|
||||
template setColor(c, col) =
|
||||
|
||||
@@ -13,17 +13,24 @@ when not defined(nimPreviewSlimSystem):
|
||||
## Outplace version of `addFloat`.
|
||||
result.addFloat(x)
|
||||
|
||||
proc `$`*(x: int): string {.raises: [].} =
|
||||
## Outplace version of `addInt`.
|
||||
result.addInt(x)
|
||||
template addIntAlias(T: typedesc) =
|
||||
proc `$`*(x: T): string {.raises: [].} =
|
||||
## Outplace version of `addInt`.
|
||||
result = ""
|
||||
result.addInt(x)
|
||||
|
||||
proc `$`*(x: int64): string {.raises: [].} =
|
||||
## Outplace version of `addInt`.
|
||||
result.addInt(x)
|
||||
# need to declare for bit types as well to not clash with converters:
|
||||
addIntAlias int
|
||||
addIntAlias int8
|
||||
addIntAlias int16
|
||||
addIntAlias int32
|
||||
addIntAlias int64
|
||||
|
||||
proc `$`*(x: uint64): string {.raises: [].} =
|
||||
## Outplace version of `addInt`.
|
||||
addInt(result, x)
|
||||
addIntAlias uint
|
||||
addIntAlias uint8
|
||||
addIntAlias uint16
|
||||
addIntAlias uint32
|
||||
addIntAlias uint64
|
||||
|
||||
# same as old `ctfeWhitelist` behavior, whether or not this is a good idea.
|
||||
template gen(T) =
|
||||
|
||||
@@ -60,6 +60,7 @@ comparisons).
|
||||
]#
|
||||
|
||||
{.push profiler:off.}
|
||||
{.push raises: [].}
|
||||
|
||||
const
|
||||
CycleIncrease = 2 # is a multiplicative increase
|
||||
@@ -595,7 +596,13 @@ proc sweep(gch: var GcHeap) =
|
||||
if isCell(x):
|
||||
# cast to PCell is correct here:
|
||||
var c = cast[PCell](x)
|
||||
if c notin gch.marked: freeCyclicCell(gch, c)
|
||||
if c notin gch.marked:
|
||||
# Don't free objects that have the ZctFlag set (created in finalizers)
|
||||
if (c.refcount and ZctFlag) == 0:
|
||||
freeCyclicCell(gch, c)
|
||||
else:
|
||||
# Clear the ZctFlag for the next collection cycle
|
||||
c.refcount = c.refcount and not ZctFlag
|
||||
|
||||
proc markS(gch: var GcHeap, c: PCell) =
|
||||
gcAssert isAllocatedPtr(gch.region, c), "markS: foreign heap root detected A!"
|
||||
@@ -906,4 +913,5 @@ when not defined(useNimRtl):
|
||||
result.add "[GC] stack bottom: " & gch.stack.bottom.repr
|
||||
result.add "[GC] max stack size: " & $gch.stat.maxStackSize & "\n"
|
||||
|
||||
{.pop.} # raises: []
|
||||
{.pop.} # profiler: off, stackTrace: off
|
||||
|
||||
@@ -25,33 +25,33 @@ when hasAlloc and not defined(js) and not usesDestructors:
|
||||
proc GC_enable*() {.rtl, inl, benign, raises: [].}
|
||||
## Enables the GC again.
|
||||
|
||||
proc GC_fullCollect*() {.rtl, benign.}
|
||||
proc GC_fullCollect*() {.rtl, benign, raises: [].}
|
||||
## Forces a full garbage collection pass.
|
||||
## Ordinary code does not need to call this (and should not).
|
||||
|
||||
proc GC_enableMarkAndSweep*() {.rtl, benign.}
|
||||
proc GC_disableMarkAndSweep*() {.rtl, benign.}
|
||||
proc GC_enableMarkAndSweep*() {.rtl, benign, raises: [].}
|
||||
proc GC_disableMarkAndSweep*() {.rtl, benign, raises: [].}
|
||||
## The current implementation uses a reference counting garbage collector
|
||||
## with a seldomly run mark and sweep phase to free cycles. The mark and
|
||||
## sweep phase may take a long time and is not needed if the application
|
||||
## does not create cycles. Thus the mark and sweep phase can be deactivated
|
||||
## and activated separately from the rest of the GC.
|
||||
|
||||
proc GC_getStatistics*(): string {.rtl, benign.}
|
||||
proc GC_getStatistics*(): string {.rtl, benign, raises: [].}
|
||||
## Returns an informative string about the GC's activity. This may be useful
|
||||
## for tweaking.
|
||||
|
||||
proc GC_ref*[T](x: ref T) {.magic: "GCref", benign.}
|
||||
proc GC_ref*[T](x: seq[T]) {.magic: "GCref", benign.}
|
||||
proc GC_ref*(x: string) {.magic: "GCref", benign.}
|
||||
proc GC_ref*[T](x: ref T) {.magic: "GCref", benign, raises: [].}
|
||||
proc GC_ref*[T](x: seq[T]) {.magic: "GCref", benign, raises: [].}
|
||||
proc GC_ref*(x: string) {.magic: "GCref", benign, raises: [].}
|
||||
## Marks the object `x` as referenced, so that it will not be freed until
|
||||
## it is unmarked via `GC_unref`.
|
||||
## If called n-times for the same object `x`,
|
||||
## n calls to `GC_unref` are needed to unmark `x`.
|
||||
|
||||
proc GC_unref*[T](x: ref T) {.magic: "GCunref", benign.}
|
||||
proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", benign.}
|
||||
proc GC_unref*(x: string) {.magic: "GCunref", benign.}
|
||||
proc GC_unref*[T](x: ref T) {.magic: "GCunref", benign, raises: [].}
|
||||
proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", benign, raises: [].}
|
||||
proc GC_unref*(x: string) {.magic: "GCunref", benign, raises: [].}
|
||||
## See the documentation of `GC_ref <#GC_ref,string>`_.
|
||||
|
||||
proc nimGC_setStackBottom*(theStackBottom: pointer) {.compilerRtl, noinline, benign, raises: [].}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
# R.D. Lins / Information Processing Letters 109 (2008) 71–78
|
||||
#
|
||||
|
||||
{.push raises: [].}
|
||||
|
||||
include cellseqs_v2
|
||||
|
||||
const
|
||||
@@ -27,8 +29,8 @@ const
|
||||
logOrc = defined(nimArcIds)
|
||||
|
||||
type
|
||||
TraceProc = proc (p, env: pointer) {.nimcall, benign.}
|
||||
DisposeProc = proc (p: pointer) {.nimcall, benign.}
|
||||
TraceProc = proc (p, env: pointer) {.nimcall, benign, raises: [].}
|
||||
DisposeProc = proc (p: pointer) {.nimcall, benign, raises: [].}
|
||||
|
||||
template color(c): untyped = c.rc and colorMask
|
||||
template setColor(c, col) =
|
||||
@@ -520,3 +522,5 @@ proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimTypeV2): bool {.compilerR
|
||||
dec cell.rc, rcIncrement
|
||||
#if cell.color == colPurple:
|
||||
rememberCycle(result, cell, desc)
|
||||
|
||||
{.pop.} # raises: []
|
||||
|
||||
@@ -14,21 +14,26 @@ proc rangeBase(T: typedesc): typedesc {.magic: "TypeTrait".}
|
||||
|
||||
proc repr*(x: NimNode): string {.magic: "Repr", noSideEffect.}
|
||||
|
||||
proc repr*(x: int): string =
|
||||
## Same as $x
|
||||
$x
|
||||
template dollarAlias(T: typedesc) =
|
||||
proc repr*(x: T): string {.noSideEffect.} =
|
||||
## Same as $x
|
||||
$x
|
||||
|
||||
proc repr*(x: int64): string =
|
||||
## Same as $x
|
||||
$x
|
||||
# need to declare for bit types as well to not clash with converters:
|
||||
dollarAlias int
|
||||
dollarAlias int8
|
||||
dollarAlias int16
|
||||
dollarAlias int32
|
||||
dollarAlias int64
|
||||
|
||||
proc repr*(x: uint64): string {.noSideEffect.} =
|
||||
## Same as $x
|
||||
$x
|
||||
dollarAlias uint
|
||||
dollarAlias uint8
|
||||
dollarAlias uint16
|
||||
dollarAlias uint32
|
||||
dollarAlias uint64
|
||||
|
||||
proc repr*(x: float): string =
|
||||
## Same as $x
|
||||
$x
|
||||
dollarAlias float
|
||||
dollarAlias float32
|
||||
|
||||
proc repr*(x: bool): string {.magic: "BoolToStr", noSideEffect.}
|
||||
## repr for a boolean argument. Returns `x`
|
||||
|
||||
@@ -166,7 +166,7 @@ proc setLengthStrV2(s: var NimStringV2, newLen: int) {.compilerRtl.} =
|
||||
s.len = newLen
|
||||
|
||||
proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
|
||||
if a.p == b.p: return
|
||||
if a.p == b.p and a.len == b.len: return
|
||||
if isLiteral(b):
|
||||
# we can shallow copy literals:
|
||||
frees(a)
|
||||
|
||||
@@ -61,15 +61,25 @@ elif defined(netbsd):
|
||||
result = threadId
|
||||
|
||||
elif defined(freebsd):
|
||||
proc syscall(arg: cint, arg0: ptr cint): cint {.varargs, importc: "syscall", header: "<unistd.h>".}
|
||||
var SYS_thr_self {.importc:"SYS_thr_self", header:"<sys/syscall.h>".}: cint
|
||||
when defined(amd64) or defined(i386):
|
||||
const SYS_thr_self = 432
|
||||
else:
|
||||
var SYS_thr_self {.importc:"SYS_thr_self", header:"<sys/syscall.h>".}: cint
|
||||
|
||||
when defined(cpu64):
|
||||
type
|
||||
Off {.importc: "off_t", header: "<sys/types.h>".} = int64
|
||||
Quad {.importc: "quad_t", header: "<sys/types.h>".} = int64
|
||||
proc syscall(arg: Quad): Off {.varargs, importc: "__syscall", header: "<unistd.h>".}
|
||||
else:
|
||||
proc syscall(arg: cint): cint {.varargs, importc: "syscall", header: "<unistd.h>".}
|
||||
|
||||
proc getThreadId*(): int =
|
||||
## Gets the ID of the currently running thread.
|
||||
var tid = 0.cint
|
||||
var tid = when defined(cpu64): Off(0) else: cint(0)
|
||||
if threadId == 0:
|
||||
discard syscall(SYS_thr_self, addr tid)
|
||||
threadId = tid
|
||||
threadId = int(tid)
|
||||
result = threadId
|
||||
|
||||
elif defined(macosx):
|
||||
|
||||
@@ -449,14 +449,9 @@ type
|
||||
|
||||
SockLen* = cuint
|
||||
|
||||
when defined(cpp):
|
||||
type
|
||||
Timeval* {.importc: "timeval", header: "<time.h>".} = object
|
||||
tv_sec*, tv_usec*: int32
|
||||
else:
|
||||
type
|
||||
Timeval* = object
|
||||
tv_sec*, tv_usec*: int32
|
||||
type
|
||||
Timeval* {.importc: "struct timeval", header: "<time.h>".} = object
|
||||
tv_sec*, tv_usec*: int32
|
||||
|
||||
var
|
||||
SOMAXCONN* {.importc, header: "winsock2.h".}: cint
|
||||
|
||||
@@ -83,7 +83,7 @@ proc runBasicDLLTest(c, r: var TResults, cat: Category, options: string, isOrc =
|
||||
|
||||
if "boehm" notin options and not isOrc:
|
||||
# hcr tests
|
||||
|
||||
|
||||
testSpec r, makeTest("tests/dll/nimhcr_basic.nim", options & " --threads:off --forceBuild --hotCodeReloading:on " & rpath, cat)
|
||||
|
||||
# force build required - see the comments in the .nim file for more details
|
||||
@@ -162,6 +162,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
|
||||
test "stackrefleak"
|
||||
test "cyclecollector"
|
||||
testWithoutBoehm "trace_globals"
|
||||
test "tfinalizers"
|
||||
|
||||
# ------------------------- threading tests -----------------------------------
|
||||
|
||||
@@ -446,7 +447,7 @@ proc testNimblePackages(r: var TResults; cat: Category; packageFilter: string) =
|
||||
if pkg.allowFailure:
|
||||
inc r.passed
|
||||
inc r.failedButAllowed
|
||||
addResult(r, test, targetC, "", "", cmd & "\n" & outp, reFailed, allowFailure = pkg.allowFailure)
|
||||
discard r.finishTest(test, targetC, "", "", cmd & "\n" & outp, reFailed, allowFailure = pkg.allowFailure)
|
||||
continue
|
||||
outp
|
||||
|
||||
@@ -462,21 +463,21 @@ proc testNimblePackages(r: var TResults; cat: Category; packageFilter: string) =
|
||||
discard tryCommand(cmds[i], maxRetries = 3)
|
||||
discard tryCommand(cmds[^1], reFailed = reBuildFailed)
|
||||
inc r.passed
|
||||
r.addResult(test, targetC, "", "", "", reSuccess, allowFailure = pkg.allowFailure)
|
||||
discard r.finishTest(test, targetC, "", "", "", reSuccess, allowFailure = pkg.allowFailure)
|
||||
|
||||
errors = r.total - r.passed
|
||||
if errors == 0:
|
||||
r.addResult(packageFileTest, targetC, "", "", "", reSuccess)
|
||||
discard r.finishTest(packageFileTest, targetC, "", "", "", reSuccess)
|
||||
else:
|
||||
r.addResult(packageFileTest, targetC, "", "", "", reBuildFailed)
|
||||
discard r.finishTest(packageFileTest, targetC, "", "", "", reBuildFailed)
|
||||
|
||||
except JsonParsingError:
|
||||
errors = 1
|
||||
r.addResult(packageFileTest, targetC, "", "", "Invalid package file", reBuildFailed)
|
||||
discard r.finishTest(packageFileTest, targetC, "", "", "Invalid package file", reBuildFailed)
|
||||
raise
|
||||
except ValueError:
|
||||
errors = 1
|
||||
r.addResult(packageFileTest, targetC, "", "", "Unknown package", reBuildFailed)
|
||||
discard r.finishTest(packageFileTest, targetC, "", "", "Unknown package", reBuildFailed)
|
||||
raise # bug #18805
|
||||
finally:
|
||||
if errors == 0: removeDir(packagesDir)
|
||||
@@ -565,6 +566,7 @@ proc isJoinableSpec(spec: TSpec): bool =
|
||||
spec.err != reDisabled and
|
||||
not spec.unjoinable and
|
||||
spec.exitCode == 0 and
|
||||
spec.retries == 0 and
|
||||
spec.input.len == 0 and
|
||||
spec.nimout.len == 0 and
|
||||
spec.nimoutFull == false and
|
||||
|
||||
@@ -30,12 +30,12 @@ type NimblePackage* = object
|
||||
|
||||
var packages*: seq[NimblePackage]
|
||||
|
||||
proc pkg(name: string; cmd = "nimble test"; url = "", useHead = true, allowFailure = false) =
|
||||
proc pkg(name: string; cmd = "nimble test -l"; url = "", useHead = true, allowFailure = false) =
|
||||
packages.add NimblePackage(name: name, cmd: cmd, url: url, useHead: useHead, allowFailure: allowFailure)
|
||||
|
||||
pkg "alea"
|
||||
pkg "argparse"
|
||||
pkg "arraymancer", "nim c tests/tests_cpu.nim"
|
||||
pkg "arraymancer", "nimble install -y; nimble uninstall -i -y nimcuda; nimble install nimcuda@0.2.1; nim c tests/tests_cpu.nim"
|
||||
pkg "ast_pattern_matching", "nim c -r tests/test1.nim"
|
||||
pkg "asyncftpclient", "nimble compileExample"
|
||||
pkg "asyncthreadpool", "nimble test --mm:refc"
|
||||
@@ -152,7 +152,7 @@ pkg "sim"
|
||||
pkg "smtp", "nimble compileExample"
|
||||
pkg "snip", "nimble test", "https://github.com/genotrance/snip"
|
||||
pkg "stew"
|
||||
pkg "stint", "nim c stint.nim"
|
||||
pkg "stint", "nimble test_internal"
|
||||
pkg "strslice"
|
||||
pkg "strunicode", "nim c -r --mm:refc src/strunicode.nim"
|
||||
pkg "supersnappy"
|
||||
|
||||
@@ -66,6 +66,11 @@ template enableRemoteNetworking*: bool =
|
||||
## a `nim` invocation (possibly via additional intermediate processes).
|
||||
getEnv("NIM_TESTAMENT_REMOTE_NETWORKING") == "1"
|
||||
|
||||
template disableSSLTesting*: bool =
|
||||
## TODO: workaround for GitHub Action gcc 14 matrix; remove this
|
||||
## matrix and the flag after Azure agent supports ubuntu 24.04
|
||||
getEnv("NIM_TESTAMENT_DISABLE_SSL") == "1"
|
||||
|
||||
template whenRuntimeJs*(bodyIf, bodyElse) =
|
||||
##[
|
||||
Behaves as `when defined(js) and not nimvm` (which isn't legal yet).
|
||||
|
||||
@@ -56,6 +56,7 @@ type
|
||||
reJoined, # test is disabled because it was joined into the megatest
|
||||
reSuccess # test was successful
|
||||
reInvalidSpec # test had problems to parse the spec
|
||||
reRetry # test is being retried
|
||||
|
||||
TTarget* = enum
|
||||
targetC = "c"
|
||||
@@ -102,6 +103,7 @@ type
|
||||
# but don't rely on much precision
|
||||
inlineErrors*: seq[InlineError] # line information to error message
|
||||
debugInfo*: string # debug info to give more context
|
||||
retries*: int # number of retry attempts after the test fails
|
||||
|
||||
proc getCmd*(s: TSpec): string =
|
||||
if s.cmd.len == 0:
|
||||
@@ -478,6 +480,8 @@ proc parseSpec*(filename: string): TSpec =
|
||||
result.timeout = parseFloat(e.value)
|
||||
except ValueError:
|
||||
result.parseErrors.addLine "cannot interpret as a float: ", e.value
|
||||
of "retries":
|
||||
discard parseInt(e.value, result.retries)
|
||||
of "targets", "target":
|
||||
try:
|
||||
result.targets.incl parseTargets(e.value)
|
||||
|
||||
@@ -272,16 +272,13 @@ proc testName(test: TTest, target: TTarget, extraOptions: string, allowFailure:
|
||||
name.strip()
|
||||
|
||||
proc addResult(r: var TResults, test: TTest, target: TTarget,
|
||||
extraOptions, expected, given: string, successOrig: TResultEnum,
|
||||
extraOptions, expected, given: string, success: TResultEnum, duration: float,
|
||||
allowFailure = false, givenSpec: ptr TSpec = nil) =
|
||||
# instead of `ptr TSpec` we could also use `Option[TSpec]`; passing `givenSpec` makes it easier to get what we need
|
||||
# instead of having to pass individual fields, or abusing existing ones like expected vs given.
|
||||
# test.name is easier to find than test.name.extractFilename
|
||||
# A bit hacky but simple and works with tests/testament/tshould_not_work.nim
|
||||
let name = testName(test, target, extraOptions, allowFailure)
|
||||
let duration = epochTime() - test.startTime
|
||||
let success = if test.spec.timeout > 0.0 and duration > test.spec.timeout: reTimeout
|
||||
else: successOrig
|
||||
|
||||
let durationStr = duration.formatFloat(ffDecimal, precision = 2).align(5)
|
||||
if backendLogging:
|
||||
@@ -342,6 +339,18 @@ proc addResult(r: var TResults, test: TTest, target: TTarget,
|
||||
discard waitForExit(p)
|
||||
close(p)
|
||||
|
||||
proc finishTest(r: var TResults, test: TTest, target: TTarget,
|
||||
extraOptions, expected, given: string, successOrig: TResultEnum,
|
||||
allowFailure = false, givenSpec: ptr TSpec = nil): bool =
|
||||
result = false
|
||||
let duration = epochTime() - test.startTime
|
||||
let success = if test.spec.timeout > 0.0 and duration > test.spec.timeout: reTimeout
|
||||
else: successOrig
|
||||
if test.spec.retries > 0 and success notin {reSuccess, reDisabled, reJoined, reInvalidSpec}:
|
||||
return true
|
||||
else:
|
||||
addResult(r, test, target, extraOptions, expected, given, success, duration, allowFailure, givenSpec)
|
||||
|
||||
proc toString(inlineError: InlineError, filename: string): string =
|
||||
result.add "$file($line, $col) $kind: $msg" % [
|
||||
"file", filename,
|
||||
@@ -370,23 +379,23 @@ proc nimoutCheck(expected, given: TSpec): bool =
|
||||
result = false
|
||||
|
||||
proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest,
|
||||
target: TTarget, extraOptions: string) =
|
||||
target: TTarget, extraOptions: string): bool =
|
||||
if not checkForInlineErrors(expected, given) or
|
||||
(not expected.nimoutFull and not nimoutCheck(expected, given)):
|
||||
r.addResult(test, target, extraOptions, expected.nimout & inlineErrorsMsgs(expected), given.nimout, reMsgsDiffer)
|
||||
result = r.finishTest(test, target, extraOptions, expected.nimout & inlineErrorsMsgs(expected), given.nimout, reMsgsDiffer)
|
||||
elif strip(expected.msg) notin strip(given.msg):
|
||||
r.addResult(test, target, extraOptions, expected.msg, given.msg, reMsgsDiffer)
|
||||
result = r.finishTest(test, target, extraOptions, expected.msg, given.msg, reMsgsDiffer)
|
||||
elif not nimoutCheck(expected, given):
|
||||
r.addResult(test, target, extraOptions, expected.nimout, given.nimout, reMsgsDiffer)
|
||||
result = r.finishTest(test, target, extraOptions, expected.nimout, given.nimout, reMsgsDiffer)
|
||||
elif extractFilename(expected.file) != extractFilename(given.file) and
|
||||
"internal error:" notin expected.msg:
|
||||
r.addResult(test, target, extraOptions, expected.file, given.file, reFilesDiffer)
|
||||
result = r.finishTest(test, target, extraOptions, expected.file, given.file, reFilesDiffer)
|
||||
elif expected.line != given.line and expected.line != 0 or
|
||||
expected.column != given.column and expected.column != 0:
|
||||
r.addResult(test, target, extraOptions, $expected.line & ':' & $expected.column,
|
||||
result = r.finishTest(test, target, extraOptions, $expected.line & ':' & $expected.column,
|
||||
$given.line & ':' & $given.column, reLinesDiffer)
|
||||
else:
|
||||
r.addResult(test, target, extraOptions, expected.msg, given.msg, reSuccess)
|
||||
result = r.finishTest(test, target, extraOptions, expected.msg, given.msg, reSuccess)
|
||||
inc(r.passed)
|
||||
|
||||
proc generatedFile(test: TTest, target: TTarget): string =
|
||||
@@ -425,7 +434,7 @@ proc codegenCheck(test: TTest, target: TTarget, spec: TSpec, expectedMsg: var st
|
||||
echo getCurrentExceptionMsg()
|
||||
|
||||
proc compilerOutputTests(test: TTest, target: TTarget, extraOptions: string,
|
||||
given: var TSpec, expected: TSpec; r: var TResults) =
|
||||
given: var TSpec, expected: TSpec; r: var TResults): bool =
|
||||
var expectedmsg: string = ""
|
||||
var givenmsg: string = ""
|
||||
if given.err == reSuccess:
|
||||
@@ -440,7 +449,7 @@ proc compilerOutputTests(test: TTest, target: TTarget, extraOptions: string,
|
||||
else:
|
||||
givenmsg = "$ " & given.cmd & '\n' & given.nimout
|
||||
if given.err == reSuccess: inc(r.passed)
|
||||
r.addResult(test, target, extraOptions, expectedmsg, givenmsg, given.err)
|
||||
result = r.finishTest(test, target, extraOptions, expectedmsg, givenmsg, given.err)
|
||||
|
||||
proc getTestSpecTarget(): TTarget =
|
||||
if getEnv("NIM_COMPILE_TO_CPP", "false") == "true":
|
||||
@@ -456,31 +465,38 @@ proc equalModuloLastNewline(a, b: string): bool =
|
||||
|
||||
proc testSpecHelper(r: var TResults, test: var TTest, expected: TSpec,
|
||||
target: TTarget, extraOptions: string, nimcache: string) =
|
||||
test.startTime = epochTime()
|
||||
template maybeRetry(x: bool) =
|
||||
if x:
|
||||
test.spec.err = reRetry
|
||||
dec test.spec.retries
|
||||
testSpecHelper(r, test, expected, target, extraOptions, nimcache)
|
||||
return
|
||||
if test.spec.err != reRetry:
|
||||
test.startTime = epochTime()
|
||||
if testName(test, target, extraOptions, false) in skips:
|
||||
test.spec.err = reDisabled
|
||||
|
||||
if test.spec.err in {reDisabled, reJoined}:
|
||||
r.addResult(test, target, extraOptions, "", "", test.spec.err)
|
||||
discard r.finishTest(test, target, extraOptions, "", "", test.spec.err)
|
||||
inc(r.skipped)
|
||||
return
|
||||
var given = callNimCompiler(expected.getCmd, test.name, test.options, nimcache, target, extraOptions)
|
||||
case expected.action
|
||||
of actionCompile:
|
||||
compilerOutputTests(test, target, extraOptions, given, expected, r)
|
||||
maybeRetry compilerOutputTests(test, target, extraOptions, given, expected, r)
|
||||
of actionRun:
|
||||
if given.err != reSuccess:
|
||||
r.addResult(test, target, extraOptions, "", "$ " & given.cmd & '\n' & given.nimout, given.err, givenSpec = given.addr)
|
||||
maybeRetry r.finishTest(test, target, extraOptions, "", "$ " & given.cmd & '\n' & given.nimout, given.err, givenSpec = given.addr)
|
||||
else:
|
||||
let isJsTarget = target == targetJS
|
||||
var exeFile = changeFileExt(test.name, if isJsTarget: "js" else: ExeExt)
|
||||
if not fileExists(exeFile):
|
||||
r.addResult(test, target, extraOptions, expected.output,
|
||||
maybeRetry r.finishTest(test, target, extraOptions, expected.output,
|
||||
"executable not found: " & exeFile, reExeNotFound)
|
||||
else:
|
||||
let nodejs = if isJsTarget: findNodeJs() else: ""
|
||||
if isJsTarget and nodejs == "":
|
||||
r.addResult(test, target, extraOptions, expected.output, "nodejs binary not in PATH",
|
||||
maybeRetry r.finishTest(test, target, extraOptions, expected.output, "nodejs binary not in PATH",
|
||||
reExeNotFound)
|
||||
else:
|
||||
var exeCmd: string
|
||||
@@ -512,19 +528,19 @@ proc testSpecHelper(r: var TResults, test: var TTest, expected: TSpec,
|
||||
buf
|
||||
if exitCode != expected.exitCode:
|
||||
given.err = reExitcodesDiffer
|
||||
r.addResult(test, target, extraOptions, "exitcode: " & $expected.exitCode,
|
||||
maybeRetry r.finishTest(test, target, extraOptions, "exitcode: " & $expected.exitCode,
|
||||
"exitcode: " & $exitCode & "\n\nOutput:\n" &
|
||||
bufB, reExitcodesDiffer)
|
||||
elif (expected.outputCheck == ocEqual and not expected.output.equalModuloLastNewline(bufB)) or
|
||||
(expected.outputCheck == ocSubstr and expected.output notin bufB):
|
||||
given.err = reOutputsDiffer
|
||||
r.addResult(test, target, extraOptions, expected.output, bufB, reOutputsDiffer)
|
||||
compilerOutputTests(test, target, extraOptions, given, expected, r)
|
||||
maybeRetry r.finishTest(test, target, extraOptions, expected.output, bufB, reOutputsDiffer)
|
||||
maybeRetry compilerOutputTests(test, target, extraOptions, given, expected, r)
|
||||
of actionReject:
|
||||
# Make sure its the compiler rejecting and not the system (e.g. segfault)
|
||||
cmpMsgs(r, expected, given, test, target, extraOptions)
|
||||
maybeRetry cmpMsgs(r, expected, given, test, target, extraOptions)
|
||||
if given.exitCode != QuitFailure:
|
||||
r.addResult(test, target, extraOptions, "exitcode: " & $QuitFailure,
|
||||
maybeRetry r.finishTest(test, target, extraOptions, "exitcode: " & $QuitFailure,
|
||||
"exitcode: " & $given.exitCode & "\n\nOutput:\n" &
|
||||
given.nimout, reExitcodesDiffer)
|
||||
|
||||
@@ -532,7 +548,7 @@ proc targetHelper(r: var TResults, test: TTest, expected: TSpec, extraOptions: s
|
||||
for target in expected.targets:
|
||||
inc(r.total)
|
||||
if target notin gTargets:
|
||||
r.addResult(test, target, extraOptions, "", "", reDisabled)
|
||||
discard r.finishTest(test, target, extraOptions, "", "", reDisabled)
|
||||
inc(r.skipped)
|
||||
elif simulate:
|
||||
inc count
|
||||
@@ -546,7 +562,7 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) =
|
||||
var expected = test.spec
|
||||
if expected.parseErrors.len > 0:
|
||||
# targetC is a lie, but a parameter is required
|
||||
r.addResult(test, targetC, "", "", expected.parseErrors, reInvalidSpec)
|
||||
discard r.finishTest(test, targetC, "", "", expected.parseErrors, reInvalidSpec)
|
||||
inc(r.total)
|
||||
return
|
||||
|
||||
|
||||
20
testament/tests/shouldfail/tnotenoughretries.nim
Normal file
20
testament/tests/shouldfail/tnotenoughretries.nim
Normal file
@@ -0,0 +1,20 @@
|
||||
discard """
|
||||
retries: 1
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
const tempFile = "tnotenoughretries_temp"
|
||||
|
||||
if not fileExists(tempFile):
|
||||
writeFile(tempFile, "abc")
|
||||
quit(1)
|
||||
else:
|
||||
let content = readFile(tempFile)
|
||||
if content == "abc":
|
||||
writeFile(tempFile, "def")
|
||||
quit(1)
|
||||
else:
|
||||
# success
|
||||
removeFile(tempFile)
|
||||
discard
|
||||
@@ -160,3 +160,16 @@ block:
|
||||
testCase()
|
||||
|
||||
main()
|
||||
|
||||
block: # bug #24147
|
||||
type
|
||||
O = object of RootObj
|
||||
val: string
|
||||
OO = object of O
|
||||
|
||||
proc `=copy`(dest: var O, src: O) =
|
||||
dest.val = src.val
|
||||
|
||||
let oo = OO(val: "hello world")
|
||||
var ooCopy : OO
|
||||
`=copy`(ooCopy, oo)
|
||||
|
||||
39
tests/arc/tdestructor_order.nim
Normal file
39
tests/arc/tdestructor_order.nim
Normal file
@@ -0,0 +1,39 @@
|
||||
discard """
|
||||
output: '''
|
||||
destroying d
|
||||
destroying c
|
||||
destroying a 2
|
||||
destroying d
|
||||
destroying c
|
||||
destroying a 1
|
||||
'''
|
||||
joinable: false
|
||||
"""
|
||||
|
||||
type
|
||||
Aaaa {.inheritable.} = object
|
||||
vvvv: int
|
||||
Bbbb = object of Aaaa
|
||||
c: Cccc
|
||||
d: Dddd
|
||||
Cccc = object
|
||||
Dddd = object
|
||||
|
||||
Holder = object
|
||||
member: ref Aaaa
|
||||
|
||||
proc `=destroy`(v: Cccc) =
|
||||
echo "destroying c"
|
||||
|
||||
proc `=destroy`(v: Dddd) =
|
||||
echo "destroying d"
|
||||
|
||||
proc `=destroy`(v: Aaaa) =
|
||||
echo "destroying a ", v.vvvv
|
||||
|
||||
func makeHolder(vvvv: int): ref Holder =
|
||||
(ref Holder)(member: (ref Bbbb)(vvvv: vvvv))
|
||||
|
||||
block:
|
||||
var v = makeHolder(1)
|
||||
var v2 = makeHolder(2)
|
||||
20
tests/arc/tnodestroyexplicithook.nim
Normal file
20
tests/arc/tnodestroyexplicithook.nim
Normal file
@@ -0,0 +1,20 @@
|
||||
# issue #24626
|
||||
|
||||
proc arrayWith2[T](y: T, size: static int): array[size, T] {.noinit, nodestroy, raises: [].} =
|
||||
## Creates a new array filled with `y`.
|
||||
for i in 0..size-1:
|
||||
when defined(nimHasDup):
|
||||
result[i] = `=dup`(y)
|
||||
else:
|
||||
wasMoved(result[i])
|
||||
`=copy`(result[i], y)
|
||||
|
||||
proc useArray(x: seq[int]) =
|
||||
var a = arrayWith2(x, 2)
|
||||
|
||||
proc main =
|
||||
let x = newSeq[int](100)
|
||||
for i in 0..5:
|
||||
useArray(x)
|
||||
|
||||
main()
|
||||
@@ -9,7 +9,8 @@ var
|
||||
try:
|
||||
x_cursor = ("hi", 5)
|
||||
if cond:
|
||||
x_cursor = ("different", 54) else:
|
||||
x_cursor = ("different", 54)
|
||||
else:
|
||||
x_cursor = ("string here", 80)
|
||||
echo [
|
||||
:tmpD = `$$`(x_cursor)
|
||||
|
||||
@@ -128,7 +128,8 @@ if dirExists(this.value):
|
||||
var :tmpD
|
||||
par = (dir:
|
||||
:tmpD = `=dup`(this.value)
|
||||
:tmpD, front: "") else:
|
||||
:tmpD, front: "")
|
||||
else:
|
||||
var
|
||||
:tmpD_1
|
||||
:tmpD_2
|
||||
|
||||
17
tests/arc/tstringliteral.nim
Normal file
17
tests/arc/tstringliteral.nim
Normal file
@@ -0,0 +1,17 @@
|
||||
discard """
|
||||
matrix: "--mm:arc; --mm:orc"
|
||||
"""
|
||||
|
||||
block: # issue #24080
|
||||
var a = (s: "a")
|
||||
var b = "a"
|
||||
a.s.setLen 0
|
||||
b = a.s
|
||||
doAssert b == ""
|
||||
|
||||
block: # issue #24080, longer string
|
||||
var a = (s: "abc")
|
||||
var b = "abc"
|
||||
a.s.setLen 2
|
||||
b = a.s
|
||||
doAssert b == "ab"
|
||||
16
tests/arc/tvalgrind.nim
Normal file
16
tests/arc/tvalgrind.nim
Normal file
@@ -0,0 +1,16 @@
|
||||
discard """
|
||||
cmd: "nim c --mm:orc -d:useMalloc $file"
|
||||
valgrind: "true"
|
||||
"""
|
||||
|
||||
import std/streams
|
||||
|
||||
|
||||
proc foo() =
|
||||
var name = newStringStream("2r2")
|
||||
raise newException(ValueError, "sh")
|
||||
|
||||
try:
|
||||
foo()
|
||||
except:
|
||||
discard
|
||||
4
tests/array/tindexconv.nim
Normal file
4
tests/array/tindexconv.nim
Normal file
@@ -0,0 +1,4 @@
|
||||
block: # issue #17958
|
||||
var mem: array[uint8, uint8]
|
||||
let val = 0xffff'u16
|
||||
discard mem[uint8 val] # Error: unhandled exception: index 65535 not in 0 .. 255 [IndexDefect]
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "index 2 not in 0 .. 1"
|
||||
errormsg: "conversion from int literal(2) to range 0..1(int) is invalid"
|
||||
line: 18
|
||||
"""
|
||||
block:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "index 3 not in 0 .. 1"
|
||||
errormsg: "conversion from int literal(3) to range 0..1(int) is invalid"
|
||||
line: 9
|
||||
"""
|
||||
|
||||
|
||||
@@ -31,3 +31,39 @@ elif defined(gcRefc):
|
||||
doAssert x.repr == "[p = nil]"
|
||||
else: # fixme # bug #20081
|
||||
doAssert x.repr == "Pledge(p: nil)"
|
||||
|
||||
block:
|
||||
block: # bug #18081
|
||||
type
|
||||
Foo = object
|
||||
discard
|
||||
|
||||
Bar = object
|
||||
x: Foo
|
||||
|
||||
proc baz(state: var Bar) =
|
||||
state.x = Foo()
|
||||
|
||||
baz((ref Bar)(x: (new Foo)[])[])
|
||||
|
||||
block: # bug #18079
|
||||
type
|
||||
Foo = object
|
||||
discard
|
||||
|
||||
Bar = object
|
||||
x: Foo
|
||||
|
||||
proc baz(state: var Bar) = discard
|
||||
baz((ref Bar)(x: (new Foo)[])[])
|
||||
|
||||
block: # bug #18080
|
||||
type
|
||||
Foo = object
|
||||
discard
|
||||
|
||||
Bar = object
|
||||
x: Foo
|
||||
|
||||
proc baz(state: var Bar) = discard
|
||||
baz((ref Bar)(x: Foo())[])
|
||||
|
||||
32
tests/ccgbugs/tunioninit.nim
Normal file
32
tests/ccgbugs/tunioninit.nim
Normal file
@@ -0,0 +1,32 @@
|
||||
# issue #20653
|
||||
|
||||
type
|
||||
EmptySeq* {.bycopy.} = object
|
||||
|
||||
ChoiceWithEmptySeq_d* {.bycopy.} = object
|
||||
a*: bool
|
||||
|
||||
INNER_C_UNION* {.bycopy, union.} = object
|
||||
a*: char
|
||||
b*: EmptySeq
|
||||
c*: byte
|
||||
d*: ChoiceWithEmptySeq_d
|
||||
|
||||
ChoiceWithEmptySeq_selection* = enum
|
||||
ChoiceWithEmptySeq_NONE,
|
||||
ChoiceWithEmptySeq_a_PRESENT,
|
||||
ChoiceWithEmptySeq_b_PRESENT,
|
||||
ChoiceWithEmptySeq_c_PRESENT,
|
||||
ChoiceWithEmptySeq_d_PRESENT
|
||||
|
||||
ChoiceWithEmptySeq* {.bycopy.} = object
|
||||
kind*: ChoiceWithEmptySeq_selection
|
||||
u*: INNER_C_UNION
|
||||
|
||||
Og_Context* {.bycopy.} = object
|
||||
state*: int
|
||||
init_done*: bool
|
||||
ch*: ChoiceWithEmptySeq
|
||||
em*: EmptySeq
|
||||
|
||||
var context* : Og_Context = Og_Context(init_done: false)
|
||||
@@ -1,6 +1,4 @@
|
||||
discard """
|
||||
# doesn't work on macos 13 seemingly due to libc++ linking issue https://stackoverflow.com/a/77375947
|
||||
disabled: osx
|
||||
targets: cpp
|
||||
"""
|
||||
|
||||
@@ -18,21 +16,21 @@ proc initStdException(): CStdException {.importcpp: "std::exception()", construc
|
||||
proc fn() =
|
||||
let a = initRuntimeError("foo")
|
||||
doAssert $a.what == "foo"
|
||||
var b: cstring
|
||||
var b = ""
|
||||
try: raise initRuntimeError("foo2")
|
||||
except CStdException as e:
|
||||
doAssert e is CStdException
|
||||
b = e.what()
|
||||
doAssert $b == "foo2"
|
||||
b = $e.what()
|
||||
doAssert b == "foo2"
|
||||
|
||||
try: raise initStdException()
|
||||
except CStdException: discard
|
||||
|
||||
try: raise initRuntimeError("foo3")
|
||||
except CRuntimeError as e:
|
||||
b = e.what()
|
||||
b = $e.what()
|
||||
except CStdException:
|
||||
doAssert false
|
||||
doAssert $b == "foo3"
|
||||
doAssert b == "foo3"
|
||||
|
||||
fn()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
output: '''----1
|
||||
output: '''
|
||||
----1
|
||||
myobj constructed
|
||||
myobj destroyed
|
||||
----2
|
||||
@@ -14,8 +15,8 @@ mygeneric3 constructed
|
||||
mygeneric1 destroyed
|
||||
----5
|
||||
mydistinctObj constructed
|
||||
myobj destroyed
|
||||
mygeneric2 destroyed
|
||||
myobj destroyed
|
||||
------------------8
|
||||
mygeneric1 destroyed
|
||||
----6
|
||||
|
||||
@@ -6,3 +6,26 @@ type DistinctSeq* = distinct seq[int]
|
||||
# `=destroy`(cast[ptr DistinctSeq](0)[])
|
||||
var x = @[].DistinctSeq
|
||||
`=destroy`(x)
|
||||
|
||||
|
||||
import std/options
|
||||
|
||||
# bug #24801
|
||||
type
|
||||
B[T] = object
|
||||
case r: bool
|
||||
of false:
|
||||
v: ref int
|
||||
of true:
|
||||
x: T
|
||||
E = distinct seq[int]
|
||||
U = ref object of RootObj
|
||||
G = ref object of U
|
||||
|
||||
proc a(): E = default(E)
|
||||
method c(_: U): seq[E] {.base.} = discard
|
||||
proc p(): seq[E] = c(default(U))
|
||||
method c(_: G): seq[E] = discard E(newSeq[seq[int]](1)[0])
|
||||
method y(_: U) {.base.} =
|
||||
let s = default(B[tuple[f: B[int], w: B[int]]])
|
||||
discard some(s.x)
|
||||
|
||||
@@ -16,3 +16,16 @@ block:
|
||||
doAssert s == 2
|
||||
|
||||
foo()
|
||||
|
||||
import std/deques
|
||||
|
||||
block: # bug #24319
|
||||
var queue = initDeque[array[32, byte]]()
|
||||
for i in 0 ..< 5:
|
||||
let element: array[32, byte] = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
]
|
||||
queue.addLast(element)
|
||||
|
||||
doAssert queue.popLast[^1] == byte(1)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
discard """
|
||||
valgrind: true
|
||||
cmd: '''nim c -d:nimAllocStats --gc:arc -d:useMalloc $file'''
|
||||
cmd: '''nim c -d:nimAllocStats --mm:arc -d:useMalloc $file'''
|
||||
output: '''
|
||||
@[(input: @["KXSC", "BGMC"]), (input: @["PXFX"]), (input: @["WXRQ", "ZSCZD"])]
|
||||
14
|
||||
@@ -252,3 +252,48 @@ proc main =
|
||||
|
||||
main()
|
||||
|
||||
|
||||
block:
|
||||
block:
|
||||
type
|
||||
JsonNode = ref object
|
||||
|
||||
proc foo(d: JsonNode) =
|
||||
discard
|
||||
|
||||
proc test_something()=
|
||||
var a = JsonNode()
|
||||
foo ensureMove(a)
|
||||
|
||||
test_something()
|
||||
|
||||
block:
|
||||
type
|
||||
JsonNode = object
|
||||
data: int
|
||||
|
||||
proc foo(d: JsonNode) =
|
||||
discard
|
||||
|
||||
proc test_something()=
|
||||
var a = JsonNode()
|
||||
foo ensureMove(a)
|
||||
|
||||
test_something()
|
||||
|
||||
block:
|
||||
type
|
||||
JsonNode = object
|
||||
data: int
|
||||
|
||||
proc `=destroy`(x: JsonNode) = discard
|
||||
|
||||
proc foo(d: JsonNode) =
|
||||
discard
|
||||
|
||||
proc test_something()=
|
||||
var a = JsonNode()
|
||||
foo ensureMove(a)
|
||||
|
||||
test_something()
|
||||
|
||||
|
||||
21
tests/distinct/tcomplexaddressableconv.nim
Normal file
21
tests/distinct/tcomplexaddressableconv.nim
Normal file
@@ -0,0 +1,21 @@
|
||||
# issue #22523
|
||||
|
||||
from std/typetraits import distinctBase
|
||||
|
||||
type
|
||||
V[p: static int] = distinct int
|
||||
D[p: static int] = distinct int
|
||||
T = V[1]
|
||||
|
||||
proc f(y: var T) = discard
|
||||
|
||||
var a: D[0]
|
||||
|
||||
static:
|
||||
doAssert distinctBase(T) is distinctBase(D[0])
|
||||
doAssert distinctBase(T) is int
|
||||
doAssert distinctBase(D[0]) is int
|
||||
doAssert T(a) is T
|
||||
|
||||
f(cast[ptr T](addr a)[])
|
||||
f(T(a))
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
# -*- nim -*-
|
||||
|
||||
import os, strutils
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
discard """
|
||||
outputsub: "true"
|
||||
disabled: "32bit"
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
type
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
discard """
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
# Program to detect bug #1796 reliably
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
type
|
||||
|
||||
@@ -6,6 +6,7 @@ Hello from thread
|
||||
Hello from thread
|
||||
'''
|
||||
cmd: "nim $target --hints:on --threads:on --tlsEmulation:off $options $file"
|
||||
retries: 2
|
||||
"""
|
||||
# Copied from stdlib
|
||||
import strutils
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "Success!"
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
# This is adapted from a benchmark written by John Ellis and Pete Kovac
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "77\n77"
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
## Check how GC/Alloc works in Emscripten
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
when defined(GC_setMaxPause):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
when defined(GC_setMaxPause):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
when defined(GC_setMaxPause):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
type
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
output: "success"
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
import os, times
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user