mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 10:53:40 +00:00
Compare commits
95 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
ce7c6f4f33 | ||
|
|
b0074121ec | ||
|
|
3713994ef1 | ||
|
|
75bd2d0688 | ||
|
|
eedfcbeb30 | ||
|
|
fe72db98c1 | ||
|
|
a70b4712fc | ||
|
|
76d834c182 | ||
|
|
72fcda1b35 | ||
|
|
fd9d2f5b82 | ||
|
|
d3f7fb3100 | ||
|
|
4acc7a5e18 | ||
|
|
e334aad202 | ||
|
|
67d7a7c124 | ||
|
|
206bbbd940 | ||
|
|
cc4c9251f0 | ||
|
|
8754469f49 | ||
|
|
e2ef322754 | ||
|
|
4fe17a2d87 | ||
|
|
cc887c23f4 | ||
|
|
acd09cec43 | ||
|
|
c8094176f1 | ||
|
|
3c66401dee | ||
|
|
ff46fcfd24 |
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 }}
|
||||
|
||||
4
.github/workflows/ci_docs.yml
vendored
4
.github/workflows/ci_docs.yml
vendored
@@ -43,11 +43,11 @@ jobs:
|
||||
target: [linux, windows, osx]
|
||||
include:
|
||||
- target: linux
|
||||
os: ubuntu-20.04
|
||||
os: ubuntu-22.04
|
||||
- target: windows
|
||||
os: windows-2019
|
||||
- target: osx
|
||||
os: macos-12
|
||||
os: macos-13
|
||||
|
||||
name: ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
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
|
||||
3
.github/workflows/ci_packages.yml
vendored
3
.github/workflows/ci_packages.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-12]
|
||||
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 }})'
|
||||
@@ -48,6 +48,7 @@ jobs:
|
||||
- name: 'Install dependencies (macOS)'
|
||||
if: runner.os == 'macOS'
|
||||
run: brew install boehmgc make sfml gtk+3
|
||||
# XXX can't find boehm and gtk on macos 13
|
||||
- name: 'Install dependencies (Windows)'
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash
|
||||
|
||||
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:
|
||||
@@ -29,23 +29,23 @@ jobs:
|
||||
# vmImage: 'ubuntu-18.04'
|
||||
# CPU: i386
|
||||
OSX_amd64:
|
||||
vmImage: 'macOS-12'
|
||||
vmImage: 'macOS-13'
|
||||
CPU: amd64
|
||||
OSX_amd64_cpp:
|
||||
vmImage: 'macOS-12'
|
||||
vmImage: 'macOS-13'
|
||||
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
|
||||
|
||||
@@ -130,6 +132,7 @@ jobs:
|
||||
- bash: brew install boehmgc make sfml
|
||||
displayName: 'Install dependencies (OSX)'
|
||||
condition: and(succeeded(), eq(variables['skipci'], 'false'), eq(variables['Agent.OS'], 'Darwin'))
|
||||
# XXX can't find boehm on macos 13
|
||||
|
||||
- bash: |
|
||||
set -e
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -890,7 +890,7 @@ proc initTabIter*(ti: var TTabIter, tab: TStrTable): PSym =
|
||||
result = nextIter(ti, tab)
|
||||
|
||||
iterator items*(tab: TStrTable): PSym =
|
||||
var it: TTabIter
|
||||
var it: TTabIter = default(TTabIter)
|
||||
var s = initTabIter(it, tab)
|
||||
while s != nil:
|
||||
yield s
|
||||
@@ -1054,14 +1054,6 @@ proc iiTablePut(t: var TIITable, key, val: int) =
|
||||
iiTableRawInsert(t.data, key, val)
|
||||
inc(t.counter)
|
||||
|
||||
proc isAddrNode*(n: PNode): bool =
|
||||
case n.kind
|
||||
of nkAddr, nkHiddenAddr: true
|
||||
of nkCallKinds:
|
||||
if n[0].kind == nkSym and n[0].sym.magic == mAddr: true
|
||||
else: false
|
||||
else: false
|
||||
|
||||
proc listSymbolNames*(symbols: openArray[PSym]): string =
|
||||
for sym in symbols:
|
||||
if result.len > 0:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -760,7 +760,7 @@ proc getRecordFields(m: BModule; typ: PType, check: var IntSet): Rope =
|
||||
genMemberProcHeader(m, prc, header, false, true)
|
||||
result.addf "$1;$n", [header]
|
||||
if isCtorGen and not isDefaultCtorGen:
|
||||
var ch: IntSet
|
||||
var ch: IntSet = default(IntSet)
|
||||
result.addf "$1() = default;$n", [getTypeDescAux(m, typ, ch, dkOther)]
|
||||
|
||||
proc fillObjectFields*(m: BModule; typ: PType) =
|
||||
@@ -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
|
||||
|
||||
@@ -1594,7 +1596,7 @@ proc generateRttiDestructor(g: ModuleGraph; typ: PType; owner: PSym; kind: TType
|
||||
))
|
||||
)
|
||||
else:
|
||||
let addrOf = newNodeIT(nkAddr, info, theProc.typ[1])
|
||||
let addrOf = newNodeIT(nkHiddenAddr, info, theProc.typ[1])
|
||||
addrOf.add newDeref(newTreeIT(
|
||||
nkCast, info, castType, newNodeIT(nkType, info, castType),
|
||||
newSymNode(dest)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -423,8 +423,8 @@ proc fficast*(conf: ConfigRef, x: PNode, destTyp: PType): PNode =
|
||||
proc callForeignFunction*(conf: ConfigRef, call: PNode): PNode =
|
||||
internalAssert conf, call[0].kind == nkPtrLit
|
||||
|
||||
var cif: TCif
|
||||
var sig: ParamList
|
||||
var cif: TCif = default(TCif)
|
||||
var sig: ParamList = default(ParamList)
|
||||
# use the arguments' types for varargs support:
|
||||
for i in 1..<call.len:
|
||||
sig[i-1] = mapType(conf, call[i].typ)
|
||||
@@ -463,8 +463,8 @@ proc callForeignFunction*(conf: ConfigRef, fn: PNode, fntyp: PType,
|
||||
info: TLineInfo): PNode =
|
||||
internalAssert conf, fn.kind == nkPtrLit
|
||||
|
||||
var cif: TCif
|
||||
var sig: ParamList
|
||||
var cif: TCif = default(TCif)
|
||||
var sig: ParamList = default(ParamList)
|
||||
for i in 0..len-1:
|
||||
var aTyp = args[i+start].typ
|
||||
if aTyp.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)
|
||||
|
||||
@@ -1047,8 +1047,12 @@ proc buildProperFieldCheck(access, check: PNode; o: Operators): PNode =
|
||||
if check[1].kind == nkCurly:
|
||||
result = copyTree(check)
|
||||
if access.kind == nkDotExpr:
|
||||
# change the access to the discriminator field access
|
||||
var a = copyTree(access)
|
||||
# set field name to discriminator field name
|
||||
a[1] = check[2]
|
||||
# set discriminator field type: important for `neg`
|
||||
a.typ = check[2].typ
|
||||
result[2] = a
|
||||
# 'access.kind != nkDotExpr' can happen for object constructors
|
||||
# which we don't check yet
|
||||
|
||||
@@ -141,7 +141,7 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym; importSet: var IntSet) =
|
||||
# for an enumeration we have to add all identifiers
|
||||
if multiImport:
|
||||
# for a overloadable syms add all overloaded routines
|
||||
var it: ModuleIter
|
||||
var it: ModuleIter = default(ModuleIter)
|
||||
var e = initModuleIter(it, c.graph, fromMod, s.name)
|
||||
while e != nil:
|
||||
if e.name.id != s.name.id: internalError(c.config, n.info, "importSymbol: 3")
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -896,7 +896,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||
p.body.add("++excHandler;\L")
|
||||
var tmpFramePtr = rope"F"
|
||||
lineF(p, "try {$n", [])
|
||||
var a: TCompRes
|
||||
var a: TCompRes = default(TCompRes)
|
||||
gen(p, n[0], a)
|
||||
moveInto(p, a, r)
|
||||
var generalCatchBranchExists = false
|
||||
@@ -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)
|
||||
@@ -226,7 +226,14 @@ proc fillBodyObjTImpl(c: var TLiftCtx; t: PType, body, x, y: PNode) =
|
||||
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)
|
||||
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, obj, src)
|
||||
fillBodyObj(c, t.n, body, x, y, enforceDefaultOp = false)
|
||||
|
||||
proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
|
||||
@@ -1036,9 +1043,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 +1082,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 +1092,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 +1134,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 +1184,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)
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import std/strutils
|
||||
from std/sugar import dup
|
||||
|
||||
import options, ast, msgs, idents, lineinfos, wordrecg, astmsgs, semdata, packages
|
||||
import options, ast, msgs, idents, lineinfos, wordrecg, astmsgs, semdata, packages, modulegraphs
|
||||
export packages
|
||||
|
||||
const
|
||||
@@ -95,7 +95,7 @@ template styleCheckDef*(ctx: PContext; info: TLineInfo; sym: PSym; k: TSymKind)
|
||||
if optStyleCheck in ctx.config.options and # ignore if styleChecks are off
|
||||
{optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # check only if hint/error is enabled
|
||||
hintName in ctx.config.notes and # ignore if name checks are not requested
|
||||
ctx.config.belongsToProjectPackage(sym) and # ignore foreign packages
|
||||
ctx.config.belongsToProjectPackageMaybeNil(getModule(ctx.graph, info.fileIndex)) and # ignore foreign packages
|
||||
optStyleUsages notin ctx.config.globalOptions and # ignore if requested to only check name usage
|
||||
sym.kind != skResult and # ignore `result`
|
||||
sym.kind != skTemp and # ignore temporary variables created by the compiler
|
||||
@@ -136,7 +136,7 @@ template styleCheckUse*(ctx: PContext; info: TLineInfo; sym: PSym) =
|
||||
## Check symbol uses match their definition's style.
|
||||
if {optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # ignore if styleChecks are off
|
||||
hintName in ctx.config.notes and # ignore if name checks are not requested
|
||||
ctx.config.belongsToProjectPackage(sym) and # ignore foreign packages
|
||||
ctx.config.belongsToProjectPackageMaybeNil(getModule(ctx.graph, info.fileIndex)) and # ignore foreign packages
|
||||
sym.kind != skTemp and # ignore temporary variables created by the compiler
|
||||
sym.name.s[0] in Letters and # ignore operators TODO: what about unicode symbols???
|
||||
sfAnon notin sym.flags: # ignore temporary variables created by the compiler
|
||||
@@ -152,5 +152,5 @@ template checkPragmaUse*(ctx: PContext; info: TLineInfo; w: TSpecialWord; pragma
|
||||
## Note: This only applies to builtin pragmas, not user pragmas.
|
||||
if {optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # ignore if styleChecks are off
|
||||
hintName in ctx.config.notes and # ignore if name checks are not requested
|
||||
(sym != nil and ctx.config.belongsToProjectPackage(sym)): # ignore foreign packages
|
||||
ctx.config.belongsToProjectPackageMaybeNil(getModule(ctx.graph, info.fileIndex)): # ignore foreign packages
|
||||
checkPragmaUseImpl(ctx.config, info, w, pragmaName)
|
||||
|
||||
@@ -137,7 +137,7 @@ proc nextIdentIter(ti: var ModuleIter; marked: var IntSet; im: ImportedModule;
|
||||
return result
|
||||
|
||||
iterator symbols(im: ImportedModule; marked: var IntSet; name: PIdent; g: ModuleGraph): PSym =
|
||||
var ti: ModuleIter
|
||||
var ti: ModuleIter = default(ModuleIter)
|
||||
var candidate = initIdentIter(ti, marked, im, name, g)
|
||||
while candidate != nil:
|
||||
yield candidate
|
||||
@@ -150,7 +150,7 @@ iterator importedItems*(c: PContext; name: PIdent): PSym =
|
||||
yield s
|
||||
|
||||
proc allPureEnumFields(c: PContext; name: PIdent): seq[PSym] =
|
||||
var ti: TIdentIter
|
||||
var ti: TIdentIter = default(TIdentIter)
|
||||
result = @[]
|
||||
var res = initIdentIter(ti, c.pureEnumFields, name)
|
||||
while res != nil:
|
||||
@@ -222,7 +222,7 @@ proc debugScopes*(c: PContext; limit=0, max = int.high) {.deprecated.} =
|
||||
proc searchInScopesAllCandidatesFilterBy*(c: PContext, s: PIdent, filter: TSymKinds): seq[PSym] =
|
||||
result = @[]
|
||||
for scope in allScopes(c.currentScope):
|
||||
var ti: TIdentIter
|
||||
var ti: TIdentIter = default(TIdentIter)
|
||||
var candidate = initIdentIter(ti, scope.symbols, s)
|
||||
while candidate != nil:
|
||||
if candidate.kind in filter:
|
||||
@@ -240,7 +240,7 @@ proc searchInScopesFilterBy*(c: PContext, s: PIdent, filter: TSymKinds): seq[PSy
|
||||
result = @[]
|
||||
block outer:
|
||||
for scope in allScopes(c.currentScope):
|
||||
var ti: TIdentIter
|
||||
var ti: TIdentIter = default(TIdentIter)
|
||||
var candidate = initIdentIter(ti, scope.symbols, s)
|
||||
while candidate != nil:
|
||||
if candidate.kind in filter:
|
||||
@@ -272,7 +272,7 @@ proc isAmbiguous*(c: PContext, s: PIdent, filter: TSymKinds, sym: var PSym): boo
|
||||
result = false
|
||||
block outer:
|
||||
for scope in allScopes(c.currentScope):
|
||||
var ti: TIdentIter
|
||||
var ti: TIdentIter = default(TIdentIter)
|
||||
var candidate = initIdentIter(ti, scope.symbols, s)
|
||||
var scopeHasCandidate = false
|
||||
while candidate != nil:
|
||||
@@ -347,7 +347,7 @@ proc getSymRepr*(conf: ConfigRef; s: PSym, getDeclarationPath = true): string =
|
||||
|
||||
proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) =
|
||||
# check if all symbols have been used and defined:
|
||||
var it: TTabIter
|
||||
var it: TTabIter = default(TTabIter)
|
||||
var s = initTabIter(it, scope.symbols)
|
||||
var missingImpls = 0
|
||||
var unusedSyms: seq[tuple[sym: PSym, key: string]]
|
||||
@@ -557,7 +557,7 @@ proc errorUseQualifier(c: PContext; info: TLineInfo; s: PSym; amb: var bool): PS
|
||||
amb = false
|
||||
|
||||
proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
|
||||
var amb: bool
|
||||
var amb: bool = false
|
||||
discard errorUseQualifier(c, info, s, amb)
|
||||
|
||||
proc errorUseQualifier*(c: PContext; info: TLineInfo; candidates: seq[PSym]; prefix = "use one of") =
|
||||
@@ -680,7 +680,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
|
||||
result = strTableGet(c.topLevelScope.symbols, ident)
|
||||
else:
|
||||
if c.importModuleLookup.getOrDefault(m.name.id).len > 1:
|
||||
var amb: bool
|
||||
var amb: bool = false
|
||||
result = errorUseQualifier(c, n.info, m, amb)
|
||||
else:
|
||||
result = someSym(c.graph, m, ident)
|
||||
|
||||
@@ -195,8 +195,8 @@ proc commandScan(cache: IdentCache, config: ConfigRef) =
|
||||
var stream = llStreamOpen(f, fmRead)
|
||||
if stream != nil:
|
||||
var
|
||||
L: Lexer
|
||||
tok: Token
|
||||
L: Lexer = default(Lexer)
|
||||
tok: Token = default(Token)
|
||||
initToken(tok)
|
||||
openLexer(L, f, stream, cache, config)
|
||||
while true:
|
||||
|
||||
@@ -251,7 +251,7 @@ proc nextModuleIter*(mi: var ModuleIter; g: ModuleGraph): PSym =
|
||||
iterator allSyms*(g: ModuleGraph; m: PSym): PSym =
|
||||
let importHidden = optImportHidden in m.options
|
||||
if isCachedModule(g, m):
|
||||
var rodIt: RodIter
|
||||
var rodIt: RodIter = default(RodIter)
|
||||
var r = initRodIterAllSyms(rodIt, g.config, g.cache, g.packed, FileIndex m.position, importHidden)
|
||||
while r != nil:
|
||||
yield r
|
||||
@@ -272,7 +272,7 @@ proc systemModuleSym*(g: ModuleGraph; name: PIdent): PSym =
|
||||
result = someSym(g, g.systemModule, name)
|
||||
|
||||
iterator systemModuleSyms*(g: ModuleGraph; name: PIdent): PSym =
|
||||
var mi: ModuleIter
|
||||
var mi: ModuleIter = default(ModuleIter)
|
||||
var r = initModuleIter(mi, g, g.systemModule, name)
|
||||
while r != nil:
|
||||
yield r
|
||||
|
||||
@@ -125,14 +125,14 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile; isKnownFile: var bool
|
||||
conf.m.filenameToIndexTbl[canon2] = result
|
||||
|
||||
proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile): FileIndex =
|
||||
var dummy: bool
|
||||
var dummy: bool = false
|
||||
result = fileInfoIdx(conf, filename, dummy)
|
||||
|
||||
proc fileInfoIdx*(conf: ConfigRef; filename: RelativeFile; isKnownFile: var bool): FileIndex =
|
||||
fileInfoIdx(conf, AbsoluteFile expandFilename(filename.string), isKnownFile)
|
||||
|
||||
proc fileInfoIdx*(conf: ConfigRef; filename: RelativeFile): FileIndex =
|
||||
var dummy: bool
|
||||
var dummy: bool = false
|
||||
fileInfoIdx(conf, AbsoluteFile expandFilename(filename.string), dummy)
|
||||
|
||||
proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =
|
||||
|
||||
@@ -40,7 +40,7 @@ proc selectUniqueSymbol*(i: Interpreter; name: string;
|
||||
assert i != nil
|
||||
assert i.mainModule != nil, "no main module selected"
|
||||
let n = getIdent(i.graph.cache, name)
|
||||
var it: ModuleIter
|
||||
var it: ModuleIter = default(ModuleIter)
|
||||
var s = initModuleIter(it, i.graph, i.mainModule, n)
|
||||
result = nil
|
||||
while s != nil:
|
||||
|
||||
@@ -279,8 +279,8 @@ proc optimize*(n: PNode): PNode =
|
||||
|
||||
Now assume 'use' raises, then we shouldn't do the 'wasMoved(s)'
|
||||
]#
|
||||
var c: Con
|
||||
var b: BasicBlock
|
||||
var c: Con = Con()
|
||||
var b: BasicBlock = default(BasicBlock)
|
||||
analyse(c, b, n)
|
||||
if c.somethingTodo:
|
||||
result = shallowCopy(n)
|
||||
|
||||
@@ -51,3 +51,11 @@ func belongsToProjectPackage*(conf: ConfigRef, sym: PSym): bool =
|
||||
## See Also:
|
||||
## * `modulegraphs.belongsToStdlib`
|
||||
conf.mainPackageId == sym.getPackageId
|
||||
|
||||
func belongsToProjectPackageMaybeNil*(conf: ConfigRef, sym: PSym): bool =
|
||||
## Return whether the symbol belongs to the project's package.
|
||||
## Returns `false` if `sym` is nil.
|
||||
##
|
||||
## See Also:
|
||||
## * `modulegraphs.belongsToStdlib`
|
||||
sym != nil and conf.mainPackageId == sym.getPackageId
|
||||
|
||||
@@ -91,7 +91,7 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
|
||||
stream: PLLStream): bool =
|
||||
if graph.stopCompile(): return true
|
||||
var
|
||||
p: Parser
|
||||
p: Parser = default(Parser)
|
||||
s: PLLStream
|
||||
fileIdx = module.fileIdx
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -31,7 +31,7 @@ proc equalGenericParams(procA, procB: PNode): bool =
|
||||
proc searchForProcAux(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||
const flags = {ExactGenericParams, ExactTypeDescValues,
|
||||
ExactConstraints, IgnoreCC}
|
||||
var it: TIdentIter
|
||||
var it: TIdentIter = default(TIdentIter)
|
||||
result = initIdentIter(it, scope.symbols, fn.name)
|
||||
while result != nil:
|
||||
if result.kind == fn.kind: #and sameType(result.typ, fn.typ, flags):
|
||||
@@ -74,7 +74,7 @@ when false:
|
||||
proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
|
||||
# Searches for the fn in the symbol table. If the parameter lists are suitable
|
||||
# for borrowing the sym in the symbol table is returned, else nil.
|
||||
var it: TIdentIter
|
||||
var it: TIdentIter = default(TIdentIter)
|
||||
for scope in walkScopes(startScope):
|
||||
result = initIdentIter(it, scope.symbols, fn.Name)
|
||||
while result != nil:
|
||||
|
||||
@@ -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:
|
||||
@@ -1310,10 +1316,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
|
||||
put(g, tkCustomLit, n[0].strVal)
|
||||
gsub(g, n, 1)
|
||||
else:
|
||||
gsub(g, n, 0)
|
||||
for i in 0..<n.len-1:
|
||||
gsub(g, n, i)
|
||||
put(g, tkDot, ".")
|
||||
assert n.len == 2, $n.len
|
||||
accentedName(g, n[1])
|
||||
if n.len > 1:
|
||||
accentedName(g, n[^1])
|
||||
of nkBind:
|
||||
putWithSpace(g, tkBind, "bind")
|
||||
gsub(g, n, 0)
|
||||
@@ -1458,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, "(")
|
||||
@@ -1728,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:
|
||||
|
||||
@@ -408,7 +408,8 @@ proc strongConnect(v: var DepN, idx: var int, s: var seq[DepN],
|
||||
proc getStrongComponents(g: var DepG): seq[seq[DepN]] =
|
||||
## Tarjan's algorithm. Performs a topological sort
|
||||
## and detects strongly connected components.
|
||||
var s: seq[DepN]
|
||||
result = @[]
|
||||
var s: seq[DepN] = @[]
|
||||
var idx = 0
|
||||
for v in g.mitems:
|
||||
if v.idx < 0:
|
||||
|
||||
@@ -88,6 +88,11 @@ proc fitNodePostMatch(c: PContext, formal: PType, arg: PNode): PNode =
|
||||
changeType(c, x, formal, check=true)
|
||||
result = arg
|
||||
result = skipHiddenSubConv(result, c.graph, c.idgen)
|
||||
# mark inserted converter as used:
|
||||
var a = result
|
||||
if a.kind == nkHiddenDeref: a = a[0]
|
||||
if a.kind == nkHiddenCallConv and a[0].kind == nkSym:
|
||||
markUsed(c, a.info, a[0].sym)
|
||||
|
||||
|
||||
proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
|
||||
@@ -496,7 +501,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
if retType.kind == tyVoid:
|
||||
result = semStmt(c, result, flags)
|
||||
else:
|
||||
result = semExpr(c, result, flags, expectedType)
|
||||
result = semExpr(c, result, flags)
|
||||
result = fitNode(c, retType, result, result.info)
|
||||
#globalError(s.info, errInvalidParamKindX, typeToString(s.typ[0]))
|
||||
dec(c.config.evalTemplateCounter)
|
||||
|
||||
@@ -68,7 +68,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||
# `matches` may find new symbols, so keep track of count
|
||||
var symCount = c.currentScope.symbols.counter
|
||||
|
||||
var o: TOverloadIter
|
||||
var o: TOverloadIter = default(TOverloadIter)
|
||||
# https://github.com/nim-lang/Nim/issues/21272
|
||||
# prevent mutation during iteration by storing them in a seq
|
||||
# luckily `initCandidateSymbols` does just that
|
||||
@@ -399,7 +399,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||
|
||||
proc bracketNotFoundError(c: PContext; n: PNode) =
|
||||
var errors: CandidateErrors = @[]
|
||||
var o: TOverloadIter
|
||||
var o: TOverloadIter = default(TOverloadIter)
|
||||
let headSymbol = n[0]
|
||||
var symx = initOverloadIter(o, c, headSymbol)
|
||||
while symx != nil:
|
||||
@@ -421,7 +421,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
|
||||
# also avoid slowdowns in evaluating `compiles(expr)`.
|
||||
discard
|
||||
else:
|
||||
var o: TOverloadIter
|
||||
var o: TOverloadIter = default(TOverloadIter)
|
||||
var sym = initOverloadIter(o, c, f)
|
||||
while sym != nil:
|
||||
result &= "\n found $1" % [getSymRepr(c.config, sym)]
|
||||
@@ -465,7 +465,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
filter, result, alt, errors, efExplain in flags,
|
||||
errorsEnabled, flags)
|
||||
|
||||
var dummyErrors: CandidateErrors
|
||||
var dummyErrors: CandidateErrors = @[]
|
||||
template pickSpecialOp(headSymbol) =
|
||||
pickBestCandidate(c, headSymbol, n, orig, initialBinding,
|
||||
filter, result, alt, dummyErrors, efExplain in flags,
|
||||
@@ -556,6 +556,15 @@ proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =
|
||||
for i in 1..<n.len:
|
||||
instGenericConvertersArg(c, n[i], x)
|
||||
|
||||
proc markConvertersUsed*(c: PContext, n: PNode) =
|
||||
assert n.kind in nkCallKinds
|
||||
for i in 1..<n.len:
|
||||
var a = n[i]
|
||||
if a == nil: continue
|
||||
if a.kind == nkHiddenDeref: a = a[0]
|
||||
if a.kind == nkHiddenCallConv and a[0].kind == nkSym:
|
||||
markUsed(c, a.info, a[0].sym)
|
||||
|
||||
proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode =
|
||||
var m = newCandidate(c, f)
|
||||
result = paramTypesMatch(m, f, a, arg, nil)
|
||||
@@ -651,8 +660,10 @@ proc semResolvedCall(c: PContext, x: TCandidate,
|
||||
|
||||
result = x.call
|
||||
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.} =
|
||||
|
||||
@@ -969,9 +969,9 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||
n.typ.flags.incl tfUnresolved
|
||||
|
||||
# optimization pass: not necessary for correctness of the semantic pass
|
||||
if callee.kind == skConst or
|
||||
if (callee.kind == skConst or
|
||||
{sfNoSideEffect, sfCompileTime} * callee.flags != {} and
|
||||
{sfForward, sfImportc} * callee.flags == {} and n.typ != nil:
|
||||
{sfForward, sfImportc} * callee.flags == {}) and n.typ != nil:
|
||||
|
||||
if callee.kind != skConst and
|
||||
sfCompileTime notin callee.flags and
|
||||
@@ -1205,6 +1205,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
|
||||
else:
|
||||
result = m.call
|
||||
instGenericConvertersSons(c, result, m)
|
||||
markConvertersUsed(c, result)
|
||||
|
||||
else:
|
||||
result = overloadedCallOpr(c, n) # this uses efNoUndeclared
|
||||
@@ -1459,6 +1460,8 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
if n.kind != nkDotExpr: # dotExpr is already checked by builtinFieldAccess
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
if s.typ == nil:
|
||||
return localErrorNode(c, n, "symbol '$1' has no type" % [s.name.s])
|
||||
if s.typ.kind == tyStatic and s.typ.base.kind != tyNone and s.typ.n != nil:
|
||||
return s.typ.n
|
||||
result = newSymNode(s, n.info)
|
||||
@@ -1847,6 +1850,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.} =
|
||||
@@ -2264,7 +2269,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
|
||||
let headSymbol = macroCall[0]
|
||||
var cands = 0
|
||||
var cand: PSym = nil
|
||||
var o: TOverloadIter
|
||||
var o: TOverloadIter = default(TOverloadIter)
|
||||
var symx = initOverloadIter(o, c, headSymbol)
|
||||
while symx != nil:
|
||||
if symx.kind in {skTemplate, skMacro} and symx.typ.len == macroCall.len:
|
||||
@@ -2515,9 +2520,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P
|
||||
of mAddr:
|
||||
markUsed(c, n.info, s)
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result[0] = newSymNode(s, n[0].info)
|
||||
result[1] = semAddrArg(c, n[1])
|
||||
result.typ = makePtrType(c, result[1].typ)
|
||||
result = semAddr(c, n[1])
|
||||
of mTypeOf:
|
||||
markUsed(c, n.info, s)
|
||||
result = semTypeOf(c, n)
|
||||
@@ -2932,7 +2935,7 @@ proc semExport(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkExportStmt, n.info)
|
||||
for i in 0..<n.len:
|
||||
let a = n[i]
|
||||
var o: TOverloadIter
|
||||
var o: TOverloadIter = default(TOverloadIter)
|
||||
var s = initOverloadIter(o, c, a)
|
||||
if s == nil:
|
||||
localError(c.config, a.info, errGenerated, "cannot export: " & renderTree(a))
|
||||
@@ -3074,7 +3077,7 @@ proc getNilType(c: PContext): PType =
|
||||
c.nilTypeCache = result
|
||||
|
||||
proc enumFieldSymChoice(c: PContext, n: PNode, s: PSym; flags: TExprFlags): PNode =
|
||||
var o: TOverloadIter
|
||||
var o: TOverloadIter = default(TOverloadIter)
|
||||
var i = 0
|
||||
var a = initOverloadIter(o, c, n)
|
||||
while a != nil:
|
||||
@@ -3400,8 +3403,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
of nkAddr:
|
||||
result = n
|
||||
checkSonsLen(n, 1, c.config)
|
||||
result[0] = semAddrArg(c, n[0])
|
||||
result.typ = makePtrType(c, result[0].typ)
|
||||
result = semAddr(c, n[0])
|
||||
of nkHiddenAddr, nkHiddenDeref:
|
||||
checkSonsLen(n, 1, c.config)
|
||||
n[0] = semExpr(c, n[0], flags, expectedType)
|
||||
|
||||
@@ -18,6 +18,15 @@ type
|
||||
replaceByFieldName: bool
|
||||
c: PContext
|
||||
|
||||
proc wrapNewScope(c: PContext, n: PNode): PNode {.inline.} =
|
||||
# use `if true` to not interfere with `break`
|
||||
# just opening scope via `openScope(c)` isn't enough,
|
||||
# a scope has to be opened in the codegen as well for reused
|
||||
# template instantiations
|
||||
let trueLit = newIntLit(c.graph, n.info, 1)
|
||||
trueLit.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result = newTreeI(nkIfStmt, n.info, newTreeI(nkElifBranch, n.info, trueLit, n))
|
||||
|
||||
proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
|
||||
if c.field != nil and isEmptyType(c.field.typ):
|
||||
result = newNode(nkEmpty)
|
||||
@@ -70,7 +79,9 @@ proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) =
|
||||
fc.replaceByFieldName = c.m == mFieldPairs
|
||||
openScope(c.c)
|
||||
inc c.c.inUnrolledContext
|
||||
let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop)
|
||||
var body = instFieldLoopBody(fc, lastSon(forLoop), forLoop)
|
||||
# new scope for each field that codegen should know about:
|
||||
body = wrapNewScope(c.c, body)
|
||||
father.add(semStmt(c.c, body, {}))
|
||||
dec c.c.inUnrolledContext
|
||||
closeScope(c.c)
|
||||
@@ -145,6 +156,8 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
fc.c = c
|
||||
fc.replaceByFieldName = m == mFieldPairs
|
||||
var body = instFieldLoopBody(fc, loopBody, n)
|
||||
# new scope for each field that codegen should know about:
|
||||
body = wrapNewScope(c, body)
|
||||
inc c.inUnrolledContext
|
||||
stmts.add(semStmt(c, body, {}))
|
||||
dec c.inUnrolledContext
|
||||
|
||||
@@ -688,10 +688,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
except DivByZeroDefect:
|
||||
localError(g.config, n.info, "division by zero")
|
||||
of nkAddr:
|
||||
var a = getConstExpr(m, n[0], idgen, g)
|
||||
if a != nil:
|
||||
result = n
|
||||
n[0] = a
|
||||
result = nil # don't fold paths containing nkAddr
|
||||
of nkBracket, nkCurly:
|
||||
result = copyNode(n)
|
||||
for son in n.items:
|
||||
@@ -760,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
|
||||
|
||||
@@ -251,7 +251,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
#var s = qualifiedLookUp(c, n, luf)
|
||||
#if s != nil: result = semGenericStmtSymbol(c, n, s)
|
||||
# XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
|
||||
var dummy: bool
|
||||
var dummy: bool = false
|
||||
result = fuzzyLookup(c, n, flags, ctx, dummy)
|
||||
of nkSym:
|
||||
let a = n.sym
|
||||
@@ -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:
|
||||
|
||||
@@ -342,7 +342,11 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
if c.instCounter > 50:
|
||||
globalError(c.config, info, "generic instantiation too nested")
|
||||
inc c.instCounter
|
||||
defer: dec c.instCounter
|
||||
let currentTypeofContext = c.inTypeofContext
|
||||
c.inTypeofContext = 0
|
||||
defer:
|
||||
dec c.instCounter
|
||||
c.inTypeofContext = currentTypeofContext
|
||||
# careful! we copy the whole AST including the possibly nil body!
|
||||
var n = copyTree(fn.ast)
|
||||
# NOTE: for access of private fields within generics from a different module
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -30,13 +30,15 @@ proc addDefaultFieldForNew(c: PContext, n: PNode): PNode =
|
||||
if asgnExpr.sons.len > 1:
|
||||
result = newTree(nkAsgn, result[1], asgnExpr)
|
||||
|
||||
proc semAddrArg(c: PContext; n: PNode): PNode =
|
||||
proc semAddr(c: PContext; n: PNode): PNode =
|
||||
result = newNodeI(nkAddr, n.info)
|
||||
let x = semExprWithType(c, n)
|
||||
if x.kind == nkSym:
|
||||
x.sym.flags.incl(sfAddrTaken)
|
||||
if isAssignable(c, x) notin {arLValue, arLocalLValue, arAddressableConst, arLentValue}:
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
result = x
|
||||
result.add x
|
||||
result.typ = makePtrType(c, x.typ)
|
||||
|
||||
proc semTypeOf(c: PContext; n: PNode): PNode =
|
||||
var m = BiggestInt 1 # typeOfIter
|
||||
@@ -551,9 +553,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
case n[0].sym.magic
|
||||
of mAddr:
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result = n
|
||||
result[1] = semAddrArg(c, n[1])
|
||||
result.typ = makePtrType(c, result[1].typ)
|
||||
result = semAddr(c, n[1])
|
||||
of mTypeOf:
|
||||
result = semTypeOf(c, n)
|
||||
of mSizeOf:
|
||||
|
||||
@@ -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
|
||||
@@ -581,7 +583,7 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
|
||||
if paramType != nil and tfNotNil in paramType.flags and n.typ != nil:
|
||||
let ntyp = n.typ.skipTypesOrNil({tyVar, tyLent, tySink})
|
||||
if ntyp != nil and tfNotNil notin ntyp.flags:
|
||||
if isAddrNode(n):
|
||||
if n.kind in {nkAddr, nkHiddenAddr}:
|
||||
# addr(x[]) can't be proven, but addr(x) can:
|
||||
if not containsNode(n, {nkDerefExpr, nkHiddenDeref}): return
|
||||
elif (n.kind == nkSym and n.sym.kind in routineKinds) or
|
||||
@@ -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)
|
||||
@@ -1159,7 +1177,7 @@ proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string;
|
||||
if maType == nil: return
|
||||
|
||||
let headSymbol = selector[0]
|
||||
var o: TOverloadIter
|
||||
var o: TOverloadIter = default(TOverloadIter)
|
||||
var match: PSym = nil
|
||||
var symx = initOverloadIter(o, c, headSymbol)
|
||||
while symx != nil:
|
||||
@@ -1193,7 +1211,7 @@ proc handleCaseStmtMacro(c: PContext; n: PNode; flags: TExprFlags): PNode =
|
||||
toResolve.add newIdentNode(getIdent(c.cache, "case"), n.info)
|
||||
toResolve.add n[0]
|
||||
|
||||
var errors: CandidateErrors
|
||||
var errors: CandidateErrors = @[]
|
||||
var r = resolveOverloads(c, toResolve, toResolve, {skTemplate, skMacro}, {efNoDiagnostics},
|
||||
errors, false)
|
||||
if r.state == csMatch:
|
||||
@@ -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
|
||||
|
||||
@@ -51,7 +51,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
|
||||
isField = false): PNode =
|
||||
var
|
||||
a: PSym
|
||||
o: TOverloadIter
|
||||
o: TOverloadIter = default(TOverloadIter)
|
||||
var i = 0
|
||||
a = initOverloadIter(o, c, n)
|
||||
while a != nil:
|
||||
@@ -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
|
||||
@@ -1873,7 +1890,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
return errorSym(c, n)
|
||||
if result.kind != skType and result.magic notin {mStatic, mType, mTypeOf}:
|
||||
# this implements the wanted ``var v: V, x: V`` feature ...
|
||||
var ov: TOverloadIter
|
||||
var ov: TOverloadIter = default(TOverloadIter)
|
||||
var amb = initOverloadIter(ov, c, n)
|
||||
while amb != nil and amb.kind != skType:
|
||||
amb = nextOverloadIter(ov, c, n)
|
||||
|
||||
@@ -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) &
|
||||
|
||||
@@ -260,7 +260,8 @@ when defined(debugSigHashes):
|
||||
# (select hash from sighashes group by hash having count(*) > 1) order by hash;
|
||||
|
||||
proc hashType*(t: PType; conf: ConfigRef; flags: set[ConsiderFlag] = {CoType}): SigHash =
|
||||
var c: MD5Context
|
||||
result = default(SigHash)
|
||||
var c: MD5Context = default(MD5Context)
|
||||
md5Init c
|
||||
hashType c, t, flags+{CoOwnerSig}, conf
|
||||
md5Final c, result.MD5Digest
|
||||
@@ -269,7 +270,8 @@ proc hashType*(t: PType; conf: ConfigRef; flags: set[ConsiderFlag] = {CoType}):
|
||||
typeToString(t), $result)
|
||||
|
||||
proc hashProc(s: PSym; conf: ConfigRef): SigHash =
|
||||
var c: MD5Context
|
||||
result = default(SigHash)
|
||||
var c: MD5Context = default(MD5Context)
|
||||
md5Init c
|
||||
hashType c, s.typ, {CoProc}, conf
|
||||
|
||||
@@ -289,7 +291,8 @@ proc hashProc(s: PSym; conf: ConfigRef): SigHash =
|
||||
md5Final c, result.MD5Digest
|
||||
|
||||
proc hashNonProc*(s: PSym): SigHash =
|
||||
var c: MD5Context
|
||||
result = default(SigHash)
|
||||
var c: MD5Context = default(MD5Context)
|
||||
md5Init c
|
||||
hashSym(c, s)
|
||||
var it = s
|
||||
@@ -305,7 +308,8 @@ proc hashNonProc*(s: PSym): SigHash =
|
||||
md5Final c, result.MD5Digest
|
||||
|
||||
proc hashOwner*(s: PSym): SigHash =
|
||||
var c: MD5Context
|
||||
result = default(SigHash)
|
||||
var c: MD5Context = default(MD5Context)
|
||||
md5Init c
|
||||
var m = s
|
||||
while m.kind != skModule: m = m.owner
|
||||
@@ -378,7 +382,7 @@ proc symBodyDigest*(graph: ModuleGraph, sym: PSym): SigHash =
|
||||
graph.symBodyHashes.withValue(sym.id, value):
|
||||
return value[]
|
||||
|
||||
var c: MD5Context
|
||||
var c: MD5Context = default(MD5Context)
|
||||
md5Init(c)
|
||||
c.hashType(sym.typ, {CoProc}, graph.config)
|
||||
c &= char(sym.kind)
|
||||
|
||||
@@ -213,16 +213,17 @@ proc sumGeneric(t: PType): int =
|
||||
case t.kind
|
||||
of tyAlias, tySink, tyNot: t = t.lastSon
|
||||
of tyArray, tyRef, tyPtr, tyDistinct, tyUncheckedArray,
|
||||
tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody,
|
||||
tyOpenArray, tyVarargs, tySet, tyRange, tySequence,
|
||||
tyLent, tyOwned, tyVar:
|
||||
t = t.lastSon
|
||||
inc result
|
||||
of tyBool, tyChar, tyEnum, tyObject, tyPointer, tyVoid,
|
||||
tyString, tyCstring, tyInt..tyInt64, tyFloat..tyFloat128,
|
||||
tyUInt..tyUInt64, tyCompositeTypeClass, tyBuiltInTypeClass,
|
||||
tyGenericParam:
|
||||
tyUInt..tyUInt64, tyCompositeTypeClass, tyBuiltInTypeClass:
|
||||
inc result
|
||||
break
|
||||
of tyGenericBody:
|
||||
t = t.typeBodyImpl
|
||||
of tyGenericInst, tyStatic:
|
||||
t = t[0]
|
||||
inc result
|
||||
@@ -237,6 +238,12 @@ proc sumGeneric(t: PType): int =
|
||||
t = t.lastSon
|
||||
if t.kind == tyEmpty: break
|
||||
inc result
|
||||
of tyGenericParam:
|
||||
if t.len > 0:
|
||||
t = t.skipModifier
|
||||
else:
|
||||
inc result
|
||||
break
|
||||
of tyUntyped, tyTyped: break
|
||||
of tyGenericInvocation, tyTuple, tyProc, tyAnd:
|
||||
result += ord(t.kind == tyAnd)
|
||||
@@ -372,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:
|
||||
@@ -466,34 +474,40 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
|
||||
else: result = isIntConv
|
||||
else: result = isNone
|
||||
|
||||
proc getObjectType(f: PType): PType =
|
||||
proc reduceToBase(f: PType): PType =
|
||||
#[
|
||||
Returns a type that is f's effective typeclass. This is usually just one level deeper
|
||||
in the hierarchy of generality for a type. `object`, `ref object`, `enum` and user defined
|
||||
tyObjects are common return values.
|
||||
Returns the lowest order (most general) type that that is compatible with the input.
|
||||
E.g.
|
||||
A[T] = ptr object ... A -> ptr object
|
||||
A[N: static[int]] = array[N, int] ... A -> array
|
||||
]#
|
||||
case f.kind:
|
||||
of tyGenericParam:
|
||||
if f.len <= 0 or f.skipModifier == nil:
|
||||
result = f
|
||||
else:
|
||||
result = reduceToBase(f.skipModifier)
|
||||
of tyGenericInvocation:
|
||||
result = getObjectType(f[0])
|
||||
result = reduceToBase(f.baseClass)
|
||||
of tyCompositeTypeClass, tyAlias:
|
||||
if f.len <= 0 or f[0] == nil:
|
||||
result = f
|
||||
else:
|
||||
result = getObjectType(f[0])
|
||||
of tyGenericBody, tyGenericInst:
|
||||
result = getObjectType(f.lastSon)
|
||||
result = reduceToBase(f.elementType)
|
||||
of tyGenericInst:
|
||||
result = reduceToBase(f.skipModifier)
|
||||
of tyGenericBody:
|
||||
result = reduceToBase(f.typeBodyImpl)
|
||||
of tyUserTypeClass:
|
||||
if f.isResolvedUserTypeClass:
|
||||
result = f.base # ?? idk if this is right
|
||||
else:
|
||||
result = f.lastSon
|
||||
of tyStatic, tyOwned, tyVar, tyLent, tySink:
|
||||
result = getObjectType(f.base)
|
||||
result = reduceToBase(f.base)
|
||||
of tyInferred:
|
||||
# This is not true "After a candidate type is selected"
|
||||
result = getObjectType(f.base)
|
||||
of tyTyped, tyUntyped, tyFromExpr:
|
||||
result = f
|
||||
result = reduceToBase(f.base)
|
||||
of tyRange:
|
||||
result = f.lastSon
|
||||
else:
|
||||
@@ -1207,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:
|
||||
@@ -1269,14 +1288,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
result = typeRel(c, f.base, aOrig, flags + {trNoCovariance})
|
||||
subtypeCheck()
|
||||
of tyArray:
|
||||
a = getObjectType(a)
|
||||
case a.kind
|
||||
of tyArray:
|
||||
a = reduceToBase(a)
|
||||
if a.kind == tyArray:
|
||||
var fRange = f[0]
|
||||
var aRange = a[0]
|
||||
if fRange.kind in {tyGenericParam, tyAnything}:
|
||||
var prev = PType(idTableGet(c.bindings, fRange))
|
||||
if prev == nil:
|
||||
if typeRel(c, fRange, aRange) == isNone:
|
||||
return isNone
|
||||
put(c, fRange, a[0])
|
||||
fRange = a
|
||||
else:
|
||||
@@ -1289,7 +1309,6 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
result = isGeneric
|
||||
else:
|
||||
result = typeRel(c, ff, aa, flags)
|
||||
|
||||
if result < isGeneric:
|
||||
if nimEnableCovariance and
|
||||
trNoCovariance notin flags and
|
||||
@@ -1300,6 +1319,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
return isNone
|
||||
|
||||
if fRange.rangeHasUnresolvedStatic:
|
||||
if aRange.kind in {tyGenericParam} and aRange.reduceToBase() == aRange:
|
||||
return
|
||||
return inferStaticsInRange(c, fRange, a)
|
||||
elif c.c.matchedConcept != nil and aRange.rangeHasUnresolvedStatic:
|
||||
return inferStaticsInRange(c, aRange, f)
|
||||
@@ -1308,7 +1329,6 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
else:
|
||||
if lengthOrd(c.c.config, fRange) != lengthOrd(c.c.config, aRange):
|
||||
result = isNone
|
||||
else: discard
|
||||
of tyUncheckedArray:
|
||||
if a.kind == tyUncheckedArray:
|
||||
result = typeRel(c, base(f), base(a), flags)
|
||||
@@ -1395,7 +1415,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
let effectiveArgType = if useTypeLoweringRuleInTypeClass:
|
||||
a
|
||||
else:
|
||||
getObjectType(a)
|
||||
reduceToBase(a)
|
||||
if effectiveArgType.kind == tyObject:
|
||||
if sameObjectTypes(f, effectiveArgType):
|
||||
c.inheritancePenalty = if tfFinal in f.flags: -1 else: 0
|
||||
@@ -1426,7 +1446,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
result = isNone
|
||||
|
||||
of tyPtr, tyRef:
|
||||
a = getObjectType(a)
|
||||
a = reduceToBase(a)
|
||||
if a.kind == f.kind:
|
||||
# ptr[R, T] can be passed to ptr[T], but not the other way round:
|
||||
if a.len < f.len: return isNone
|
||||
@@ -1728,10 +1748,13 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
considerPreviousT:
|
||||
let target = f[0]
|
||||
let targetKind = target.kind
|
||||
var effectiveArgType = getObjectType(a)
|
||||
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}:
|
||||
@@ -1846,10 +1869,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
a.sym.transitionGenericParamToType()
|
||||
a.flags.excl tfWildcard
|
||||
elif doBind:
|
||||
# The mechanics of `doBind` being a flag that also denotes sig cmp via
|
||||
# negation is potentially problematic. `IsNone` is appropriate for
|
||||
# preventing illegal bindings, but it is not necessarily appropriate
|
||||
# before the bindings have been finalized.
|
||||
# careful: `trDontDont` (set by `checkGeneric`) is not always respected in this call graph.
|
||||
# typRel having two different modes (binding and non-binding) can make things harder to
|
||||
# reason about and maintain. Refactoring typeRel to not be responsible for setting, or
|
||||
# at least validating, bindings can have multiple benefits. This is debatable. I'm not 100% sure.
|
||||
# A design that allows a proper complexity analysis of types like `tyOr` would be ideal.
|
||||
concrete = concreteType(c, a, f)
|
||||
if concrete == nil:
|
||||
return isNone
|
||||
@@ -2080,7 +2104,9 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
dest = generateTypeInstance(c, m.bindings, arg, dest)
|
||||
let fdest = typeRel(m, f, dest)
|
||||
if fdest in {isEqual, isGeneric} and not (dest.kind == tyLent and f.kind in {tyVar}):
|
||||
markUsed(c, arg.info, c.converters[i])
|
||||
# can't fully mark used yet, may not be used in final call
|
||||
incl(c.converters[i].flags, sfUsed)
|
||||
markOwnerModuleAsUsed(c, c.converters[i])
|
||||
var s = newSymNode(c.converters[i])
|
||||
s.typ = c.converters[i].typ
|
||||
s.info = arg.info
|
||||
@@ -2401,9 +2427,9 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
||||
# roll back the side effects of the unification algorithm.
|
||||
let c = m.c
|
||||
var
|
||||
x = newCandidate(c, m.callee)
|
||||
y = newCandidate(c, m.callee)
|
||||
z = newCandidate(c, m.callee)
|
||||
x = newCandidate(c, m.callee) # potential "best"
|
||||
y = newCandidate(c, m.callee) # potential competitor with x
|
||||
z = newCandidate(c, m.callee) # buffer for copies of m
|
||||
x.calleeSym = m.calleeSym
|
||||
y.calleeSym = m.calleeSym
|
||||
z.calleeSym = m.calleeSym
|
||||
|
||||
@@ -57,7 +57,7 @@ proc parsePipe(filename: AbsoluteFile, inputStream: PLLStream; cache: IdentCache
|
||||
else:
|
||||
inc(i, 2)
|
||||
while i < line.len and line[i] in Whitespace: inc(i)
|
||||
var p: Parser
|
||||
var p: Parser = default(Parser)
|
||||
openParser(p, filename, llStreamOpen(substr(line, i)), cache, config)
|
||||
result = parseAll(p)
|
||||
closeParser(p)
|
||||
|
||||
@@ -100,12 +100,19 @@ proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode =
|
||||
else:
|
||||
result = newSymNode(r)
|
||||
|
||||
proc transform(c: PTransf, n: PNode): PNode
|
||||
proc transform(c: PTransf, n: PNode, noConstFold = false): PNode
|
||||
|
||||
proc transformSons(c: PTransf, n: PNode): PNode =
|
||||
proc transformSons(c: PTransf, n: PNode, noConstFold = false): PNode =
|
||||
result = newTransNode(n)
|
||||
for i in 0..<n.len:
|
||||
result[i] = transform(c, n[i])
|
||||
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)
|
||||
@@ -470,8 +477,8 @@ proc transformYield(c: PTransf, n: PNode): PNode =
|
||||
result.add(introduceNewLocalVars(c, c.transCon.forLoopBody))
|
||||
c.isIntroducingNewLocalVars = false
|
||||
|
||||
proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds): PNode =
|
||||
result = transformSons(c, n)
|
||||
proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds, isAddr = false): PNode =
|
||||
result = transformSons(c, n, noConstFold = isAddr)
|
||||
# inlining of 'var openarray' iterators; bug #19977
|
||||
if n.typ.kind != tyOpenArray and (c.graph.config.backend == backendCpp or sfCompileToCpp in c.module.flags): return
|
||||
var n = result
|
||||
@@ -497,7 +504,17 @@ proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds): PNode =
|
||||
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
|
||||
@@ -875,10 +901,6 @@ proc transformCall(c: PTransf, n: PNode): PNode =
|
||||
inc(j)
|
||||
result.add(a)
|
||||
if result.len == 2: result = result[1]
|
||||
elif magic == mAddr:
|
||||
result = newTransNode(nkAddr, n, 1)
|
||||
result[0] = n[1]
|
||||
result = transformAddrDeref(c, result, {nkDerefExpr, nkHiddenDeref})
|
||||
elif magic in {mNBindSym, mTypeOf, mRunnableExamples}:
|
||||
# for bindSym(myconst) we MUST NOT perform constant folding:
|
||||
result = n
|
||||
@@ -973,7 +995,7 @@ proc transformDerefBlock(c: PTransf, n: PNode): PNode =
|
||||
result[i] = e0[i]
|
||||
result[e0.len-1] = newTreeIT(nkHiddenDeref, n.info, n.typ, e0[e0.len-1])
|
||||
|
||||
proc transform(c: PTransf, n: PNode): PNode =
|
||||
proc transform(c: PTransf, n: PNode, noConstFold = false): PNode =
|
||||
when false:
|
||||
var oldDeferAnchor: PNode
|
||||
if n.kind in {nkElifBranch, nkOfBranch, nkExceptBranch, nkElifExpr,
|
||||
@@ -1039,10 +1061,8 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||
of nkBreakStmt: result = transformBreak(c, n)
|
||||
of nkCallKinds:
|
||||
result = transformCall(c, n)
|
||||
of nkHiddenAddr:
|
||||
result = transformAddrDeref(c, n, {nkHiddenDeref})
|
||||
of nkAddr:
|
||||
result = transformAddrDeref(c, n, {nkDerefExpr, nkHiddenDeref})
|
||||
of nkAddr, nkHiddenAddr:
|
||||
result = transformAddrDeref(c, n, {nkDerefExpr, nkHiddenDeref}, isAddr = true)
|
||||
of nkDerefExpr:
|
||||
result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
|
||||
of nkHiddenDeref:
|
||||
@@ -1054,6 +1074,9 @@ proc transform(c: PTransf, n: PNode): 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:
|
||||
@@ -1122,7 +1145,7 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||
let exprIsPointerCast = n.kind in {nkCast, nkConv, nkHiddenStdConv} and
|
||||
n.typ != nil and
|
||||
n.typ.kind == tyPointer
|
||||
if not exprIsPointerCast:
|
||||
if not exprIsPointerCast and not noConstFold:
|
||||
var cnst = getConstExpr(c.module, result, c.idgen, c.graph)
|
||||
# we inline constants if they are not complex constants:
|
||||
if cnst != nil and not dontInlineConstant(n, cnst):
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -117,7 +117,7 @@ proc isPureObject*(typ: PType): bool =
|
||||
proc isUnsigned*(t: PType): bool =
|
||||
t.skipTypes(abstractInst).kind in {tyChar, tyUInt..tyUInt64}
|
||||
|
||||
proc getOrdValue*(n: PNode; onError = high(Int128)): Int128 =
|
||||
proc getOrdValueAux*(n: PNode, err: var bool): Int128 =
|
||||
var k = n.kind
|
||||
if n.typ != nil and n.typ.skipTypes(abstractInst).kind in {tyChar, tyUInt..tyUInt64}:
|
||||
k = nkUIntLit
|
||||
@@ -133,13 +133,22 @@ proc getOrdValue*(n: PNode; onError = high(Int128)): Int128 =
|
||||
toInt128(n.intVal)
|
||||
of nkNilLit:
|
||||
int128.Zero
|
||||
of nkHiddenStdConv: getOrdValue(n[1], onError)
|
||||
of nkHiddenStdConv:
|
||||
getOrdValueAux(n[1], err)
|
||||
else:
|
||||
# XXX: The idea behind the introduction of int128 was to finally
|
||||
# have all calculations numerically far away from any
|
||||
# overflows. This command just introduces such overflows and
|
||||
# should therefore really be revisited.
|
||||
onError
|
||||
err = true
|
||||
int128.Zero
|
||||
|
||||
proc getOrdValue*(n: PNode): Int128 =
|
||||
var err: bool = false
|
||||
result = getOrdValueAux(n, err)
|
||||
#assert err == false
|
||||
|
||||
proc getOrdValue*(n: PNode, onError: Int128): Int128 =
|
||||
var err = false
|
||||
result = getOrdValueAux(n, err)
|
||||
if err:
|
||||
result = onError
|
||||
|
||||
proc getFloatValue*(n: PNode): BiggestFloat =
|
||||
case n.kind
|
||||
@@ -1217,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,
|
||||
@@ -1234,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,
|
||||
@@ -2375,8 +2375,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
|
||||
|
||||
@@ -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)
|
||||
@@ -1556,6 +1559,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 +1649,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 +1949,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 +2014,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 +2162,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 +2219,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 +2256,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:
|
||||
|
||||
@@ -286,7 +286,7 @@ proc loadAny(p: var JsonParser, t: PType,
|
||||
|
||||
proc loadAny*(s: string; t: PType; cache: IdentCache; conf: ConfigRef; idgen: IdGenerator): PNode =
|
||||
var tab = initTable[BiggestInt, PNode]()
|
||||
var p: JsonParser
|
||||
var p: JsonParser = default(JsonParser)
|
||||
open(p, newStringStream(s), "unknown file")
|
||||
next(p)
|
||||
result = loadAny(p, t, tab, cache, conf, idgen)
|
||||
|
||||
@@ -2634,7 +2634,9 @@ of the argument.
|
||||
range.
|
||||
3. Generic match: `f` is a generic type and `a` matches, for
|
||||
instance `a` is `int` and `f` is a generic (constrained) parameter
|
||||
type (like in `[T]` or `[T: int|char]`).
|
||||
type (like in `[T]` or `[T: int|char]`). Constraints given an alias (as in `T`)
|
||||
shall be used to define `f`, when `f` is composed of `T`, following simple variable
|
||||
substitution.
|
||||
4. Subrange or subtype match: `a` is a `range[T]` and `T`
|
||||
matches `f` exactly. Or: `a` is a subtype of `f`.
|
||||
5. Integral conversion match: `a` is convertible to `f` and `f` and `a`
|
||||
@@ -2646,9 +2648,8 @@ of the argument.
|
||||
There are two major methods of selecting the best matching candidate, namely
|
||||
counting and disambiguation. Counting takes precedence to disambiguation. In counting,
|
||||
each parameter is given a category and the number of parameters in each category is counted.
|
||||
The categories are listed above and are in order of precedence. For example, if
|
||||
a candidate with one exact match is compared to a candidate with multiple generic matches
|
||||
and zero exact matches, the candidate with an exact match will win.
|
||||
For example, if a candidate with one exact match is compared to a candidate with multiple
|
||||
generic matches and zero exact matches, the candidate with an exact match will win.
|
||||
|
||||
In the following, `count(p, m)` counts the number of matches of the matching category `m`
|
||||
for the routine `p`.
|
||||
@@ -2668,10 +2669,12 @@ algorithm returns true:
|
||||
return "ambiguous"
|
||||
```
|
||||
|
||||
When counting is ambiguous, disambiguation begins. Parameters are iterated
|
||||
by position and these parameter pairs are compared for their type relation. The general goal
|
||||
of this comparison is to determine which parameter is more specific. The types considered are
|
||||
not of the inputs from the callsite, but of the competing candidates' parameters.
|
||||
When counting is ambiguous, disambiguation begins. Disambiguation also has two stages, first a
|
||||
hierarchical type relation comparison, and if that is inconclusive, a complexity comparison.
|
||||
Where counting relates the type of the operand to the formal parameter, disambiguation relates the
|
||||
formal parameters with each other to find the most competitive choice.
|
||||
Parameters are iterated by position and these parameter pairs are compared for their type
|
||||
relation. The general goal of this comparison is to determine which parameter is least general.
|
||||
|
||||
|
||||
Some examples:
|
||||
@@ -2691,7 +2694,6 @@ Some examples:
|
||||
```
|
||||
|
||||
|
||||
If this algorithm returns "ambiguous" further disambiguation is performed:
|
||||
If the argument `a` matches both the parameter type `f` of `p`
|
||||
and `g` of `q` via a subtyping relation, the inheritance depth is taken
|
||||
into account:
|
||||
@@ -2733,6 +2735,23 @@ matches) is preferred:
|
||||
gen(ri) # "ref T"
|
||||
```
|
||||
|
||||
Type variables match
|
||||
----------------------
|
||||
|
||||
When overload resolution is considering candidates, the type variable's definition
|
||||
is not overlooked as it is used to define the formal parameter's type via variable substitution.
|
||||
|
||||
For example:
|
||||
```nim
|
||||
type A
|
||||
proc p[T: A](param: T)
|
||||
proc p[T: object](param: T)
|
||||
```
|
||||
|
||||
These signatures are not ambiguous for an instance of `A` even though the formal parameters match ("T" == "T").
|
||||
Instead `T` is treated as a variable in that (`T` ?= `T`) depending on the bound type of `T` at the time of
|
||||
overload resolution.
|
||||
|
||||
|
||||
Overloading based on 'var T'
|
||||
--------------------------------------
|
||||
@@ -5064,7 +5083,7 @@ It is possible to raise/catch imported C++ exceptions. Types imported using
|
||||
`importcpp` can be raised or caught. Exceptions are raised by value and
|
||||
caught by reference. Example:
|
||||
|
||||
```nim test = "nim cpp -r $1"
|
||||
```nim
|
||||
type
|
||||
CStdException {.importcpp: "std::exception", header: "<exception>", inheritable.} = object
|
||||
## does not inherit from `RootObj`, so we use `inheritable` instead
|
||||
@@ -5077,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()
|
||||
```
|
||||
@@ -5422,6 +5441,7 @@ Generics are Nim's means to parametrize procs, iterators or types with
|
||||
`type parameters`:idx:. Depending on the context, the brackets are used either to
|
||||
introduce type parameters or to instantiate a generic proc, iterator, or type.
|
||||
|
||||
|
||||
The following example shows how a generic binary tree can be modeled:
|
||||
|
||||
```nim test = "nim c $1"
|
||||
|
||||
26
koch.nim
26
koch.nim
@@ -1,17 +1,17 @@
|
||||
#
|
||||
#
|
||||
# Maintenance program for Nim
|
||||
# (c) Copyright 2017 Andreas Rumpf
|
||||
# (c) Copyright 2024 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
# See doc/koch.txt for documentation.
|
||||
# See doc/koch.md for documentation.
|
||||
#
|
||||
|
||||
const
|
||||
# examples of possible values for repos: Head, ea82b54
|
||||
NimbleStableCommit = "4fb6f8e6c33963f6f510fe82d09ad2a61b5e4265" # 0.16.1
|
||||
NimbleStableCommit = "123f97a5e4ee9ba35720c0869e19a047c43c797e" # 0.16.4
|
||||
AtlasStableCommit = "5faec3e9a33afe99a7d22377dd1b45a5391f5504"
|
||||
ChecksumsStableCommit = "bd9bf4eaea124bf8d01e08f92ac1b14c6879d8d3"
|
||||
SatStableCommit = "faf1617f44d7632ee9601ebc13887644925dcc01"
|
||||
@@ -52,7 +52,7 @@ const
|
||||
+-----------------------------------------------------------------+
|
||||
| Maintenance program for Nim |
|
||||
| Version $1|
|
||||
| (c) 2017 Andreas Rumpf |
|
||||
| (c) 2024 Andreas Rumpf |
|
||||
+-----------------------------------------------------------------+
|
||||
Build time: $2, $3
|
||||
|
||||
@@ -77,6 +77,7 @@ Possible Commands:
|
||||
doesn't require network connectivity
|
||||
nimble builds the Nimble tool
|
||||
atlas builds the Atlas tool
|
||||
checksums installs the checksums dependency
|
||||
fusion installs fusion via Nimble
|
||||
|
||||
Boot options:
|
||||
@@ -155,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
|
||||
@@ -325,8 +325,7 @@ proc boot(args: string, skipIntegrityCheck: bool) =
|
||||
let smartNimcache = (if "release" in args or "danger" in args: "nimcache/r_" else: "nimcache/d_") &
|
||||
hostOS & "_" & hostCPU
|
||||
|
||||
if not dirExists("dist/checksums"):
|
||||
bundleChecksums(false)
|
||||
bundleChecksums(false)
|
||||
|
||||
let nimStart = findStartNim().quoteShell()
|
||||
let times = 2 - ord(skipIntegrityCheck)
|
||||
@@ -481,8 +480,7 @@ proc temp(args: string) =
|
||||
result[1].add " " & quoteShell(args[i])
|
||||
inc i
|
||||
|
||||
if not dirExists("dist/checksums"):
|
||||
bundleChecksums(false)
|
||||
bundleChecksums(false)
|
||||
|
||||
let d = getAppDir()
|
||||
let output = d / "compiler" / "nim".exe
|
||||
|
||||
@@ -503,7 +503,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 +1095,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
|
||||
|
||||
@@ -1414,7 +1414,7 @@ proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool =
|
||||
doAssert a.hasKey('a') == true
|
||||
doAssert a.hasKey('z') == false
|
||||
|
||||
var hc: Hash
|
||||
var hc: Hash = default(Hash)
|
||||
result = rawGet(t, key, hc) >= 0
|
||||
|
||||
proc contains*[A, B](t: OrderedTable[A, B], key: A): bool =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -72,6 +72,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 +176,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)
|
||||
|
||||
@@ -10,7 +10,7 @@ const
|
||||
## is the minor number of Nim's version.
|
||||
## Odd for devel, even for releases.
|
||||
|
||||
NimPatch* {.intdefine.}: int = 10
|
||||
NimPatch* {.intdefine.}: int = 16
|
||||
## is the patch number of Nim's version.
|
||||
## Odd for devel, even for releases.
|
||||
|
||||
|
||||
@@ -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) =
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -103,7 +103,8 @@ proc dllTests(r: var TResults, cat: Category, options: string) =
|
||||
runBasicDLLTest c, r, cat, options & " -d:release --mm:refc"
|
||||
runBasicDLLTest c, r, cat, options, isOrc = true
|
||||
runBasicDLLTest c, r, cat, options & " -d:release", isOrc = true
|
||||
when not defined(windows):
|
||||
when not defined(windows) and not defined(osx):
|
||||
# boehm library linking broken on macos 13
|
||||
# still cannot find a recent Windows version of boehm.dll:
|
||||
runBasicDLLTest c, r, cat, options & " --gc:boehm"
|
||||
runBasicDLLTest c, r, cat, options & " -d:release --gc:boehm"
|
||||
@@ -130,7 +131,8 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
|
||||
|
||||
template test(filename: untyped) =
|
||||
testWithoutBoehm filename
|
||||
when not defined(windows) and not defined(android):
|
||||
when not defined(windows) and not defined(android) and not defined(osx):
|
||||
# boehm library linking broken on macos 13
|
||||
# AR: cannot find any boehm.dll on the net, right now, so disabled
|
||||
# for windows:
|
||||
testSpec r, makeTest("tests/gc" / filename, options &
|
||||
@@ -444,7 +446,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
|
||||
|
||||
@@ -460,21 +462,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)
|
||||
@@ -563,6 +565,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"
|
||||
@@ -43,10 +43,8 @@ pkg "awk"
|
||||
pkg "bigints"
|
||||
pkg "binaryheap", "nim c -r binaryheap.nim"
|
||||
pkg "BipBuffer"
|
||||
pkg "blscurve", allowFailure = true
|
||||
pkg "bncurve"
|
||||
pkg "brainfuck", "nim c -d:release -r tests/compile.nim"
|
||||
pkg "bump", "nim c --mm:arc --path:. -r tests/tbump.nim", "https://github.com/disruptek/bump", allowFailure = true
|
||||
pkg "c2nim", "nim c testsuite/tester.nim"
|
||||
pkg "cascade"
|
||||
pkg "cello", url = "https://github.com/nim-lang/cello", useHead = true
|
||||
@@ -58,28 +56,23 @@ pkg "cligen", "nim c --path:. -r cligen.nim"
|
||||
pkg "combparser", "nimble test --mm:orc"
|
||||
pkg "compactdict"
|
||||
pkg "comprehension", "nimble test", "https://github.com/alehander92/comprehension"
|
||||
pkg "cowstrings"
|
||||
pkg "criterion", allowFailure = true # needs testing binary
|
||||
pkg "datamancer"
|
||||
pkg "confutils", "nimble install -y toml_serialization json_serialization unittest2; nimble test"
|
||||
pkg "constantine", "nimble make_lib"
|
||||
pkg "criterion"
|
||||
pkg "dashing", "nim c tests/functional.nim"
|
||||
pkg "delaunay"
|
||||
pkg "dnsclient", allowFailure = true # super fragile
|
||||
pkg "docopt"
|
||||
pkg "dotenv"
|
||||
# when defined(linux): pkg "drchaos"
|
||||
pkg "easygl", "nim c -o:egl -r src/easygl.nim", "https://github.com/jackmott/easygl"
|
||||
pkg "elvis"
|
||||
pkg "eth", "nim c -o:common -r tests/common/all_tests"
|
||||
pkg "faststreams"
|
||||
pkg "fidget"
|
||||
pkg "fragments", "nim c -r fragments/dsl.nim", allowFailure = true # pending https://github.com/nim-lang/packages/issues/2115
|
||||
pkg "fusion"
|
||||
pkg "gara"
|
||||
pkg "glob"
|
||||
pkg "ggplotnim", "nim c -d:noCairo -r tests/tests.nim"
|
||||
pkg "gittyup", "nimble test", "https://github.com/disruptek/gittyup", allowFailure = true
|
||||
pkg "glob"
|
||||
pkg "gnuplot", "nim c gnuplot.nim"
|
||||
# pkg "gram", "nim c -r --mm:arc --define:danger tests/test.nim", "https://github.com/disruptek/gram"
|
||||
# pending https://github.com/nim-lang/Nim/issues/16509
|
||||
pkg "hts", "nim c -o:htss src/hts.nim"
|
||||
pkg "httpauth"
|
||||
pkg "httputils"
|
||||
@@ -92,22 +85,27 @@ pkg "json_serialization"
|
||||
pkg "jstin"
|
||||
pkg "karax", "nim c -r tests/tester.nim"
|
||||
pkg "kdtree", "nimble test -d:nimLegacyRandomInitRand", "https://github.com/jblindsay/kdtree"
|
||||
pkg "loopfusion"
|
||||
pkg "lockfreequeues"
|
||||
pkg "loopfusion"
|
||||
pkg "macroutils"
|
||||
pkg "manu"
|
||||
pkg "markdown"
|
||||
pkg "measuremancer", "nimble testDeps; nimble -y test"
|
||||
# when unchained is version 0.3.7 or higher, use `nimble testDeps;`
|
||||
pkg "memo"
|
||||
pkg "metrics"
|
||||
pkg "msgpack4nim", "nim c -r tests/test_spec.nim"
|
||||
pkg "nake", "nim c nakefile.nim"
|
||||
pkg "nat_traversal"
|
||||
pkg "neo", "nim c -d:blas=openblas --mm:refc tests/all.nim"
|
||||
pkg "nesm", "nimble tests", "https://github.com/nim-lang/NESM", useHead = true
|
||||
pkg "netty"
|
||||
pkg "nico", allowFailure = true
|
||||
pkg "nicy", "nim c -r src/nicy.nim"
|
||||
pkg "nigui", "nim c -o:niguii -r src/nigui.nim"
|
||||
when defined(osx):
|
||||
# gives "could not load: libgtk-3.0.dylib" on macos 13
|
||||
# just test compiling instead of running
|
||||
pkg "nigui", "nim c -o:niguii src/nigui.nim"
|
||||
else:
|
||||
pkg "nigui", "nim c -o:niguii -r src/nigui.nim"
|
||||
pkg "nimcrypto", "nim r --path:. tests/testall.nim" # `--path:.` workaround needed, see D20210308T165435
|
||||
pkg "NimData", "nim c -o:nimdataa src/nimdata.nim"
|
||||
pkg "nimes", "nim c src/nimes.nim"
|
||||
@@ -117,16 +115,13 @@ pkg "nimgen", "nim c -o:nimgenn -r src/nimgen/runcfg.nim"
|
||||
pkg "nimib"
|
||||
pkg "nimlsp"
|
||||
pkg "nimly", "nim c -r tests/test_readme_example.nim"
|
||||
pkg "nimongo", "nimble test_ci", allowFailure = true
|
||||
pkg "nimph", "nimble test", "https://github.com/disruptek/nimph", allowFailure = true
|
||||
pkg "nimPNG", useHead = true
|
||||
pkg "nimpy", "nim c -r tests/nimfrompy.nim"
|
||||
pkg "nimquery"
|
||||
pkg "nimsl"
|
||||
pkg "nimsvg"
|
||||
pkg "nimterop", "nimble minitest", url = "https://github.com/nim-lang/nimterop"
|
||||
pkg "nimwc", "nim c nimwc.nim", allowFailure = true
|
||||
pkg "nimx", "nim c test/main.nim", allowFailure = true
|
||||
pkg "nimwc", "nim c nimwc.nim"
|
||||
pkg "nitter", "nim c src/nitter.nim", "https://github.com/zedeus/nitter"
|
||||
pkg "norm", "testament r tests/common/tmodel.nim"
|
||||
pkg "normalize"
|
||||
@@ -156,9 +151,8 @@ pkg "sigv4", "nim c --mm:arc -r sigv4.nim", "https://github.com/disruptek/sigv4"
|
||||
pkg "sim"
|
||||
pkg "smtp", "nimble compileExample"
|
||||
pkg "snip", "nimble test", "https://github.com/genotrance/snip"
|
||||
pkg "ssostrings"
|
||||
pkg "stew"
|
||||
pkg "stint", "nim c stint.nim"
|
||||
pkg "stint", "nimble test_internal"
|
||||
pkg "strslice"
|
||||
pkg "strunicode", "nim c -r --mm:refc src/strunicode.nim"
|
||||
pkg "supersnappy"
|
||||
@@ -174,17 +168,16 @@ pkg "testutils"
|
||||
pkg "timeit"
|
||||
pkg "timezones"
|
||||
pkg "tiny_sqlite"
|
||||
pkg "toml_serialization", "nimble install -y stint unittest2; nimble test"
|
||||
pkg "unicodedb", "nim c -d:release -r tests/tests.nim"
|
||||
pkg "unicodeplus", "nim c -d:release -r tests/tests.nim"
|
||||
pkg "union", "nim c -r tests/treadme.nim", url = "https://github.com/alaviss/union"
|
||||
pkg "unittest2"
|
||||
pkg "unpack"
|
||||
pkg "weave", "nimble test_gc_arc", useHead = true
|
||||
pkg "websock"
|
||||
pkg "websock", "nim c -d:chronosStrictException -d:chronicles_log_level=INFO --mm:refc tests/all_tests.nim"
|
||||
pkg "websocket", "nim c websocket.nim"
|
||||
pkg "winim", "nim c winim.nim"
|
||||
pkg "with"
|
||||
pkg "ws", allowFailure = true
|
||||
pkg "yaml"
|
||||
pkg "zero_functional", "nim c -r test.nim"
|
||||
pkg "zippy"
|
||||
|
||||
@@ -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)
|
||||
|
||||
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)
|
||||
@@ -2,6 +2,7 @@ discard """
|
||||
cmd: "nim c --gc:boehm $options $file"
|
||||
output: '''meep'''
|
||||
disabled: "windows"
|
||||
disabled: osx
|
||||
"""
|
||||
|
||||
proc callit(it: proc ()) =
|
||||
|
||||
57
tests/concepts/t976.nim
Normal file
57
tests/concepts/t976.nim
Normal file
@@ -0,0 +1,57 @@
|
||||
discard """
|
||||
output: '''
|
||||
Printable
|
||||
'''
|
||||
joinable: false
|
||||
"""
|
||||
|
||||
#[
|
||||
The converter is a proper example of a confounding variable
|
||||
Moved to an isolated file
|
||||
]#
|
||||
|
||||
type
|
||||
Obj1[T] = object
|
||||
v: T
|
||||
converter toObj1[T](t: T): Obj1[T] =
|
||||
return Obj1[T](v: t)
|
||||
block t976:
|
||||
type
|
||||
int1 = distinct int
|
||||
int2 = distinct int
|
||||
int1g = concept x
|
||||
x is int1
|
||||
int2g = concept x
|
||||
x is int2
|
||||
|
||||
proc take[T: int1g](value: int1) =
|
||||
when T is int2:
|
||||
static: error("killed in take(int1)")
|
||||
|
||||
proc take[T: int2g](vale: int2) =
|
||||
when T is int1:
|
||||
static: error("killed in take(int2)")
|
||||
|
||||
var i1: int1 = 1.int1
|
||||
var i2: int2 = 2.int2
|
||||
|
||||
take[int1](i1)
|
||||
take[int2](i2)
|
||||
|
||||
template reject(e) =
|
||||
static: assert(not compiles(e))
|
||||
|
||||
reject take[string](i2)
|
||||
reject take[int1](i2)
|
||||
|
||||
# bug #6249
|
||||
type
|
||||
Obj2 = ref object
|
||||
PrintAble = concept x
|
||||
$x is string
|
||||
|
||||
proc `$`[T](nt: Obj1[T]): string =
|
||||
when T is PrintAble: result = "Printable"
|
||||
else: result = "Non Printable"
|
||||
|
||||
echo Obj2()
|
||||
@@ -1,7 +1,6 @@
|
||||
discard """
|
||||
output: '''
|
||||
20.0 USD
|
||||
Printable
|
||||
true
|
||||
true
|
||||
true
|
||||
@@ -78,55 +77,6 @@ block t3414:
|
||||
let s2 = s1.find(10)
|
||||
|
||||
|
||||
|
||||
type
|
||||
Obj1[T] = object
|
||||
v: T
|
||||
converter toObj1[T](t: T): Obj1[T] =
|
||||
return Obj1[T](v: t)
|
||||
block t976:
|
||||
type
|
||||
int1 = distinct int
|
||||
int2 = distinct int
|
||||
int1g = concept x
|
||||
x is int1
|
||||
int2g = concept x
|
||||
x is int2
|
||||
|
||||
proc take[T: int1g](value: int1) =
|
||||
when T is int2:
|
||||
static: error("killed in take(int1)")
|
||||
|
||||
proc take[T: int2g](vale: int2) =
|
||||
when T is int1:
|
||||
static: error("killed in take(int2)")
|
||||
|
||||
var i1: int1 = 1.int1
|
||||
var i2: int2 = 2.int2
|
||||
|
||||
take[int1](i1)
|
||||
take[int2](i2)
|
||||
|
||||
template reject(e) =
|
||||
static: assert(not compiles(e))
|
||||
|
||||
reject take[string](i2)
|
||||
reject take[int1](i2)
|
||||
|
||||
# bug #6249
|
||||
type
|
||||
Obj2 = ref object
|
||||
PrintAble = concept x
|
||||
$x is string
|
||||
|
||||
proc `$`[T](nt: Obj1[T]): string =
|
||||
when T is PrintAble: result = "Printable"
|
||||
else: result = "Non Printable"
|
||||
|
||||
echo Obj2()
|
||||
|
||||
|
||||
|
||||
block t1128:
|
||||
type
|
||||
TFooContainer[T] = object
|
||||
|
||||
14
tests/converter/tdeprecatedconverter.nim
Normal file
14
tests/converter/tdeprecatedconverter.nim
Normal file
@@ -0,0 +1,14 @@
|
||||
# issue #24241
|
||||
|
||||
{.warningAsError[Deprecated]: on.}
|
||||
|
||||
type X = distinct int
|
||||
|
||||
converter toInt(x: X): int{.deprecated.} = int(x)
|
||||
|
||||
template `==`(a, b: X): bool = false # this gets called so we didn't convert
|
||||
|
||||
doAssert not (X(1) == X(2))
|
||||
doAssert not compiles(X(1) + X(2))
|
||||
doAssert not (compiles do:
|
||||
let x: int = X(1))
|
||||
@@ -3,7 +3,6 @@ discard """
|
||||
output: '''
|
||||
6.0
|
||||
0'''
|
||||
disabled: "windows" # pending bug #18011
|
||||
"""
|
||||
|
||||
# bug #4730
|
||||
|
||||
@@ -3,7 +3,6 @@ discard """
|
||||
output: '''
|
||||
int
|
||||
float'''
|
||||
disabled: "windows" # pending bug #18011
|
||||
"""
|
||||
|
||||
import typetraits
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user