mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 19:03:42 +00:00
Compare commits
131 Commits
v1.0.6
...
version-1-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a1f77cb18 | ||
|
|
a57b1d7fac | ||
|
|
f577229a6f | ||
|
|
b057bb6654 | ||
|
|
af2b7ff28f | ||
|
|
f964fdbec0 | ||
|
|
d5a7fb8ea0 | ||
|
|
22e71cbc0f | ||
|
|
f40c941580 | ||
|
|
e5a3f30519 | ||
|
|
286b94e7de | ||
|
|
52155b5587 | ||
|
|
9edb694173 | ||
|
|
8be2614608 | ||
|
|
bd2b298244 | ||
|
|
311b7aaf37 | ||
|
|
a13fd00729 | ||
|
|
a8c706760c | ||
|
|
86298e30d9 | ||
|
|
19440baa80 | ||
|
|
a0d62e654a | ||
|
|
67d9848027 | ||
|
|
4663a261f9 | ||
|
|
69322f86de | ||
|
|
f29e7cfdcd | ||
|
|
bf85f35226 | ||
|
|
f76ed447c2 | ||
|
|
0ca09f64cf | ||
|
|
52ad63bc22 | ||
|
|
98073624f7 | ||
|
|
c32e002e63 | ||
|
|
5b920dc01f | ||
|
|
4234a6373a | ||
|
|
f6ada8874a | ||
|
|
4088d7f2ae | ||
|
|
ad29fe8946 | ||
|
|
52a3d38bda | ||
|
|
1b530b5897 | ||
|
|
9193c85b61 | ||
|
|
758a54ce23 | ||
|
|
cc49902fa2 | ||
|
|
8ec5dc1969 | ||
|
|
dc5e8fc39d | ||
|
|
37c3465081 | ||
|
|
f713c54166 | ||
|
|
dc519a539b | ||
|
|
acfd1b272d | ||
|
|
53fc3924a0 | ||
|
|
95d4961612 | ||
|
|
b5ec602763 | ||
|
|
9a649d91ad | ||
|
|
e6cdbad6a5 | ||
|
|
e79e0616b1 | ||
|
|
6b555e78b7 | ||
|
|
36619e3569 | ||
|
|
f4ae3ab729 | ||
|
|
289e35166b | ||
|
|
338f25b56f | ||
|
|
872795e18a | ||
|
|
58515f6042 | ||
|
|
59a35563cf | ||
|
|
66c21b9e95 | ||
|
|
94a855893e | ||
|
|
46c9eb5904 | ||
|
|
9cc5927a99 | ||
|
|
85fb709020 | ||
|
|
3483fdd43c | ||
|
|
507d7a9daa | ||
|
|
75f427a57b | ||
|
|
b0f71b051f | ||
|
|
b036c57dd3 | ||
|
|
339c08ce5b | ||
|
|
5c266cdf05 | ||
|
|
234f4a27e1 | ||
|
|
c7cf5d4e73 | ||
|
|
561092003d | ||
|
|
5b168d3f9b | ||
|
|
965f7ebf54 | ||
|
|
da7a6f4875 | ||
|
|
ff9d59747d | ||
|
|
6d5761d488 | ||
|
|
931a70b123 | ||
|
|
0c6c11f2aa | ||
|
|
d15cbb229a | ||
|
|
c90bbe3201 | ||
|
|
45b53ee36f | ||
|
|
20e5173cca | ||
|
|
46d785aa40 | ||
|
|
71027936e8 | ||
|
|
f89db4915f | ||
|
|
d4f961b08a | ||
|
|
8cf8879941 | ||
|
|
5a1ed8f4d4 | ||
|
|
fec5d04afc | ||
|
|
3dd84b36fd | ||
|
|
490bf10a6c | ||
|
|
50de7732ed | ||
|
|
df6fbf6521 | ||
|
|
5cae61ce21 | ||
|
|
122ac6775a | ||
|
|
73c83905af | ||
|
|
22d60a53f7 | ||
|
|
265f565be3 | ||
|
|
6673934482 | ||
|
|
8a8fddcc40 | ||
|
|
99e6d328ec | ||
|
|
2dcf32f5c8 | ||
|
|
6f79408576 | ||
|
|
17ae3016c7 | ||
|
|
02d7a181f6 | ||
|
|
349039678a | ||
|
|
b64e109fdc | ||
|
|
26681769e8 | ||
|
|
c160b2161e | ||
|
|
fbf28d1ce7 | ||
|
|
b6924383df | ||
|
|
cfd0ae4adb | ||
|
|
04e70f1f4b | ||
|
|
14e1f82f42 | ||
|
|
2304af294f | ||
|
|
5768dd08cd | ||
|
|
8cdba8ea29 | ||
|
|
3bf9ef537f | ||
|
|
bdb679c487 | ||
|
|
a9fa981000 | ||
|
|
3a47e433be | ||
|
|
6d65e69b10 | ||
|
|
faa4720dcf | ||
|
|
6d3a1fcda6 | ||
|
|
bf24379af5 | ||
|
|
0591cc2f8a |
6
.gitattributes
vendored
Normal file
6
.gitattributes
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# Avoids changelog conflicts by assuming additions-only, which is by far the common case.
|
||||
# In the rare case where branch b1 rebases against branch b2 and both branches
|
||||
# modified the same changelog entry, you'll end up with that changelog entry
|
||||
# duplicated, which is easily identifiable and fixable.
|
||||
/changelog.md merge=union
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
trigger:
|
||||
branches:
|
||||
include:
|
||||
- '*'
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
- '*'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
Linux_amd64:
|
||||
@@ -33,9 +42,10 @@ steps:
|
||||
condition: eq(variables['Agent.OS'], 'Windows_NT')
|
||||
|
||||
- checkout: self
|
||||
fetchDepth: 1
|
||||
|
||||
- bash: git clone --depth 1 https://github.com/nim-lang/csources.git
|
||||
displayName: 'Checkout csources'
|
||||
- bash: git clone --depth 1 https://github.com/nim-lang/csources
|
||||
displayName: 'Checkout Nim csources'
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
@@ -53,19 +63,13 @@ steps:
|
||||
- bash: |
|
||||
sudo dpkg --add-architecture i386
|
||||
|
||||
# Downgrade llvm, libgcc and libstdc++:
|
||||
# Downgrade llvm:
|
||||
# - llvm has to be downgraded to have 32bit version installed for sfml.
|
||||
# - libgcc and libstdc++ have to be downgraded as an optimization to
|
||||
# prevent the use of the toolchain ppa, which has a terrible download
|
||||
# speed.
|
||||
cat << EOF | sudo tee /etc/apt/preferences.d/pin-to-rel
|
||||
Package: libllvm6.0 libgcc1 libstdc++6
|
||||
Package: libllvm6.0
|
||||
Pin: origin "azure.archive.ubuntu.com"
|
||||
Pin-Priority: 1001
|
||||
|
||||
Package: *
|
||||
Pin: release o=LP-PPA-ubuntu-toolchain-r-test
|
||||
Pin-Priority: 100
|
||||
EOF
|
||||
|
||||
sudo apt-fast update -qq
|
||||
@@ -119,8 +123,19 @@ steps:
|
||||
make -v
|
||||
displayName: 'System information'
|
||||
|
||||
- bash: echo '##vso[task.setvariable variable=csources_version]'"$(git -C csources rev-parse HEAD)"
|
||||
displayName: 'Get csources version'
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: 'csources | "$(Agent.OS)" | $(CPU) | $(csources_version)'
|
||||
path: csources/bin
|
||||
displayName: 'Restore built csources'
|
||||
|
||||
|
||||
- bash: |
|
||||
ncpu=
|
||||
ext=
|
||||
case '$(Agent.OS)' in
|
||||
'Linux')
|
||||
ncpu=$(nproc)
|
||||
@@ -130,19 +145,24 @@ steps:
|
||||
;;
|
||||
'Windows_NT')
|
||||
ncpu=$NUMBER_OF_PROCESSORS
|
||||
ext=.exe
|
||||
;;
|
||||
esac
|
||||
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
|
||||
|
||||
make -C csources -j $ncpu CC=gcc ucpu=$(CPU)
|
||||
displayName: 'Build csources'
|
||||
if [[ -x csources/bin/nim$ext ]]; then
|
||||
echo "Found cached compiler, skipping build"
|
||||
else
|
||||
make -C csources -j $ncpu CC=gcc ucpu=$(CPU) koch=no
|
||||
fi
|
||||
cp csources/bin/nim$ext bin
|
||||
displayName: 'Build 1-stage compiler from csources'
|
||||
|
||||
- bash: nim c koch
|
||||
displayName: 'Build koch'
|
||||
|
||||
# set result to omit the "bash exited with error code '1'" message
|
||||
- bash: |
|
||||
./koch runCI || echo '##vso[task.complete result=Failed]'
|
||||
- bash: ./koch runCI || echo '##vso[task.complete result=Failed]'
|
||||
displayName: 'Run CI'
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
|
||||
12
changelog.md
12
changelog.md
@@ -1,4 +1,4 @@
|
||||
# v1.1 - xxxx-xx-xx
|
||||
# v1.0.8 - xxxx-xx-xx
|
||||
|
||||
|
||||
## Changes affecting backwards compatibility
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
### Breaking changes in the standard library
|
||||
|
||||
- `CountTable.mget` has been removed from `tables.nim`. It didn't work, and it
|
||||
was an oversight to be included in v1.0.
|
||||
|
||||
|
||||
|
||||
### Breaking changes in the compiler
|
||||
@@ -14,7 +17,11 @@
|
||||
|
||||
|
||||
## Library additions
|
||||
- Fixed buffer overflow bugs in `net`
|
||||
|
||||
- Added `sections` iterator in `parsecfg`.
|
||||
|
||||
- Added `browsers.osOpen` const alias for the operating system specific *"open"* command.
|
||||
|
||||
|
||||
## Library changes
|
||||
@@ -25,6 +32,9 @@
|
||||
|
||||
|
||||
|
||||
- Fix a bug where calling `close` on io streams in osproc.startProcess was a noop and led to
|
||||
hangs if a process had both reads from stdin and writes (eg to stdout).
|
||||
|
||||
## Language changes
|
||||
|
||||
|
||||
|
||||
@@ -858,7 +858,7 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||
if optBoundsCheck in p.options and ty.kind != tyUncheckedArray:
|
||||
if not isConstExpr(y):
|
||||
# semantic pass has already checked for const index expressions
|
||||
if firstOrd(p.config, ty) == 0:
|
||||
if firstOrd(p.config, ty) == 0 and lastOrd(p.config, ty) >= 0:
|
||||
if (firstOrd(p.config, b.t) < firstOrd(p.config, ty)) or (lastOrd(p.config, b.t) > lastOrd(p.config, ty)):
|
||||
linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError2($1, $2);$n",
|
||||
[rdCharLoc(b), intLiteral(lastOrd(p.config, ty))])
|
||||
@@ -1735,9 +1735,9 @@ template binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) =
|
||||
|
||||
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) =
|
||||
case int(getSize(p.config, skipTypes(e.sons[1].typ, abstractVar)))
|
||||
of 1: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&7U)))!=0)")
|
||||
of 2: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&15U)))!=0)")
|
||||
of 4: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&31U)))!=0)")
|
||||
of 1: binaryExprIn(p, e, a, b, d, "(($1 &((NU8)1<<((NU)($2)&7U)))!=0)")
|
||||
of 2: binaryExprIn(p, e, a, b, d, "(($1 &((NU16)1<<((NU)($2)&15U)))!=0)")
|
||||
of 4: binaryExprIn(p, e, a, b, d, "(($1 &((NU32)1<<((NU)($2)&31U)))!=0)")
|
||||
of 8: binaryExprIn(p, e, a, b, d, "(($1 &((NU64)1<<((NU)($2)&63U)))!=0)")
|
||||
else: binaryExprIn(p, e, a, b, d, "(($1[(NU)($2)>>3] &(1U<<((NU)($2)&7U)))!=0)")
|
||||
|
||||
@@ -1824,7 +1824,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mCard:
|
||||
if size <= 4: unaryExprChar(p, e, d, "#countBits32($1)")
|
||||
else: unaryExprChar(p, e, d, "#countBits64($1)")
|
||||
of mLtSet: binaryExprChar(p, e, d, "(($1 & ~ $2 ==0)&&($1 != $2))")
|
||||
of mLtSet: binaryExprChar(p, e, d, "((($1 & ~ $2)==0)&&($1 != $2))")
|
||||
of mLeSet: binaryExprChar(p, e, d, "(($1 & ~ $2)==0)")
|
||||
of mEqSet: binaryExpr(p, e, d, "($1 == $2)")
|
||||
of mMulSet: binaryExpr(p, e, d, "($1 & $2)")
|
||||
|
||||
@@ -29,10 +29,7 @@ proc initDefinesProg*(self: NimProg, conf: ConfigRef, name: string) =
|
||||
proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) =
|
||||
self.processCmdLine(passCmd1, "", conf)
|
||||
if self.supportsStdinFile and conf.projectName == "-":
|
||||
conf.projectName = "stdinfile"
|
||||
conf.projectFull = AbsoluteFile "stdinfile"
|
||||
conf.projectPath = AbsoluteDir getCurrentDir()
|
||||
conf.projectIsStdin = true
|
||||
handleStdinInput(conf)
|
||||
elif conf.projectName != "":
|
||||
try:
|
||||
conf.projectFull = canonicalizePath(conf, AbsoluteFile conf.projectName)
|
||||
|
||||
@@ -359,6 +359,14 @@ proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, in
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
options.inclDynlibOverride(conf, arg)
|
||||
|
||||
proc handleStdinInput*(conf: ConfigRef) =
|
||||
conf.projectName = "stdinfile"
|
||||
conf.projectFull = conf.projectName.AbsoluteFile
|
||||
conf.projectPath = AbsoluteDir getCurrentDir()
|
||||
conf.projectIsStdin = true
|
||||
if conf.outDir.isEmpty:
|
||||
conf.outDir = getNimcacheDir(conf)
|
||||
|
||||
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
conf: ConfigRef) =
|
||||
var
|
||||
@@ -795,8 +803,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
discard "the default"
|
||||
else:
|
||||
localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
|
||||
of "":
|
||||
conf.projectName = "-"
|
||||
of "": # comes from "-" in for example: `nim c -r -` (gets stripped from -)
|
||||
handleStdinInput(conf)
|
||||
else:
|
||||
if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
|
||||
else: invalidCmdLineOption(conf, pass, switch, info)
|
||||
|
||||
@@ -143,7 +143,7 @@ compiler vcc:
|
||||
buildDll: " /LD",
|
||||
buildLib: "lib /OUT:$libfile $objfiles",
|
||||
linkerExe: "cl",
|
||||
linkTmpl: "$options $builddll$vccplatform /Fe$exefile $objfiles $buildgui",
|
||||
linkTmpl: "$builddll$vccplatform /Fe$exefile $objfiles $buildgui $options",
|
||||
includeCmd: " /I",
|
||||
linkDirCmd: " /LIBPATH:",
|
||||
linkLibCmd: " $1.lib",
|
||||
|
||||
@@ -6,12 +6,12 @@ Name: "Nim"
|
||||
Version: "$version"
|
||||
Platforms: """
|
||||
windows: i386;amd64
|
||||
linux: i386;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv64
|
||||
macosx: i386;amd64;powerpc64
|
||||
linux: i386;hppa;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv32;riscv64
|
||||
macosx: i386;amd64;powerpc64;arm64
|
||||
solaris: i386;amd64;sparc;sparc64
|
||||
freebsd: i386;amd64;powerpc64
|
||||
freebsd: i386;amd64;powerpc64;arm;arm64;riscv64;sparc64;mips;mipsel;mips64;mips64el;powerpc;powerpc64el
|
||||
netbsd: i386;amd64
|
||||
openbsd: i386;amd64
|
||||
openbsd: i386;amd64;arm;arm64
|
||||
dragonfly: i386;amd64
|
||||
haiku: i386;amd64
|
||||
android: i386;arm;arm64
|
||||
@@ -89,6 +89,7 @@ Files: "bin/vccexe.exe"
|
||||
Files: "bin/nimgrab.exe"
|
||||
Files: "bin/nimpretty.exe"
|
||||
Files: "bin/testament.exe"
|
||||
Files: "bin/nim-gdb.bat"
|
||||
|
||||
Files: "koch.exe"
|
||||
Files: "finish.exe"
|
||||
@@ -117,6 +118,8 @@ Files: "bin/nim"
|
||||
[Unix]
|
||||
InstallScript: "yes"
|
||||
UninstallScript: "yes"
|
||||
Files: "bin/nim-gdb"
|
||||
Files: "bin/nim-gdb.bash"
|
||||
|
||||
|
||||
[InnoSetup]
|
||||
|
||||
@@ -1632,7 +1632,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
of tyObject:
|
||||
var initList: Rope
|
||||
createObjInitList(p, t, initIntSet(), initList)
|
||||
result = ("{$1}") % [initList]
|
||||
result = ("({$1})") % [initList]
|
||||
if indirect: result = "[$1]" % [result]
|
||||
of tyVar, tyPtr, tyLent, tyRef, tyPointer:
|
||||
if mapType(p, t) == etyBaseIndex:
|
||||
|
||||
@@ -13,7 +13,7 @@ when not defined(nimcore):
|
||||
{.error: "nimcore MUST be defined for Nim's core tooling".}
|
||||
|
||||
import
|
||||
llstream, strutils, ast, lexer, syntaxes, options, msgs,
|
||||
llstream, strutils, os, ast, lexer, syntaxes, options, msgs,
|
||||
condsyms, times,
|
||||
sem, idents, passes, extccomp,
|
||||
cgen, json, nversion,
|
||||
@@ -303,6 +303,8 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
|
||||
var dumpdata = %[
|
||||
(key: "version", val: %VersionAsString),
|
||||
(key: "nimExe", val: %(getAppFilename())),
|
||||
(key: "prefixdir", val: %conf.getPrefixDir().string),
|
||||
(key: "project_path", val: %conf.projectFull.string),
|
||||
(key: "defined_symbols", val: definedSymbols),
|
||||
(key: "lib_paths", val: %libpaths),
|
||||
|
||||
@@ -380,7 +380,7 @@ proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) =
|
||||
if context.info != lastinfo and context.info != info:
|
||||
if conf.structuredErrorHook != nil:
|
||||
conf.structuredErrorHook(conf, context.info, instantiationFrom,
|
||||
Severity.Error)
|
||||
Severity.Hint)
|
||||
else:
|
||||
let message = if context.detail == "":
|
||||
instantiationFrom
|
||||
|
||||
@@ -22,7 +22,7 @@ type
|
||||
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
||||
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx,
|
||||
osAmiga, osAtari, osNetware, osMacos, osMacosx, osIos, osHaiku, osAndroid, osVxWorks
|
||||
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch
|
||||
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch, osFreeRTOS, osAny
|
||||
|
||||
type
|
||||
TInfoOSProp* = enum
|
||||
@@ -177,15 +177,23 @@ const
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: ".elf", extSep: ".",
|
||||
props: {ospNeedsPIC, ospPosix}),
|
||||
(name: "FreeRTOS", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
props: {ospPosix}),
|
||||
(name: "Any", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
props: {}),
|
||||
]
|
||||
|
||||
type
|
||||
TSystemCPU* = enum # Also add CPU for in initialization section and
|
||||
# alias conditionals to condsyms (end of module).
|
||||
cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
|
||||
cpuPowerpc64el, cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuMipsel,
|
||||
cpuArm, cpuArm64, cpuJS, cpuNimVM, cpuAVR, cpuMSP430, cpuSparc64,
|
||||
cpuMips64, cpuMips64el, cpuRiscV64, cpuWasm32
|
||||
cpuPowerpc64el, cpuSparc, cpuVm, cpuHppa, cpuIa64, cpuAmd64, cpuMips,
|
||||
cpuMipsel, cpuArm, cpuArm64, cpuJS, cpuNimVM, cpuAVR, cpuMSP430,
|
||||
cpuSparc64, cpuMips64, cpuMips64el, cpuRiscV32, cpuRiscV64, cpuEsp, cpuWasm32
|
||||
|
||||
type
|
||||
TEndian* = enum
|
||||
@@ -204,6 +212,7 @@ const
|
||||
(name: "powerpc64el", intSize: 64, endian: littleEndian, floatSize: 64,bit: 64),
|
||||
(name: "sparc", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
|
||||
(name: "vm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||
(name: "hppa", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
|
||||
(name: "ia64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "amd64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "mips", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
|
||||
@@ -217,7 +226,9 @@ const
|
||||
(name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
|
||||
(name: "mips64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
|
||||
(name: "mips64el", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "riscv32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||
(name: "riscv64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "esp", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||
(name: "wasm32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32)]
|
||||
|
||||
type
|
||||
@@ -241,23 +252,23 @@ proc setTarget*(t: var Target; o: TSystemOS, c: TSystemCPU) =
|
||||
t.tnl = OS[o].newLine
|
||||
|
||||
proc nameToOS*(name: string): TSystemOS =
|
||||
for i in succ(osNone) .. high(TSystemOS):
|
||||
for i in succ(osNone)..high(TSystemOS):
|
||||
if cmpIgnoreStyle(name, OS[i].name) == 0:
|
||||
return i
|
||||
result = osNone
|
||||
|
||||
proc listOSnames*(): seq[string] =
|
||||
for i in succ(osNone) .. high(TSystemOS):
|
||||
for i in succ(osNone)..high(TSystemOS):
|
||||
result.add OS[i].name
|
||||
|
||||
proc nameToCPU*(name: string): TSystemCPU =
|
||||
for i in succ(cpuNone) .. high(TSystemCPU):
|
||||
for i in succ(cpuNone)..high(TSystemCPU):
|
||||
if cmpIgnoreStyle(name, CPU[i].name) == 0:
|
||||
return i
|
||||
result = cpuNone
|
||||
|
||||
proc listCPUnames*(): seq[string] =
|
||||
for i in succ(cpuNone) .. high(TSystemCPU):
|
||||
for i in succ(cpuNone)..high(TSystemCPU):
|
||||
result.add CPU[i].name
|
||||
|
||||
proc setTargetFromSystem*(t: var Target) =
|
||||
|
||||
@@ -52,17 +52,17 @@ const
|
||||
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
||||
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
|
||||
wInjectStmt, wExperimental, wThis, wUsed}
|
||||
lambdaPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||
lambdaPragmas* = {FirstCallConv..LastCallConv,
|
||||
wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
|
||||
wThread, wAsmNoStackFrame,
|
||||
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl} - {wExportNims, wError, wUsed} # why exclude these?
|
||||
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl, wNoInit}
|
||||
typePragmas* = declPragmas + {wMagic, wAcyclic,
|
||||
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wShallow,
|
||||
wIncompleteStruct, wByCopy, wByRef,
|
||||
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
|
||||
wBorrow, wGcSafe, wPartial, wExplain, wPackage}
|
||||
fieldPragmas* = declPragmas + {
|
||||
wGuard, wBitsize} - {wExportNims, wNodecl} # why exclude these?
|
||||
wGuard, wBitsize, wAlign} - {wExportNims, wNodecl} # why exclude these?
|
||||
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
|
||||
wMagic, wHeader, wCompilerProc, wCore, wDynlib,
|
||||
wNoInit, wCompileTime, wGlobal,
|
||||
|
||||
@@ -196,7 +196,11 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||
candidates.add(" first type mismatch at position: " & $err.firstMismatch.arg)
|
||||
# candidates.add "\n reason: " & $err.firstMismatch.kind # for debugging
|
||||
case err.firstMismatch.kind
|
||||
of kUnknownNamedParam: candidates.add("\n unknown named parameter: " & $nArg[0])
|
||||
of kUnknownNamedParam:
|
||||
if nArg == nil:
|
||||
candidates.add("\n unknown named parameter")
|
||||
else:
|
||||
candidates.add("\n unknown named parameter: " & $nArg[0])
|
||||
of kAlreadyGiven: candidates.add("\n named param already provided: " & $nArg[0])
|
||||
of kPositionalAlreadyGiven: candidates.add("\n positional param was already given as named param")
|
||||
of kExtraArg: candidates.add("\n extra argument given")
|
||||
@@ -296,7 +300,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
|
||||
sym = nextOverloadIter(o, c, f)
|
||||
|
||||
let ident = considerQuotedIdent(c, f, n).s
|
||||
if nfDotField in n.flags and nfExplicitCall notin n.flags:
|
||||
if {nfDotField, nfExplicitCall} * n.flags == {nfDotField}:
|
||||
let sym = n.sons[1].typ.sym
|
||||
var typeHint = ""
|
||||
if sym == nil:
|
||||
|
||||
@@ -508,7 +508,7 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
|
||||
addSon(a, m)
|
||||
changeType(m, tup.sons[i], check)
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if check and n.kind != nkUInt64Lit:
|
||||
if check and n.kind != nkUInt64Lit and not sameType(n.typ, newType):
|
||||
let value = n.intVal
|
||||
if value < firstOrd(c.config, newType) or value > lastOrd(c.config, newType):
|
||||
localError(c.config, n.info, "cannot convert " & $value &
|
||||
@@ -2034,6 +2034,10 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
|
||||
|
||||
proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
# watch out, hacks ahead:
|
||||
when defined(nimsuggest):
|
||||
# Remove the error hook so nimsuggest doesn't report errors there
|
||||
let tempHook = c.graph.config.structuredErrorHook
|
||||
c.graph.config.structuredErrorHook = nil
|
||||
let oldErrorCount = c.config.errorCounter
|
||||
let oldErrorMax = c.config.errorMax
|
||||
let oldCompilesId = c.compilesContextId
|
||||
@@ -2080,6 +2084,9 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
c.config.m.errorOutputs = oldErrorOutputs
|
||||
c.config.errorCounter = oldErrorCount
|
||||
c.config.errorMax = oldErrorMax
|
||||
when defined(nimsuggest):
|
||||
# Restore the error hook
|
||||
c.graph.config.structuredErrorHook = tempHook
|
||||
|
||||
proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# we replace this node by a 'true' or 'false' node:
|
||||
@@ -2394,7 +2401,7 @@ proc checkPar(c: PContext; n: PNode): TParKind =
|
||||
for i in 0 ..< length:
|
||||
if result == paTupleFields:
|
||||
if (n.sons[i].kind != nkExprColonExpr) or
|
||||
n.sons[i].sons[0].kind notin {nkSym, nkIdent}:
|
||||
n.sons[i].sons[0].kind notin {nkSym, nkIdent, nkAccQuoted}:
|
||||
localError(c.config, n.sons[i].info, errNamedExprExpected)
|
||||
return paNone
|
||||
else:
|
||||
|
||||
@@ -23,7 +23,7 @@ proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
|
||||
result = newNode(nkEmpty)
|
||||
return
|
||||
case n.kind
|
||||
of nkEmpty..pred(nkIdent), succ(nkSym)..nkNilLit: result = n
|
||||
of nkEmpty..pred(nkIdent), succ(nkSym)..nkNilLit: result = copyNode(n)
|
||||
of nkIdent, nkSym:
|
||||
result = n
|
||||
let ident = considerQuotedIdent(c.c, n)
|
||||
@@ -53,8 +53,7 @@ proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
|
||||
if n.kind == nkContinueStmt:
|
||||
localError(c.c.config, n.info,
|
||||
"'continue' not supported in a 'fields' loop")
|
||||
result = copyNode(n)
|
||||
newSons(result, len(n))
|
||||
result = shallowCopy(n)
|
||||
for i in 0 ..< len(n):
|
||||
result.sons[i] = instFieldLoopBody(c, n.sons[i], forLoop)
|
||||
|
||||
|
||||
@@ -446,7 +446,6 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
|
||||
result = newIntNodeT(BiggestInt(getFloat(a)), n, g)
|
||||
of tyChar, tyUInt..tyUInt64, tyInt..tyInt64:
|
||||
var val = a.getOrdValue
|
||||
|
||||
if check: rangeCheck(n, val, g)
|
||||
result = newIntNodeT(val, n, g)
|
||||
if dstTyp.kind in {tyUInt..tyUInt64}:
|
||||
@@ -734,7 +733,11 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
of nkBracketExpr: result = foldArrayAccess(m, n, g)
|
||||
of nkDotExpr: result = foldFieldAccess(m, n, g)
|
||||
of nkStmtListExpr:
|
||||
if n.len == 2 and n[0].kind == nkComesFrom:
|
||||
result = getConstExpr(m, n[1], g)
|
||||
var i = 0
|
||||
while i <= n.len - 2:
|
||||
if n[i].kind in {nkComesFrom, nkCommentStmt, nkEmpty}: i.inc
|
||||
else: break
|
||||
if i == n.len - 1:
|
||||
result = getConstExpr(m, n[i], g)
|
||||
else:
|
||||
discard
|
||||
|
||||
@@ -955,9 +955,9 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
checkSonsLen(x, 1, c.config)
|
||||
x.sons[0] = semExprBranchScope(c, x.sons[0])
|
||||
typ = commonType(typ, x.sons[0])
|
||||
hasElse = true
|
||||
if chckCovered and covered == toCover(c, n.sons[0].typ):
|
||||
if (chckCovered and covered == toCover(c, n[0].typ)) or hasElse:
|
||||
localError(c.config, x.info, "invalid else, all cases are already covered")
|
||||
hasElse = true
|
||||
chckCovered = false
|
||||
else:
|
||||
illFormedAst(x, c.config)
|
||||
|
||||
@@ -626,7 +626,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
case typ.kind
|
||||
of shouldChckCovered:
|
||||
chckCovered = true
|
||||
of tyFloat..tyFloat128, tyString, tyError:
|
||||
of tyFloat..tyFloat128, tyError:
|
||||
discard
|
||||
of tyRange:
|
||||
if skipTypes(typ.sons[0], abstractInst).kind in shouldChckCovered:
|
||||
@@ -634,7 +634,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
of tyForward:
|
||||
errorUndeclaredIdentifier(c, n.sons[0].info, typ.sym.name.s)
|
||||
elif not isOrdinalType(typ):
|
||||
localError(c.config, n.sons[0].info, "selector must be of an ordinal type, float or string")
|
||||
localError(c.config, n.sons[0].info, "selector must be of an ordinal type or float")
|
||||
if firstOrd(c.config, typ) != 0:
|
||||
localError(c.config, n.info, "low(" & $a.sons[0].sym.name.s &
|
||||
") must be 0 for discriminant")
|
||||
@@ -768,7 +768,7 @@ proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int,
|
||||
addInheritedFieldsAux(c, check, pos, lastSon(n.sons[i]))
|
||||
else: internalError(c.config, n.info, "addInheritedFieldsAux(record case branch)")
|
||||
of nkRecList, nkRecWhen, nkElifBranch, nkElse:
|
||||
for i in 0 ..< len(n):
|
||||
for i in int(n.kind == nkElifBranch) ..< len(n):
|
||||
addInheritedFieldsAux(c, check, pos, n.sons[i])
|
||||
of nkSym:
|
||||
incl(check, n.sym.name.id)
|
||||
|
||||
@@ -1089,7 +1089,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
let x = typeRel(c, f, branch, flags + {trDontBind})
|
||||
if x == isNone: return isNone
|
||||
if x < result: result = x
|
||||
return
|
||||
return result
|
||||
|
||||
of tyAnd:
|
||||
# XXX: deal with the current dual meaning of tyGenericParam
|
||||
@@ -1423,7 +1423,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
let ff = rootf.sons[i]
|
||||
let aa = roota.sons[i]
|
||||
let res = typeRel(c, ff, aa, nextFlags)
|
||||
if res != isEqual: result = isGeneric
|
||||
if res != isNone and res != isEqual: result = isGeneric
|
||||
if res notin {isEqual, isGeneric}:
|
||||
if trNoCovariance notin flags and ff.kind == aa.kind:
|
||||
let paramFlags = rootf.base.sons[i-1].flags
|
||||
@@ -1941,7 +1941,8 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
var call = newNodeI(nkCall, arg.info)
|
||||
call.add(f.n.copyTree)
|
||||
call.add(arg.copyTree)
|
||||
result = c.semExpr(c, call)
|
||||
result = c.semTryExpr(c, call)
|
||||
|
||||
if result != nil:
|
||||
if result.typ == nil: return nil
|
||||
# resulting type must be consistent with the other arguments:
|
||||
|
||||
@@ -138,12 +138,13 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, packed: bool, a
|
||||
accum.offset = szUnknownSize
|
||||
accum.maxAlign = szUnknownSize
|
||||
else:
|
||||
# the union neds to be aligned first, before the offsets can be assigned
|
||||
# the union needs to be aligned first, before the offsets can be assigned
|
||||
accum.align(maxChildAlign)
|
||||
let accumRoot = accum # copy, because each branch should start af the same offset
|
||||
for i in 1 ..< len(n):
|
||||
var branchAccum = accumRoot
|
||||
var branchAccum = OffsetAccum(offset: accumRoot.offset, maxAlign: 1)
|
||||
computeObjectOffsetsFoldFunction(conf, n.sons[i].lastSon, packed, branchAccum)
|
||||
discard finish(branchAccum)
|
||||
accum.mergeBranch(branchAccum)
|
||||
of nkRecList:
|
||||
for i, child in n.sons:
|
||||
@@ -171,9 +172,10 @@ proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; accum: var
|
||||
localError(conf, n.info, "Illegal use of ``case`` in union type.")
|
||||
of nkRecList:
|
||||
let accumRoot = accum # copy, because each branch should start af the same offset
|
||||
for i, child in n.sons:
|
||||
var branchAccum = accumRoot
|
||||
for child in n.sons:
|
||||
var branchAccum = OffsetAccum(offset: accumRoot.offset, maxAlign: 1)
|
||||
computeUnionObjectOffsetsFoldFunction(conf, child, branchAccum)
|
||||
discard finish(branchAccum)
|
||||
accum.mergeBranch(branchAccum)
|
||||
of nkSym:
|
||||
var size = szUnknownSize
|
||||
|
||||
@@ -573,10 +573,19 @@ proc putArgInto(arg: PNode, formal: PType): TPutArgInto =
|
||||
case arg.kind
|
||||
of nkEmpty..nkNilLit:
|
||||
result = paDirectMapping
|
||||
of nkPar, nkTupleConstr, nkCurly, nkBracket:
|
||||
result = paFastAsgn
|
||||
for i in 0 ..< len(arg):
|
||||
if putArgInto(arg.sons[i], formal) != paDirectMapping: return
|
||||
of nkDotExpr, nkDerefExpr, nkHiddenDeref, nkAddr, nkHiddenAddr:
|
||||
result = putArgInto(arg[0], formal)
|
||||
of nkCurly, nkBracket:
|
||||
for i in 0..<arg.len:
|
||||
if putArgInto(arg[i], formal) != paDirectMapping:
|
||||
return paFastAsgn
|
||||
result = paDirectMapping
|
||||
of nkPar, nkTupleConstr, nkObjConstr:
|
||||
for i in 0..<arg.len:
|
||||
let a = if arg[i].kind == nkExprColonExpr: arg[i][1]
|
||||
else: arg[0]
|
||||
if putArgInto(a, formal) != paDirectMapping:
|
||||
return paFastAsgn
|
||||
result = paDirectMapping
|
||||
else:
|
||||
if skipTypes(formal, abstractInst).kind in {tyVar, tyLent}: result = paVarAsgn
|
||||
@@ -1095,15 +1104,15 @@ proc liftDeferAux(n: PNode) =
|
||||
if n.sons[i].kind == nkDefer:
|
||||
let deferPart = newNodeI(nkFinally, n.sons[i].info)
|
||||
deferPart.add n.sons[i].sons[0]
|
||||
var tryStmt = newNodeI(nkTryStmt, n.sons[i].info)
|
||||
var body = newNodeI(n.kind, n.sons[i].info)
|
||||
var tryStmt = newNodeIT(nkTryStmt, n.sons[i].info, n.typ)
|
||||
var body = newNodeIT(n.kind, n.sons[i].info, n.typ)
|
||||
if i < last:
|
||||
body.sons = n.sons[(i+1)..last]
|
||||
tryStmt.addSon(body)
|
||||
tryStmt.addSon(deferPart)
|
||||
n.sons[i] = tryStmt
|
||||
n.sons.setLen(i+1)
|
||||
n.typ = n.sons[i].typ
|
||||
n.typ = tryStmt.typ
|
||||
goOn = true
|
||||
break
|
||||
for i in 0..n.safeLen-1:
|
||||
|
||||
@@ -87,7 +87,11 @@ proc isUnsigned*(t: PType): bool =
|
||||
t.skipTypes(abstractInst).kind in {tyChar, tyUInt..tyUInt64}
|
||||
|
||||
proc getOrdValue*(n: PNode; onError = high(Int128)): Int128 =
|
||||
case n.kind
|
||||
var k = n.kind
|
||||
if n.typ != nil and n.typ.skipTypes(abstractInst).kind in {tyChar, tyUInt..tyUInt64}:
|
||||
k = nkUIntLit
|
||||
|
||||
case k
|
||||
of nkCharLit, nkUIntLit..nkUInt64Lit:
|
||||
# XXX: enable this assert
|
||||
#assert n.typ == nil or isUnsigned(n.typ), $n.typ
|
||||
|
||||
@@ -247,6 +247,8 @@ proc freeTemp(c: PCtx; r: TRegister) =
|
||||
proc getTempRange(cc: PCtx; n: int; kind: TSlotKind): TRegister =
|
||||
# if register pressure is high, we re-use more aggressively:
|
||||
let c = cc.prc
|
||||
# we could also customize via the following (with proper caching in ConfigRef):
|
||||
# let highRegisterPressure = cc.config.getConfigVar("vm.highRegisterPressure", "40").parseInt
|
||||
if c.maxSlots >= HighRegisterPressure or c.maxSlots+n >= high(TRegister):
|
||||
for i in 0 .. c.maxSlots-n:
|
||||
if not c.slots[i].inUse:
|
||||
@@ -1533,14 +1535,14 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||
let tmp = c.genx(ri)
|
||||
c.preventFalseAlias(le[0], opcWrObj, objR, idx, tmp)
|
||||
c.freeTemp(tmp)
|
||||
c.freeTemp(idx)
|
||||
# c.freeTemp(idx) # BUGFIX, see nkDotExpr
|
||||
c.freeTemp(objR)
|
||||
of nkDotExpr:
|
||||
let dest = c.genx(le.sons[0], {gfNode})
|
||||
let idx = genField(c, le.sons[1])
|
||||
let tmp = c.genx(ri)
|
||||
c.preventFalseAlias(le, opcWrObj, dest, idx, tmp)
|
||||
c.freeTemp(idx)
|
||||
# c.freeTemp(idx) # BUGFIX: idx is an immediate (field position), not a register
|
||||
c.freeTemp(tmp)
|
||||
c.freeTemp(dest)
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
@@ -1955,16 +1957,6 @@ proc genProc*(c: PCtx; s: PSym): int
|
||||
|
||||
proc matches(s: PSym; x: string): bool =
|
||||
let y = x.split('.')
|
||||
var s = s
|
||||
var L = y.len-1
|
||||
while L >= 0:
|
||||
if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"):
|
||||
return false
|
||||
s = s.owner
|
||||
dec L
|
||||
result = true
|
||||
|
||||
proc matches(s: PSym; y: varargs[string]): bool =
|
||||
var s = s
|
||||
var L = y.len-1
|
||||
while L >= 0:
|
||||
@@ -2027,11 +2019,11 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
elif s.kind == skMethod:
|
||||
localError(c.config, n.info, "cannot call method " & s.name.s &
|
||||
" at compile time")
|
||||
elif matches(s, "stdlib", "marshal", "to"):
|
||||
elif matches(s, "stdlib.marshal.to"):
|
||||
# XXX marshal load&store should not be opcodes, but use the
|
||||
# general callback mechanisms.
|
||||
genMarshalLoad(c, n, dest)
|
||||
elif matches(s, "stdlib", "marshal", "$$"):
|
||||
elif matches(s, "stdlib.marshal.$$"):
|
||||
genMarshalStore(c, n, dest)
|
||||
else:
|
||||
genCall(c, n, dest)
|
||||
|
||||
@@ -76,6 +76,7 @@ path="$lib/pure"
|
||||
debugger:off
|
||||
line_dir:off
|
||||
opt:speed
|
||||
define:release
|
||||
@end
|
||||
|
||||
@if false: # not danger: # this does not work yet.
|
||||
|
||||
@@ -472,6 +472,9 @@ Modules for JS backend
|
||||
* `dom <dom.html>`_
|
||||
Declaration of the Document Object Model for the JS backend.
|
||||
|
||||
* `jsconsole <jsconsole.html>`_
|
||||
Wrapper for the ``console`` object.
|
||||
|
||||
* `jscore <jscore.html>`_
|
||||
Wrapper of core JavaScript functions. For most purposes you should be using
|
||||
the ``math``, ``json``, and ``times`` stdlib modules instead of this module.
|
||||
|
||||
@@ -142,7 +142,7 @@ It is mostly accurate to picture semantic analysis proceeding top to bottom and
|
||||
left to right in the source code, with compile-time code execution interleaved
|
||||
when necessary to compute values that are required for subsequent semantic
|
||||
analysis. We will see much later in this document that macro invocation not only
|
||||
requires this interleaving, but also creates a situation where semantic analyis
|
||||
requires this interleaving, but also creates a situation where semantic analysis
|
||||
does not entirely proceed top to bottom and left to right.
|
||||
|
||||
|
||||
@@ -783,7 +783,7 @@ features supported at compile time (as detailed in the next section below).
|
||||
Within such a code block, it is possible to declare variables and then later
|
||||
read and update them, or declare variables and pass them to procedures that
|
||||
modify them. However, the code in such a block must still adhere to the
|
||||
retrictions listed above for referencing values and operations outside the
|
||||
restrictions listed above for referencing values and operations outside the
|
||||
block.
|
||||
|
||||
The ability to access and modify compile-time variables adds flexibility to
|
||||
@@ -1287,7 +1287,7 @@ A parameter ``A`` may be an *open array*, in which case it is indexed by
|
||||
integers from 0 to ``len(A)-1``. An array expression may be constructed by the
|
||||
array constructor ``[]``. The element type of this array expression is
|
||||
inferred from the type of the first element. All other elements need to be
|
||||
implicitly convertable to this type.
|
||||
implicitly convertible to this type.
|
||||
|
||||
Sequences are similar to arrays but of dynamic length which may change
|
||||
during runtime (like strings). Sequences are implemented as growable arrays,
|
||||
@@ -1790,7 +1790,7 @@ Mixing GC'ed memory with ``ptr``
|
||||
|
||||
Special care has to be taken if an untraced object contains traced objects like
|
||||
traced references, strings or sequences: in order to free everything properly,
|
||||
the built-in procedure ``GCunref`` has to be called before freeing the untraced
|
||||
the built-in procedure ``reset`` has to be called before freeing the untraced
|
||||
memory manually:
|
||||
|
||||
.. code-block:: nim
|
||||
@@ -1804,12 +1804,12 @@ memory manually:
|
||||
d.s = "abc"
|
||||
|
||||
# tell the GC that the string is not needed anymore:
|
||||
GCunref(d.s)
|
||||
reset(d.s)
|
||||
|
||||
# free the memory:
|
||||
dealloc(d)
|
||||
|
||||
Without the ``GCunref`` call the memory allocated for the ``d.s`` string would
|
||||
Without the ``reset`` call the memory allocated for the ``d.s`` string would
|
||||
never be freed. The example also demonstrates two important features for low
|
||||
level programming: the ``sizeof`` proc returns the size of a type or value
|
||||
in bytes. The ``cast`` operator can circumvent the type system: the compiler
|
||||
@@ -2350,7 +2350,7 @@ The convertible relation can be relaxed by a user-defined type
|
||||
# implicit conversion magic happens here
|
||||
x = chr
|
||||
echo x # => 97
|
||||
# you can use the explicit form too
|
||||
# one can use the explicit form too
|
||||
x = chr.toInt
|
||||
echo x # => 97
|
||||
|
||||
@@ -3814,7 +3814,7 @@ as there are components in the tuple. The i'th iteration variable's type is
|
||||
the type of the i'th component. In other words, implicit tuple unpacking in a
|
||||
for loop context is supported.
|
||||
|
||||
Implict items/pairs invocations
|
||||
Implicit items/pairs invocations
|
||||
-------------------------------
|
||||
|
||||
If the for loop expression ``e`` does not denote an iterator and the for loop
|
||||
@@ -4493,8 +4493,8 @@ more complex type classes:
|
||||
|
||||
Whilst the syntax of type classes appears to resemble that of ADTs/algebraic data
|
||||
types in ML-like languages, it should be understood that type classes are static
|
||||
constraints to be enforced at type instantations. Type classes are not really
|
||||
types in themsleves, but are instead a system of providing generic "checks" that
|
||||
constraints to be enforced at type instantiations. Type classes are not really
|
||||
types in themselves, but are instead a system of providing generic "checks" that
|
||||
ultimately *resolve* to some singular type. Type classes do not allow for
|
||||
runtime type dynamism, unlike object variants or methods.
|
||||
|
||||
@@ -4656,7 +4656,7 @@ instantiation. The following is not allowed:
|
||||
# not valid: 'T' is not inferred to be of type 'var int'
|
||||
g(v, i)
|
||||
|
||||
# also not allowed: explict instantiation via 'var int'
|
||||
# also not allowed: explicit instantiation via 'var int'
|
||||
g[var int](v, i)
|
||||
|
||||
|
||||
@@ -4812,7 +4812,7 @@ compiler. Explicit immediate templates are now deprecated.
|
||||
Passing a code block to a template
|
||||
----------------------------------
|
||||
|
||||
You can pass a block of statements as the last argument to a template
|
||||
One can pass a block of statements as the last argument to a template
|
||||
following the special ``:`` syntax:
|
||||
|
||||
.. code-block:: nim
|
||||
@@ -5127,7 +5127,7 @@ tree (AST) of the code that is passed to it. The macro can then do
|
||||
transformations on it and return the transformed AST. This can be used to
|
||||
add custom language features and implement `domain specific languages`:idx:.
|
||||
|
||||
Macro invocation is a case where semantic analyis does **not** entirely proceed
|
||||
Macro invocation is a case where semantic analysis does **not** entirely proceed
|
||||
top to bottom and left to right. Instead, semantic analysis happens at least
|
||||
twice:
|
||||
|
||||
@@ -5399,7 +5399,7 @@ generic type ``static[T]``. The type param can be omitted to obtain the type
|
||||
class of all constant expressions. A more specific type class can be created by
|
||||
instantiating ``static`` with another type class.
|
||||
|
||||
You can force an expression to be evaluated at compile time as a constant
|
||||
One can force an expression to be evaluated at compile time as a constant
|
||||
expression by coercing it to a corresponding ``static`` type:
|
||||
|
||||
.. code-block:: nim
|
||||
@@ -5413,14 +5413,14 @@ possible type mismatch error.
|
||||
typedesc[T]
|
||||
-----------
|
||||
|
||||
In many contexts, Nim allows you to treat the names of types as regular
|
||||
In many contexts, Nim allows to treat the names of types as regular
|
||||
values. These values exists only during the compilation phase, but since
|
||||
all values must have a type, ``typedesc`` is considered their special type.
|
||||
|
||||
``typedesc`` acts like a generic type. For instance, the type of the symbol
|
||||
``int`` is ``typedesc[int]``. Just like with regular generic types, when the
|
||||
generic param is omitted, ``typedesc`` denotes the type class of all types.
|
||||
As a syntactic convenience, you can also use ``typedesc`` as a modifier.
|
||||
As a syntactic convenience, one can also use ``typedesc`` as a modifier.
|
||||
|
||||
Procs featuring ``typedesc`` params are considered implicitly generic.
|
||||
They will be instantiated for each unique combination of supplied types
|
||||
@@ -5498,7 +5498,7 @@ typeof operator
|
||||
**Note**: ``typeof(x)`` can for historical reasons also be written as
|
||||
``type(x)`` but ``type(x)`` is discouraged.
|
||||
|
||||
You can obtain the type of a given expression by constructing a ``typeof``
|
||||
One can obtain the type of a given expression by constructing a ``typeof``
|
||||
value from it (in many other languages this is known as the `typeof`:idx:
|
||||
operator):
|
||||
|
||||
@@ -5711,9 +5711,9 @@ modules don't need to import a module's dependencies:
|
||||
echo $x
|
||||
|
||||
When the exported symbol is another module, all of its definitions will
|
||||
be forwarded. You can use an ``except`` list to exclude some of the symbols.
|
||||
be forwarded. One can use an ``except`` list to exclude some of the symbols.
|
||||
|
||||
Notice that when exporting, you need to specify only the module name:
|
||||
Notice that when exporting, one needs to specify only the module name:
|
||||
|
||||
.. code-block:: nim
|
||||
import foo/bar/baz
|
||||
@@ -6483,7 +6483,7 @@ and instead the generated code should contain an ``#include``:
|
||||
PFile {.importc: "FILE*", header: "<stdio.h>".} = distinct pointer
|
||||
# import C's FILE* type; Nim will treat it as a new pointer type
|
||||
|
||||
The ``header`` pragma always expects a string constant. The string contant
|
||||
The ``header`` pragma always expects a string constant. The string constant
|
||||
contains the header file: As usual for C, a system header file is enclosed
|
||||
in angle brackets: ``<>``. If no angle brackets are given, Nim
|
||||
encloses the header file in ``""`` in the generated C code.
|
||||
@@ -6511,7 +6511,7 @@ with the project:
|
||||
{.compile: "myfile.cpp".}
|
||||
|
||||
**Note**: Nim computes a SHA1 checksum and only recompiles the file if it
|
||||
has changed. You can use the ``-f`` command line option to force recompilation
|
||||
has changed. One can use the ``-f`` command line option to force recompilation
|
||||
of the file.
|
||||
|
||||
|
||||
@@ -6531,7 +6531,7 @@ compiler like you would using the commandline switch ``--passC``:
|
||||
.. code-block:: Nim
|
||||
{.passC: "-Wall -Werror".}
|
||||
|
||||
Note that you can use ``gorge`` from the `system module <system.html>`_ to
|
||||
Note that one can use ``gorge`` from the `system module <system.html>`_ to
|
||||
embed parameters from an external command that will be executed
|
||||
during semantic analysis:
|
||||
|
||||
@@ -6541,12 +6541,12 @@ during semantic analysis:
|
||||
PassL pragma
|
||||
------------
|
||||
The ``passL`` pragma can be used to pass additional parameters to the linker
|
||||
like you would using the commandline switch ``--passL``:
|
||||
like one would using the commandline switch ``--passL``:
|
||||
|
||||
.. code-block:: Nim
|
||||
{.passL: "-lSDLmain -lSDL".}
|
||||
|
||||
Note that you can use ``gorge`` from the `system module <system.html>`_ to
|
||||
Note that one can use ``gorge`` from the `system module <system.html>`_ to
|
||||
embed parameters from an external command that will be executed
|
||||
during semantic analysis:
|
||||
|
||||
@@ -6801,7 +6801,7 @@ Importcpp for objects
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Generic ``importcpp``'ed objects are mapped to C++ templates. This means that
|
||||
you can import C++'s templates rather easily without the need for a pattern
|
||||
one can import C++'s templates rather easily without the need for a pattern
|
||||
language for object types:
|
||||
|
||||
.. code-block:: nim
|
||||
@@ -7022,9 +7022,9 @@ specified. It is possible to annotate procs, templates, type and variable
|
||||
definitions, statements, etc.
|
||||
|
||||
Macros module includes helpers which can be used to simplify custom pragma
|
||||
access `hasCustomPragma`, `getCustomPragmaVal`. Please consult macros module
|
||||
documentation for details. These macros are no magic, they don't do anything
|
||||
you cannot do yourself by walking AST object representation.
|
||||
access `hasCustomPragma`, `getCustomPragmaVal`. Please consult the macros module
|
||||
documentation for details. These macros are not magic, everything they do can
|
||||
also be achieved by walking the AST of the object representation.
|
||||
|
||||
More examples with custom pragmas:
|
||||
|
||||
|
||||
18
doc/tut1.rst
18
doc/tut1.rst
@@ -743,13 +743,19 @@ Overloaded procedures
|
||||
Nim provides the ability to overload procedures similar to C++:
|
||||
|
||||
.. code-block:: nim
|
||||
proc toString(x: int): string = ...
|
||||
proc toString(x: bool): string =
|
||||
if x: result = "true"
|
||||
else: result = "false"
|
||||
proc toString(x: int): string =
|
||||
result =
|
||||
if x < 0: "negative"
|
||||
elif x > 0: "positive"
|
||||
else: "zero"
|
||||
|
||||
echo toString(13) # calls the toString(x: int) proc
|
||||
echo toString(true) # calls the toString(x: bool) proc
|
||||
proc toString(x: bool): string =
|
||||
result =
|
||||
if x: "yep"
|
||||
else: "nope"
|
||||
|
||||
assert toString(13) == "positive" # calls the toString(x: int) proc
|
||||
assert toString(true) == "yep" # calls the toString(x: bool) proc
|
||||
|
||||
(Note that ``toString`` is usually the `$ <dollars.html>`_ operator in
|
||||
Nim.) The compiler chooses the most appropriate proc for the ``toString``
|
||||
|
||||
64
koch.nim
64
koch.nim
@@ -10,7 +10,7 @@
|
||||
#
|
||||
|
||||
const
|
||||
NimbleStableCommit = "4007b2a778429a978e12307bf13a038029b4c4d9" # master
|
||||
NimbleStableCommit = "8f7af860c5ce9634af880a7081c6435e1f2a5148" # master
|
||||
|
||||
when defined(gcc) and defined(windows):
|
||||
when defined(x86):
|
||||
@@ -27,6 +27,7 @@ import
|
||||
os, strutils, parseopt, osproc, streams
|
||||
|
||||
import tools / kochdocs
|
||||
import tools / deps
|
||||
|
||||
const VersionAsString = system.NimVersion
|
||||
|
||||
@@ -115,6 +116,7 @@ proc copyExe(source, dest: string) =
|
||||
|
||||
const
|
||||
compileNimInst = "tools/niminst/niminst"
|
||||
distDir = "dist"
|
||||
|
||||
proc csource(args: string) =
|
||||
nimexec(("cc $1 -r $3 --var:version=$2 --var:mingw=none csource " &
|
||||
@@ -122,45 +124,17 @@ proc csource(args: string) =
|
||||
[args, VersionAsString, compileNimInst])
|
||||
|
||||
proc bundleC2nim(args: string) =
|
||||
if not dirExists("dist/c2nim/.git"):
|
||||
exec("git clone https://github.com/nim-lang/c2nim.git dist/c2nim")
|
||||
cloneDependency(distDir, "https://github.com/nim-lang/c2nim.git")
|
||||
nimCompile("dist/c2nim/c2nim",
|
||||
options = "--noNimblePath --path:. " & args)
|
||||
|
||||
proc bundleNimbleExe(latest: bool, args: string) =
|
||||
if not dirExists("dist/nimble/.git"):
|
||||
exec("git clone https://github.com/nim-lang/nimble.git dist/nimble")
|
||||
if not latest:
|
||||
withDir("dist/nimble"):
|
||||
exec("git fetch")
|
||||
exec("git checkout " & NimbleStableCommit)
|
||||
let commit = if latest: "HEAD" else: NimbleStableCommit
|
||||
cloneDependency(distDir, "https://github.com/nim-lang/nimble.git",
|
||||
commit = commit, allowBundled = true)
|
||||
# installer.ini expects it under $nim/bin
|
||||
nimCompile("dist/nimble/src/nimble.nim",
|
||||
options = "-d:release --nilseqs:on " & args)
|
||||
|
||||
proc buildNimble(latest: bool, args: string) =
|
||||
# if koch is used for a tar.xz, build the dist/nimble we shipped
|
||||
# with the tarball:
|
||||
var installDir = "dist/nimble"
|
||||
if not latest and dirExists(installDir) and not dirExists("dist/nimble/.git"):
|
||||
discard "don't do the git dance"
|
||||
else:
|
||||
if not dirExists("dist/nimble/.git"):
|
||||
if dirExists(installDir):
|
||||
var id = 0
|
||||
while dirExists("dist/nimble" & $id):
|
||||
inc id
|
||||
installDir = "dist/nimble" & $id
|
||||
exec("git clone https://github.com/nim-lang/nimble.git " & installDir)
|
||||
withDir(installDir):
|
||||
if latest:
|
||||
exec("git checkout -f master")
|
||||
exec("git pull")
|
||||
else:
|
||||
exec("git fetch")
|
||||
exec("git checkout " & NimbleStableCommit)
|
||||
nimCompile(installDir / "src/nimble.nim",
|
||||
options = "--noNimblePath --nilseqs:on -d:release " & args)
|
||||
options = "-d:release --noNimblePath --nilseqs:on " & args)
|
||||
|
||||
proc bundleNimsuggest(args: string) =
|
||||
nimCompileFold("Compile nimsuggest", "nimsuggest/nimsuggest.nim",
|
||||
@@ -258,7 +232,7 @@ when false:
|
||||
|
||||
proc pdf(args="") =
|
||||
exec("$# cc -r tools/nimweb.nim $# --pdf web/website.ini --putenv:nimversion=$#" %
|
||||
[findNim(), args, VersionAsString], additionalPATH=findNim().splitFile.dir)
|
||||
[findNim().quoteShell(), args, VersionAsString], additionalPATH=findNim().splitFile.dir)
|
||||
|
||||
# -------------- boot ---------------------------------------------------------
|
||||
|
||||
@@ -296,7 +270,7 @@ proc boot(args: string) =
|
||||
let smartNimcache = (if "release" in args or "danger" in args: "nimcache/r_" else: "nimcache/d_") &
|
||||
hostOS & "_" & hostCPU
|
||||
|
||||
let nimStart = findStartNim()
|
||||
let nimStart = findStartNim().quoteShell()
|
||||
for i in 0..2:
|
||||
let defaultCommand = if useCpp: "cpp" else: "c"
|
||||
let bootOptions = if args.len == 0 or args.startsWith("-"): defaultCommand else: ""
|
||||
@@ -318,10 +292,10 @@ proc boot(args: string) =
|
||||
# in order to use less memory, we split the build into two steps:
|
||||
# --compileOnly produces a $project.json file and does not run GCC/Clang.
|
||||
# jsonbuild then uses the $project.json file to build the Nim binary.
|
||||
exec "$# $# $# $# --nimcache:$# --compileOnly compiler" / "nim.nim" %
|
||||
[nimi, bootOptions, extraOption, args, smartNimcache]
|
||||
exec "$# jsonscript $# --nimcache:$# compiler" / "nim.nim" %
|
||||
[nimi, args, smartNimcache]
|
||||
exec "$# $# $# --nimcache:$# $# --compileOnly compiler" / "nim.nim" %
|
||||
[nimi, bootOptions, extraOption, smartNimcache, args]
|
||||
exec "$# jsonscript --nimcache:$# $# compiler" / "nim.nim" %
|
||||
[nimi, smartNimcache, args]
|
||||
|
||||
if sameFileContent(output, i.thVersion):
|
||||
copyExe(output, finalDest)
|
||||
@@ -454,7 +428,7 @@ proc temp(args: string) =
|
||||
"threads" notin programArgs and
|
||||
"js" notin programArgs:
|
||||
bootArgs.add " -d:leanCompiler"
|
||||
let nimexec = findNim()
|
||||
let nimexec = findNim().quoteShell()
|
||||
exec(nimexec & " c -d:debug --debugger:native -d:nimBetterRun " & bootArgs & " " & (d / "compiler" / "nim"), 125)
|
||||
copyExe(output, finalDest)
|
||||
setCurrentDir(origDir)
|
||||
@@ -479,7 +453,7 @@ proc runCI(cmd: string) =
|
||||
when defined(posix): # appveyor (on windows) didn't run this
|
||||
kochExecFold("Boot", "boot")
|
||||
# boot without -d:nimHasLibFFI to make sure this still works
|
||||
kochExecFold("Boot in release mode", "boot -d:release -d:danger")
|
||||
kochExecFold("Boot in release mode", "boot -d:release")
|
||||
|
||||
## build nimble early on to enable remainder to depend on it if needed
|
||||
kochExecFold("Build Nimble", "nimble")
|
||||
@@ -491,7 +465,7 @@ proc runCI(cmd: string) =
|
||||
if getEnv("NIM_TEST_PACKAGES", "false") == "true":
|
||||
execFold("Test selected Nimble packages", "nim c -r testament/testament cat nimble-packages")
|
||||
else:
|
||||
buildTools() # altenatively, kochExec "tools --toolsNoNimble"
|
||||
buildTools()
|
||||
|
||||
## run tests
|
||||
execFold("Test nimscript", "nim e tests/test_nimscript.nims")
|
||||
@@ -628,13 +602,13 @@ when isMainModule:
|
||||
of "temp": temp(op.cmdLineRest)
|
||||
of "xtemp": xtemp(op.cmdLineRest)
|
||||
of "wintools": bundleWinTools(op.cmdLineRest)
|
||||
of "nimble": buildNimble(latest, op.cmdLineRest)
|
||||
of "nimble": bundleNimbleExe(latest, op.cmdLineRest)
|
||||
of "nimsuggest": bundleNimsuggest(op.cmdLineRest)
|
||||
of "toolsnonimble":
|
||||
buildTools(op.cmdLineRest)
|
||||
of "tools":
|
||||
buildTools(op.cmdLineRest)
|
||||
buildNimble(latest, op.cmdLineRest)
|
||||
bundleNimbleExe(latest, op.cmdLineRest)
|
||||
of "pushcsource", "pushcsources": pushCsources()
|
||||
of "valgrind": valgrind(op.cmdLineRest)
|
||||
of "c2nim": bundleC2nim(op.cmdLineRest)
|
||||
|
||||
@@ -242,7 +242,7 @@ proc tryExec*(db: var DbConn, query: SqlQuery, args: varargs[string, `$`]): bool
|
||||
try:
|
||||
db.prepareFetchDirect(query, args)
|
||||
var
|
||||
rCnt = -1
|
||||
rCnt:TSqlLen = -1
|
||||
res = SQLRowCount(db.stmt, rCnt)
|
||||
properFreeResult(SQL_HANDLE_STMT, db.stmt)
|
||||
if res != SQL_SUCCESS: dbError(db)
|
||||
@@ -461,10 +461,10 @@ proc execAffectedRows*(db: var DbConn, query: SqlQuery,
|
||||
var q = dbFormat(query, args)
|
||||
db.sqlCheck(SQLPrepare(db.stmt, q.PSQLCHAR, q.len.TSqlSmallInt))
|
||||
rawExec(db, query, args)
|
||||
var rCnt = -1
|
||||
var rCnt:TSqlLen = -1
|
||||
db.sqlCheck(SQLRowCount(db.hDb, rCnt))
|
||||
properFreeResult(SQL_HANDLE_STMT, db.stmt)
|
||||
result = rCnt
|
||||
result = rCnt.int64
|
||||
|
||||
proc close*(db: var DbConn) {.
|
||||
tags: [WriteDbEffect], raises: [].} =
|
||||
@@ -489,7 +489,7 @@ proc open*(connection, user, password, database: string): DbConn {.
|
||||
## Currently the database parameter is ignored,
|
||||
## but included to match ``open()`` in the other db_xxxxx library modules.
|
||||
var
|
||||
val: TSqlInteger = SQL_OV_ODBC3
|
||||
val = SQL_OV_ODBC3
|
||||
resLen = 0
|
||||
result = (hDb: nil, env: nil, stmt: nil)
|
||||
# allocate environment handle
|
||||
@@ -497,7 +497,7 @@ proc open*(connection, user, password, database: string): DbConn {.
|
||||
if res != SQL_SUCCESS: dbError("Error: unable to initialise ODBC environment.")
|
||||
res = SQLSetEnvAttr(result.env,
|
||||
SQL_ATTR_ODBC_VERSION.TSqlInteger,
|
||||
val, resLen.TSqlInteger)
|
||||
cast[SqlPointer](val.addr), resLen.TSqlInteger)
|
||||
if res != SQL_SUCCESS: dbError("Error: unable to set ODBC driver version.")
|
||||
# allocate hDb handle
|
||||
res = SQLAllocHandle(SQL_HANDLE_DBC, result.env, result.hDb)
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
when defined(js):
|
||||
{.error: "This library needs to be compiled with a c-like backend, and depends on PCRE.".}
|
||||
|
||||
## What is NRE?
|
||||
## ============
|
||||
##
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
when defined(js):
|
||||
{.error: "This library needs to be compiled with a c-like backend, and depends on PCRE.".}
|
||||
|
||||
## Regular expression support for Nim.
|
||||
##
|
||||
## This module is implemented by providing a wrapper around the
|
||||
@@ -665,4 +668,3 @@ when isMainModule:
|
||||
doAssert replace("bar", re"^", "foo") == "foobar"
|
||||
doAssert replace("foo", re"", "-") == "-foo"
|
||||
doAssert replace("foo", re"$", "bar") == "foobar"
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
## var document {.importc, nodecl.}: JsObject
|
||||
## var console {.importc, nodecl.}: JsObject
|
||||
## # import the "$" function
|
||||
## proc jq(selector: JsObject): JsObject {.importcpp: "$(#)".}
|
||||
## proc jq(selector: JsObject): JsObject {.importcpp: "$$(#)".}
|
||||
##
|
||||
## # Use jQuery to make the following code run, after the document is ready.
|
||||
## # This uses an experimental ``.()`` operator for ``JsObject``, to emit
|
||||
|
||||
@@ -34,7 +34,12 @@ type
|
||||
SocketHandle* = distinct cint # The type used to represent socket descriptors
|
||||
|
||||
type
|
||||
Time* {.importc: "time_t", header: "<time.h>".} = distinct clong
|
||||
Time* {.importc: "time_t", header: "<time.h>".} = distinct (
|
||||
when defined(nimUse64BitCTime):
|
||||
int64
|
||||
else:
|
||||
clong
|
||||
)
|
||||
|
||||
Timespec* {.importc: "struct timespec",
|
||||
header: "<time.h>", final, pure.} = object ## struct timespec
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
## (year: 2010, name: "Jane")]
|
||||
##
|
||||
## proc myCmp(x, y: People): int =
|
||||
## if x.name < y.name: -1 else: 1
|
||||
## if x.name < y.name: -1
|
||||
## elif x.name == y.name: 0
|
||||
## else: 1
|
||||
##
|
||||
## # Sorting with custom proc
|
||||
## a.sort(myCmp)
|
||||
|
||||
@@ -267,7 +267,7 @@ when defined(windows) or defined(nimdoc):
|
||||
pcd: PostCallbackDataPtr
|
||||
AsyncEvent* = ptr AsyncEventImpl
|
||||
|
||||
Callback = proc (fd: AsyncFD): bool {.closure, gcsafe.}
|
||||
Callback* = proc (fd: AsyncFD): bool {.closure, gcsafe.}
|
||||
|
||||
proc hash(x: AsyncFD): Hash {.borrow.}
|
||||
proc `==`*(x: AsyncFD, y: AsyncFD): bool {.borrow.}
|
||||
@@ -997,10 +997,11 @@ when defined(windows) or defined(nimdoc):
|
||||
proc addProcess*(pid: int, cb: Callback) =
|
||||
## Registers callback ``cb`` to be called when process with process ID
|
||||
## ``pid`` exited.
|
||||
const NULL = Handle(0)
|
||||
let p = getGlobalDispatcher()
|
||||
let procFlags = SYNCHRONIZE
|
||||
var hProcess = openProcess(procFlags, 0, pid.DWORD)
|
||||
if hProcess == INVALID_HANDLE_VALUE:
|
||||
if hProcess == NULL:
|
||||
raiseOSError(osLastError())
|
||||
|
||||
var pcd = cast[PostCallbackDataPtr](allocShared0(sizeof(PostCallbackData)))
|
||||
@@ -1093,7 +1094,7 @@ else:
|
||||
# queue.
|
||||
type
|
||||
AsyncFD* = distinct cint
|
||||
Callback = proc (fd: AsyncFD): bool {.closure, gcsafe.}
|
||||
Callback* = proc (fd: AsyncFD): bool {.closure, gcsafe.}
|
||||
|
||||
AsyncData = object
|
||||
readList: seq[Callback]
|
||||
@@ -1205,14 +1206,19 @@ else:
|
||||
let newLength = max(len(curList), InitCallbackListSize)
|
||||
var newList = newSeqOfCap[Callback](newLength)
|
||||
|
||||
var eventsExtinguished = false
|
||||
for cb in curList:
|
||||
if eventsExtinguished:
|
||||
newList.add(cb)
|
||||
continue
|
||||
if not cb(fd):
|
||||
# Callback wants to be called again.
|
||||
newList.add(cb)
|
||||
# This callback has returned with EAGAIN, so we don't need to
|
||||
# call any other callbacks as they are all waiting for the same event
|
||||
# on the same fd.
|
||||
break
|
||||
# We do need to ensure they are called again though.
|
||||
eventsExtinguished = true
|
||||
|
||||
withData(selector, fd.int, fdData) do:
|
||||
# Descriptor is still present in the queue.
|
||||
|
||||
@@ -131,12 +131,13 @@ type
|
||||
const multiLineLimit = 10000
|
||||
|
||||
proc expectReply(ftp: AsyncFtpClient): Future[TaintedString] {.async.} =
|
||||
result = await ftp.csock.recvLine()
|
||||
var line = await ftp.csock.recvLine()
|
||||
result = TaintedString(line)
|
||||
var count = 0
|
||||
while result[3] == '-':
|
||||
while line.len > 3 and line[3] == '-':
|
||||
## Multi-line reply.
|
||||
let line = await ftp.csock.recvLine()
|
||||
result.add("\n" & line)
|
||||
line = await ftp.csock.recvLine()
|
||||
string(result).add("\n" & line)
|
||||
count.inc()
|
||||
if count >= multiLineLimit:
|
||||
raise newException(ReplyError, "Reached maximum multi-line reply count.")
|
||||
@@ -145,7 +146,11 @@ proc send*(ftp: AsyncFtpClient, m: string): Future[TaintedString] {.async.} =
|
||||
## Send a message to the server, and wait for a primary reply.
|
||||
## ``\c\L`` is added for you.
|
||||
##
|
||||
## You need to make sure that the message ``m`` doesn't contain any newline
|
||||
## characters. Failing to do so will raise ``AssertionDefect``.
|
||||
##
|
||||
## **Note:** The server may return multiple lines of coded replies.
|
||||
doAssert(not m.contains({'\c', '\L'}), "message shouldn't contain any newline characters")
|
||||
await ftp.csock.send(m & "\c\L")
|
||||
return await ftp.expectReply()
|
||||
|
||||
@@ -178,7 +183,7 @@ proc connect*(ftp: AsyncFtpClient) {.async.} =
|
||||
await ftp.csock.connect(ftp.address, ftp.port)
|
||||
|
||||
var reply = await ftp.expectReply()
|
||||
if reply.startsWith("120"):
|
||||
if string(reply).startsWith("120"):
|
||||
# 120 Service ready in nnn minutes.
|
||||
# We wait until we receive 220.
|
||||
reply = await ftp.expectReply()
|
||||
@@ -357,7 +362,7 @@ proc doUpload(ftp: AsyncFtpClient, file: File,
|
||||
var countdownFut = sleepAsync(1000)
|
||||
var sendFut: Future[void] = nil
|
||||
while ftp.dsockConnected:
|
||||
if sendFut == nil or sendFut.finished:
|
||||
if sendFut == nil or sendFut.finished:
|
||||
# TODO: Async file reading.
|
||||
let len = file.readBuffer(addr(data[0]), 4000)
|
||||
setLen(data, len)
|
||||
|
||||
@@ -46,7 +46,7 @@ template createCb(retFutureSym, iteratorNameSym,
|
||||
else:
|
||||
{.gcsafe.}:
|
||||
{.push hint[ConvFromXtoItselfNotNeeded]: off.}
|
||||
next.callback = (proc() {.closure, gcsafe.})(identName)
|
||||
next.addCallback cast[proc() {.closure, gcsafe.}](identName)
|
||||
{.pop.}
|
||||
except:
|
||||
futureVarCompletions
|
||||
|
||||
@@ -689,8 +689,12 @@ elif defined(nimdoc):
|
||||
|
||||
proc close*(socket: AsyncSocket) =
|
||||
## Closes the socket.
|
||||
if socket.closed: return
|
||||
|
||||
defer:
|
||||
socket.fd.AsyncFD.closeSocket()
|
||||
socket.closed = true # TODO: Add extra debugging checks for this.
|
||||
|
||||
when defineSsl:
|
||||
if socket.isSsl:
|
||||
let res = SSL_shutdown(socket.sslHandle)
|
||||
@@ -699,7 +703,6 @@ proc close*(socket: AsyncSocket) =
|
||||
discard
|
||||
elif res != 1:
|
||||
raiseSSLError()
|
||||
socket.closed = true # TODO: Add extra debugging checks for this.
|
||||
|
||||
when defineSsl:
|
||||
proc wrapSocket*(ctx: SslContext, socket: AsyncSocket) =
|
||||
|
||||
@@ -16,9 +16,21 @@ import strutils
|
||||
|
||||
when defined(windows):
|
||||
import winlean
|
||||
from os import absolutePath
|
||||
else:
|
||||
import os, osproc
|
||||
|
||||
const osOpenCmd* =
|
||||
when defined(macos) or defined(macosx) or defined(windows): "open" else: "xdg-open" ## \
|
||||
## Alias for the operating system specific *"open"* command,
|
||||
## ``"open"`` on OSX, MacOS and Windows, ``"xdg-open"`` on Linux, BSD, etc.
|
||||
|
||||
proc prepare(s: string): string =
|
||||
if s.contains("://"):
|
||||
result = s
|
||||
else:
|
||||
result = "file://" & absolutePath(s)
|
||||
|
||||
proc openDefaultBrowser*(url: string) =
|
||||
## opens `url` with the user's default browser. This does not block.
|
||||
##
|
||||
@@ -29,14 +41,14 @@ proc openDefaultBrowser*(url: string) =
|
||||
##
|
||||
## This proc doesn't raise an exception on error, beware.
|
||||
when defined(windows):
|
||||
var o = newWideCString("open")
|
||||
var u = newWideCString(url)
|
||||
var o = newWideCString(osOpenCmd)
|
||||
var u = newWideCString(prepare url)
|
||||
discard shellExecuteW(0'i32, o, u, nil, nil, SW_SHOWNORMAL)
|
||||
elif defined(macosx):
|
||||
discard execShellCmd("open " & quoteShell(url))
|
||||
discard execShellCmd(osOpenCmd & " " & quoteShell(prepare url))
|
||||
else:
|
||||
var u = quoteShell(url)
|
||||
if execShellCmd("xdg-open " & u) == 0: return
|
||||
var u = quoteShell(prepare url)
|
||||
if execShellCmd(osOpenCmd & " " & u) == 0: return
|
||||
for b in getEnv("BROWSER").string.split(PathSep):
|
||||
try:
|
||||
# we use ``startProcess`` here because we don't want to block!
|
||||
|
||||
@@ -32,12 +32,7 @@
|
||||
import strutils, os, strtabs, cookies, uri
|
||||
export uri.encodeUrl, uri.decodeUrl
|
||||
|
||||
proc handleHexChar(c: char, x: var int) {.inline.} =
|
||||
case c
|
||||
of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
|
||||
of 'a'..'f': x = (x shl 4) or (ord(c) - ord('a') + 10)
|
||||
of 'A'..'F': x = (x shl 4) or (ord(c) - ord('A') + 10)
|
||||
else: assert(false)
|
||||
include includes/decode_helpers
|
||||
|
||||
proc addXmlChar(dest: var string, c: char) {.inline.} =
|
||||
case c
|
||||
@@ -93,40 +88,27 @@ proc getEncodedData(allowedMethods: set[RequestMethod]): string =
|
||||
iterator decodeData*(data: string): tuple[key, value: TaintedString] =
|
||||
## Reads and decodes CGI data and yields the (name, value) pairs the
|
||||
## data consists of.
|
||||
proc parseData(data: string, i: int, field: var string): int =
|
||||
result = i
|
||||
while result < data.len:
|
||||
case data[result]
|
||||
of '%': add(field, decodePercent(data, result))
|
||||
of '+': add(field, ' ')
|
||||
of '=', '&': break
|
||||
else: add(field, data[result])
|
||||
inc(result)
|
||||
|
||||
var i = 0
|
||||
var name = ""
|
||||
var value = ""
|
||||
# decode everything in one pass:
|
||||
while i < data.len:
|
||||
setLen(name, 0) # reuse memory
|
||||
while i < data.len:
|
||||
case data[i]
|
||||
of '%':
|
||||
var x = 0
|
||||
handleHexChar(data[i+1], x)
|
||||
handleHexChar(data[i+2], x)
|
||||
inc(i, 2)
|
||||
add(name, chr(x))
|
||||
of '+': add(name, ' ')
|
||||
of '=', '&': break
|
||||
else: add(name, data[i])
|
||||
inc(i)
|
||||
i = parseData(data, i, name)
|
||||
if i >= data.len or data[i] != '=': cgiError("'=' expected")
|
||||
inc(i) # skip '='
|
||||
setLen(value, 0) # reuse memory
|
||||
while i < data.len:
|
||||
case data[i]
|
||||
of '%':
|
||||
var x = 0
|
||||
if i+2 < data.len:
|
||||
handleHexChar(data[i+1], x)
|
||||
handleHexChar(data[i+2], x)
|
||||
inc(i, 2)
|
||||
add(value, chr(x))
|
||||
of '+': add(value, ' ')
|
||||
of '&', '\0': break
|
||||
else: add(value, data[i])
|
||||
inc(i)
|
||||
i = parseData(data, i, value)
|
||||
yield (name.TaintedString, value.TaintedString)
|
||||
if i < data.len:
|
||||
if data[i] == '&': inc(i)
|
||||
|
||||
@@ -317,6 +317,15 @@ proc excl*(s: var IntSet, other: IntSet) =
|
||||
|
||||
for item in other: excl(s, item)
|
||||
|
||||
proc len*(s: IntSet): int {.inline.} =
|
||||
## Returns the number of elements in `s`.
|
||||
if s.elems < s.a.len:
|
||||
result = s.elems
|
||||
else:
|
||||
result = 0
|
||||
for _ in s:
|
||||
inc(result)
|
||||
|
||||
proc missingOrExcl*(s: var IntSet, key: int): bool =
|
||||
## Excludes `key` in the set `s` and tells if `key` was already missing from `s`.
|
||||
##
|
||||
@@ -335,9 +344,9 @@ proc missingOrExcl*(s: var IntSet, key: int): bool =
|
||||
assert a.missingOrExcl(5) == false
|
||||
assert a.missingOrExcl(5) == true
|
||||
|
||||
var count = s.elems
|
||||
var count = s.len
|
||||
exclImpl(s, key)
|
||||
result = count == s.elems
|
||||
result = count == s.len
|
||||
|
||||
proc clear*(result: var IntSet) =
|
||||
## Clears the IntSet back to an empty state.
|
||||
@@ -500,15 +509,6 @@ proc disjoint*(s1, s2: IntSet): bool =
|
||||
return false
|
||||
return true
|
||||
|
||||
proc len*(s: IntSet): int {.inline.} =
|
||||
## Returns the number of elements in `s`.
|
||||
if s.elems < s.a.len:
|
||||
result = s.elems
|
||||
else:
|
||||
result = 0
|
||||
for _ in s:
|
||||
inc(result)
|
||||
|
||||
proc card*(s: IntSet): int {.inline.} =
|
||||
## Alias for `len() <#len,IntSet>`_.
|
||||
result = s.len()
|
||||
|
||||
@@ -204,6 +204,11 @@ proc del*[A, B](t: var SharedTable[A, B], key: A) =
|
||||
withLock t:
|
||||
delImpl()
|
||||
|
||||
proc len*[A, B](t: var SharedTable[A, B]): int =
|
||||
## number of elements in `t`
|
||||
withLock t:
|
||||
result = t.counter
|
||||
|
||||
proc init*[A, B](t: var SharedTable[A, B], initialSize = 64) =
|
||||
## creates a new hash table that is empty.
|
||||
##
|
||||
|
||||
@@ -114,13 +114,23 @@ template clearImpl() {.dirty.} =
|
||||
t.data[i].val = default(type(t.data[i].val))
|
||||
t.counter = 0
|
||||
|
||||
template ctAnd(a, b): bool =
|
||||
# pending https://github.com/nim-lang/Nim/issues/13502
|
||||
when a:
|
||||
when b: true
|
||||
else: false
|
||||
else: false
|
||||
|
||||
template initImpl(result: typed, size: int) =
|
||||
assert isPowerOfTwo(size)
|
||||
result.counter = 0
|
||||
newSeq(result.data, size)
|
||||
when compiles(result.first):
|
||||
result.first = -1
|
||||
result.last = -1
|
||||
when ctAnd(declared(SharedTable), type(result) is SharedTable):
|
||||
init(result, size)
|
||||
else:
|
||||
assert isPowerOfTwo(size)
|
||||
result.counter = 0
|
||||
newSeq(result.data, size)
|
||||
when compiles(result.first):
|
||||
result.first = -1
|
||||
result.last = -1
|
||||
|
||||
template insertImpl() = # for CountTable
|
||||
if t.dataLen == 0: initImpl(t, defaultInitialSize)
|
||||
|
||||
@@ -2239,13 +2239,6 @@ proc `[]`*[A](t: CountTable[A], key: A): int =
|
||||
assert(not t.isSorted, "CountTable must not be used after sorting")
|
||||
ctget(t, key, 0)
|
||||
|
||||
proc mget*[A](t: var CountTable[A], key: A): var int =
|
||||
## Retrieves the value at ``t[key]``. The value can be modified.
|
||||
##
|
||||
## If ``key`` is not in ``t``, the ``KeyError`` exception is raised.
|
||||
assert(not t.isSorted, "CountTable must not be used after sorting")
|
||||
get(t, key)
|
||||
|
||||
proc `[]=`*[A](t: var CountTable[A], key: A, val: int) =
|
||||
## Inserts a ``(key, value)`` pair into ``t``.
|
||||
##
|
||||
@@ -2553,19 +2546,13 @@ proc `[]`*[A](t: CountTableRef[A], key: A): int =
|
||||
## See also:
|
||||
## * `getOrDefault<#getOrDefault,CountTableRef[A],A,int>`_ to return
|
||||
## a custom value if the key doesn't exist
|
||||
## * `mget proc<#mget,CountTableRef[A],A>`_
|
||||
## * `inc proc<#inc,CountTableRef[A],A>`_ to inc even if missing
|
||||
## * `[]= proc<#[]%3D,CountTableRef[A],A,int>`_ for inserting a new
|
||||
## (key, value) pair in the table
|
||||
## * `hasKey proc<#hasKey,CountTableRef[A],A>`_ for checking if a key
|
||||
## is in the table
|
||||
result = t[][key]
|
||||
|
||||
proc mget*[A](t: CountTableRef[A], key: A): var int =
|
||||
## Retrieves the value at ``t[key]``. The value can be modified.
|
||||
##
|
||||
## If ``key`` is not in ``t``, the ``KeyError`` exception is raised.
|
||||
mget(t[], key)
|
||||
|
||||
proc `[]=`*[A](t: CountTableRef[A], key: A, val: int) =
|
||||
## Inserts a ``(key, value)`` pair into ``t``.
|
||||
##
|
||||
|
||||
@@ -218,7 +218,8 @@ proc contentLength*(response: Response | AsyncResponse): int =
|
||||
##
|
||||
## A ``ValueError`` exception will be raised if the value is not an integer.
|
||||
var contentLengthHeader = response.headers.getOrDefault("Content-Length")
|
||||
return contentLengthHeader.parseInt()
|
||||
result = contentLengthHeader.parseInt()
|
||||
doAssert(result >= 0 and result <= high(int32))
|
||||
|
||||
proc lastModified*(response: Response | AsyncResponse): DateTime =
|
||||
## Retrieves the specified response's last modified time.
|
||||
@@ -904,6 +905,11 @@ proc request*(client: HttpClient | AsyncHttpClient, url: string,
|
||||
##
|
||||
## This procedure will follow redirects up to a maximum number of redirects
|
||||
## specified in ``client.maxRedirects``.
|
||||
##
|
||||
## You need to make sure that the ``url`` doesn't contain any newline
|
||||
## characters. Failing to do so will raise ``AssertionDefect``.
|
||||
doAssert(not url.contains({'\c', '\L'}), "url shouldn't contain any newline characters")
|
||||
|
||||
result = await client.requestAux(url, httpMethod, body, headers)
|
||||
|
||||
var lastURL = url
|
||||
|
||||
24
lib/pure/includes/decode_helpers.nim
Normal file
24
lib/pure/includes/decode_helpers.nim
Normal file
@@ -0,0 +1,24 @@
|
||||
# Include file that implements 'decodePercent' and friends. Do not import it!
|
||||
|
||||
proc handleHexChar(c: char, x: var int, f: var bool) {.inline.} =
|
||||
case c
|
||||
of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
|
||||
of 'a'..'f': x = (x shl 4) or (ord(c) - ord('a') + 10)
|
||||
of 'A'..'F': x = (x shl 4) or (ord(c) - ord('A') + 10)
|
||||
else: f = true
|
||||
|
||||
proc decodePercent(s: string, i: var int): char =
|
||||
## Converts `%xx` hexadecimal to the charracter with ordinal number `xx`.
|
||||
##
|
||||
## If `xx` is not a valid hexadecimal value, it is left intact: only the
|
||||
## leading `%` is returned as-is, and `xx` characters will be processed in the
|
||||
## next step (e.g. in `uri.decodeUrl`) as regular characters.
|
||||
result = '%'
|
||||
if i+2 < s.len:
|
||||
var x = 0
|
||||
var failed = false
|
||||
handleHexChar(s[i+1], x, failed)
|
||||
handleHexChar(s[i+2], x, failed)
|
||||
if not failed:
|
||||
result = chr(x)
|
||||
inc(i, 2)
|
||||
@@ -114,7 +114,7 @@ proc osLastError*(): OSErrorCode {.sideEffect.} =
|
||||
when defined(nimscript):
|
||||
discard
|
||||
elif defined(windows):
|
||||
result = OSErrorCode(getLastError())
|
||||
result = cast[OSErrorCode](getLastError())
|
||||
else:
|
||||
result = OSErrorCode(errno)
|
||||
{.pop.}
|
||||
|
||||
@@ -181,6 +181,8 @@ type
|
||||
of JArray:
|
||||
elems*: seq[JsonNode]
|
||||
|
||||
const DepthLimit = 1000
|
||||
|
||||
proc newJString*(s: string): JsonNode =
|
||||
## Creates a new `JString JsonNode`.
|
||||
result = JsonNode(kind: JString, str: s)
|
||||
@@ -785,7 +787,7 @@ iterator mpairs*(node: var JsonNode): tuple[key: string, val: var JsonNode] =
|
||||
for key, val in mpairs(node.fields):
|
||||
yield (key, val)
|
||||
|
||||
proc parseJson(p: var JsonParser): JsonNode =
|
||||
proc parseJson(p: var JsonParser, depth=0): JsonNode =
|
||||
## Parses JSON from a JSON Parser `p`.
|
||||
case p.tok
|
||||
of tkString:
|
||||
@@ -809,6 +811,8 @@ proc parseJson(p: var JsonParser): JsonNode =
|
||||
result = newJNull()
|
||||
discard getTok(p)
|
||||
of tkCurlyLe:
|
||||
if depth > DepthLimit:
|
||||
raiseParseErr(p, "}")
|
||||
result = newJObject()
|
||||
discard getTok(p)
|
||||
while p.tok != tkCurlyRi:
|
||||
@@ -817,16 +821,18 @@ proc parseJson(p: var JsonParser): JsonNode =
|
||||
var key = p.a
|
||||
discard getTok(p)
|
||||
eat(p, tkColon)
|
||||
var val = parseJson(p)
|
||||
var val = parseJson(p, depth+1)
|
||||
result[key] = val
|
||||
if p.tok != tkComma: break
|
||||
discard getTok(p)
|
||||
eat(p, tkCurlyRi)
|
||||
of tkBracketLe:
|
||||
if depth > DepthLimit:
|
||||
raiseParseErr(p, "]")
|
||||
result = newJArray()
|
||||
discard getTok(p)
|
||||
while p.tok != tkBracketRi:
|
||||
result.add(parseJson(p))
|
||||
result.add(parseJson(p, depth+1))
|
||||
if p.tok != tkComma: break
|
||||
discard getTok(p)
|
||||
eat(p, tkBracketRi)
|
||||
|
||||
@@ -177,11 +177,16 @@ proc isDisconnectionError*(flags: set[SocketFlag],
|
||||
## if flags contains ``SafeDisconn``.
|
||||
when useWinVersion:
|
||||
SocketFlag.SafeDisconn in flags and
|
||||
lastError.int32 in {WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
|
||||
WSAEDISCON, ERROR_NETNAME_DELETED}
|
||||
(lastError.int32 == WSAECONNRESET or
|
||||
lastError.int32 == WSAECONNABORTED or
|
||||
lastError.int32 == WSAENETRESET or
|
||||
lastError.int32 == WSAEDISCON or
|
||||
lastError.int32 == ERROR_NETNAME_DELETED)
|
||||
else:
|
||||
SocketFlag.SafeDisconn in flags and
|
||||
lastError.int32 in {ECONNRESET, EPIPE, ENETRESET}
|
||||
(lastError.int32 == ECONNRESET or
|
||||
lastError.int32 == EPIPE or
|
||||
lastError.int32 == ENETRESET)
|
||||
|
||||
proc toOSFlags*(socketFlags: set[SocketFlag]): cint =
|
||||
## Converts the flags into the underlying OS representation.
|
||||
@@ -593,12 +598,11 @@ when defineSsl:
|
||||
let ctx = SslContext(context: ssl.SSL_get_SSL_CTX)
|
||||
let hintString = if hint == nil: "" else: $hint
|
||||
let (identityString, pskString) = (ctx.clientGetPskFunc)(hintString)
|
||||
if psk.len.cuint > max_psk_len:
|
||||
if pskString.len.cuint > max_psk_len:
|
||||
return 0
|
||||
if identityString.len.cuint >= max_identity_len:
|
||||
return 0
|
||||
|
||||
copyMem(identity, identityString.cstring, pskString.len + 1) # with the last zero byte
|
||||
copyMem(identity, identityString.cstring, identityString.len + 1) # with the last zero byte
|
||||
copyMem(psk, pskString.cstring, pskString.len)
|
||||
|
||||
return pskString.len.cuint
|
||||
@@ -619,7 +623,7 @@ when defineSsl:
|
||||
max_psk_len: cint): cuint {.cdecl.} =
|
||||
let ctx = SslContext(context: ssl.SSL_get_SSL_CTX)
|
||||
let pskString = (ctx.serverGetPskFunc)($identity)
|
||||
if psk.len.cint > max_psk_len:
|
||||
if pskString.len.cint > max_psk_len:
|
||||
return 0
|
||||
copyMem(psk, pskString.cstring, pskString.len)
|
||||
|
||||
@@ -1698,4 +1702,5 @@ proc getPrimaryIPAddr*(dest = parseIpAddress("8.8.8.8")): IpAddress =
|
||||
else:
|
||||
newSocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
|
||||
socket.connect($dest, 80.Port)
|
||||
socket.getLocalAddr()[0].parseIpAddress()
|
||||
result = socket.getLocalAddr()[0].parseIpAddress()
|
||||
socket.close()
|
||||
|
||||
@@ -130,6 +130,7 @@ proc joinPath*(head, tail: string): string {.
|
||||
when defined(posix):
|
||||
assert joinPath("usr", "lib") == "usr/lib"
|
||||
assert joinPath("usr", "") == "usr/"
|
||||
assert joinPath("", "") == ""
|
||||
assert joinPath("", "lib") == "lib"
|
||||
assert joinPath("", "/lib") == "/lib"
|
||||
assert joinPath("usr/", "/lib") == "usr/lib"
|
||||
@@ -138,7 +139,7 @@ proc joinPath*(head, tail: string): string {.
|
||||
result = newStringOfCap(head.len + tail.len)
|
||||
var state = 0
|
||||
addNormalizePath(head, result, state, DirSep)
|
||||
if tail.len == 0:
|
||||
if result.len != 0 and result[^1] notin {DirSep, AltSep} and tail.len == 0:
|
||||
result.add DirSep
|
||||
else:
|
||||
addNormalizePath(tail, result, state, DirSep)
|
||||
|
||||
@@ -440,7 +440,11 @@ when defined(Windows) and not defined(useNimRtl):
|
||||
handle: Handle
|
||||
atTheEnd: bool
|
||||
|
||||
proc hsClose(s: Stream) = discard # nothing to do here
|
||||
proc hsClose(s: Stream) =
|
||||
# xxx here + elsewhere: check instead of discard; ignoring errors leads to
|
||||
# hard to track bugs
|
||||
discard FileHandleStream(s).handle.closeHandle
|
||||
|
||||
proc hsAtEnd(s: Stream): bool = return FileHandleStream(s).atTheEnd
|
||||
|
||||
proc hsReadData(s: Stream, buffer: pointer, bufLen: int): int =
|
||||
|
||||
@@ -108,10 +108,10 @@ proc open*(my: var CsvParser, input: Stream, filename: string,
|
||||
## the diverse optional parameters:
|
||||
## - `separator`: character used to separate fields
|
||||
## - `quote`: Used to quote fields containing special characters like
|
||||
## `separator`, `quote` or new-line characters. '\0' disables the parsing
|
||||
## `separator`, `quote` or new-line characters. '\\0' disables the parsing
|
||||
## of quotes.
|
||||
## - `escape`: removes any special meaning from the following character;
|
||||
## '\0' disables escaping; if escaping is disabled and `quote` is not '\0',
|
||||
## '\\0' disables escaping; if escaping is disabled and `quote` is not '\\0',
|
||||
## two `quote` characters are parsed one literal `quote` character.
|
||||
## - `skipInitialSpace`: If true, whitespace immediately following the
|
||||
## `separator` is ignored.
|
||||
|
||||
@@ -12,32 +12,29 @@
|
||||
##
|
||||
## To unpack raw bytes look at the `streams <streams.html>`_ module.
|
||||
##
|
||||
##
|
||||
## .. code-block::
|
||||
## import parseutils
|
||||
## .. code-block:: nim
|
||||
## :test:
|
||||
##
|
||||
## let logs = @["2019-01-10: OK_", "2019-01-11: FAIL_", "2019-01: aaaa"]
|
||||
## var outp: seq[string]
|
||||
##
|
||||
## for log in logs:
|
||||
## var res: string
|
||||
## if parseUntil(log, res, ':') == 10: # YYYY-MM-DD == 10
|
||||
## echo res & " - " & captureBetween(log, ' ', '_')
|
||||
## # => 2019-01-10 - OK
|
||||
## outp.add(res & " - " & captureBetween(log, ' ', '_'))
|
||||
## doAssert outp == @["2019-01-10 - OK", "2019-01-11 - FAIL"]
|
||||
##
|
||||
##
|
||||
## .. code-block::
|
||||
## import parseutils
|
||||
## .. code-block:: nim
|
||||
## :test:
|
||||
## from strutils import Digits, parseInt
|
||||
##
|
||||
## let input1 = "2019 school start"
|
||||
## let input2 = "3 years back"
|
||||
##
|
||||
## let startYear = input1[0..skipWhile(input1, Digits)-1] # 2019
|
||||
## let yearsBack = input2[0..skipWhile(input2, Digits)-1] # 3
|
||||
##
|
||||
## echo "Examination is in " & $(parseInt(startYear) + parseInt(yearsBack))
|
||||
## # => Examination is in 2022
|
||||
##
|
||||
## let
|
||||
## input1 = "2019 school start"
|
||||
## input2 = "3 years back"
|
||||
## startYear = input1[0 .. skipWhile(input1, Digits)-1] # 2019
|
||||
## yearsBack = input2[0 .. skipWhile(input2, Digits)-1] # 3
|
||||
## examYear = parseInt(startYear) + parseInt(yearsBack)
|
||||
## doAssert "Examination is in " & $examYear == "Examination is in 2022"
|
||||
##
|
||||
## **See also:**
|
||||
## * `strutils module<strutils.html>`_ for combined and identical parsing proc's
|
||||
@@ -586,21 +583,17 @@ iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind,
|
||||
value: string] =
|
||||
## Tokenizes the string `s` into substrings for interpolation purposes.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## for k, v in interpolatedFragments(" $this is ${an example} $$"):
|
||||
## echo "(", k, ", \"", v, "\")"
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## (ikString, " ")
|
||||
## (ikExpr, "this")
|
||||
## (ikString, " is ")
|
||||
## (ikExpr, "an example")
|
||||
## (ikString, " ")
|
||||
## (ikDollar, "$")
|
||||
runnableExamples:
|
||||
var outp: seq[tuple[kind: InterpolatedKind, value: string]]
|
||||
for k, v in interpolatedFragments(" $this is ${an example} $$"):
|
||||
outp.add (k, v)
|
||||
doAssert outp == @[(ikStr, " "),
|
||||
(ikVar, "this"),
|
||||
(ikStr, " is "),
|
||||
(ikExpr, "an example"),
|
||||
(ikStr, " "),
|
||||
(ikDollar, "$")]
|
||||
|
||||
var i = 0
|
||||
var kind: InterpolatedKind
|
||||
while true:
|
||||
|
||||
@@ -666,6 +666,9 @@ proc parseAttribute(my: var XmlParser) =
|
||||
parseEntity(my, my.b)
|
||||
my.kind = xmlAttribute # parseEntity overwrites my.kind!
|
||||
pos = my.bufpos
|
||||
elif c == '/':
|
||||
pos = lexbase.handleRefillChar(my, pos)
|
||||
add(my.b, '/')
|
||||
else:
|
||||
add(my.b, c)
|
||||
inc(pos)
|
||||
|
||||
@@ -69,7 +69,8 @@ proc addNormalizePath*(x: string; result: var string; state: var int;
|
||||
while hasNext(it, x):
|
||||
let b = next(it, x)
|
||||
if (state shr 1 == 0) and isSlash(x, b):
|
||||
result.add dirSep
|
||||
if result.len == 0 or result[^1] notin {DirSep, AltSep}:
|
||||
result.add dirSep
|
||||
state = state or 1
|
||||
elif isDotDot(x, b):
|
||||
if (state shr 1) >= 1:
|
||||
|
||||
@@ -870,26 +870,26 @@ macro mkHandlerTplts(handlers: untyped): untyped =
|
||||
# The AST structure of *handlers[0]*:
|
||||
#
|
||||
# .. code-block::
|
||||
# StmtList
|
||||
# Call
|
||||
# Ident "pkNonTerminal"
|
||||
# StmtList
|
||||
# Call
|
||||
# Ident "enter"
|
||||
# StmtList
|
||||
# <handler code block>
|
||||
# Call
|
||||
# Ident "leave"
|
||||
# StmtList
|
||||
# <handler code block>
|
||||
# Call
|
||||
# Ident "pkChar"
|
||||
# StmtList
|
||||
# Call
|
||||
# Ident "leave"
|
||||
# StmtList
|
||||
# <handler code block>
|
||||
# ...
|
||||
# StmtList
|
||||
# Call
|
||||
# Ident "pkNonTerminal"
|
||||
# StmtList
|
||||
# Call
|
||||
# Ident "enter"
|
||||
# StmtList
|
||||
# <handler code block>
|
||||
# Call
|
||||
# Ident "leave"
|
||||
# StmtList
|
||||
# <handler code block>
|
||||
# Call
|
||||
# Ident "pkChar"
|
||||
# StmtList
|
||||
# Call
|
||||
# Ident "leave"
|
||||
# StmtList
|
||||
# <handler code block>
|
||||
# ...
|
||||
proc mkEnter(hdName, body: NimNode): NimNode =
|
||||
template helper(hdName, body) {.dirty.} =
|
||||
template hdName(s, p, start) =
|
||||
@@ -907,16 +907,16 @@ macro mkHandlerTplts(handlers: untyped): untyped =
|
||||
|
||||
result = newStmtList()
|
||||
for topCall in handlers[0]:
|
||||
if nnkCall != topCall.kind:
|
||||
if topCall.kind notin nnkCallKinds:
|
||||
error("Call syntax expected.", topCall)
|
||||
let pegKind = topCall[0]
|
||||
if nnkIdent != pegKind.kind:
|
||||
if pegKind.kind notin {nnkIdent, nnkSym}:
|
||||
error("PegKind expected.", pegKind)
|
||||
if 2 == topCall.len:
|
||||
for hdDef in topCall[1]:
|
||||
if nnkCall != hdDef.kind:
|
||||
if hdDef.kind notin nnkCallKinds:
|
||||
error("Call syntax expected.", hdDef)
|
||||
if nnkIdent != hdDef[0].kind:
|
||||
if hdDef[0].kind notin {nnkIdent, nnkSym}:
|
||||
error("Handler identifier expected.", hdDef[0])
|
||||
if 2 == hdDef.len:
|
||||
let hdPostf = substr(pegKind.strVal, 2)
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
## For SSL support this module relies on OpenSSL. If you want to
|
||||
## enable SSL, compile with ``-d:ssl``.
|
||||
|
||||
import net, strutils, strtabs, base64, os
|
||||
import net, strutils, strtabs, base64, os, strutils
|
||||
import asyncnet, asyncdispatch
|
||||
|
||||
export Port
|
||||
@@ -65,7 +65,22 @@ type
|
||||
Smtp* = SmtpBase[Socket]
|
||||
AsyncSmtp* = SmtpBase[AsyncSocket]
|
||||
|
||||
proc debugSend(smtp: Smtp | AsyncSmtp, cmd: string) {.multisync.} =
|
||||
proc containsNewline(xs: seq[string]): bool =
|
||||
for x in xs:
|
||||
if x.contains({'\c', '\L'}):
|
||||
return true
|
||||
|
||||
proc debugSend*(smtp: Smtp | AsyncSmtp, cmd: string) {.multisync.} =
|
||||
## Sends ``cmd`` on the socket connected to the SMTP server.
|
||||
##
|
||||
## If the ``smtp`` object was created with ``debug`` enabled,
|
||||
## debugSend will invoke ``echo("C:" & cmd)`` before sending.
|
||||
##
|
||||
## This is a lower level proc and not something that you typically
|
||||
## would need to call when using this module. One exception to
|
||||
## this is if you are implementing any
|
||||
## `SMTP extensions<https://en.wikipedia.org/wiki/Extended_SMTP>`_.
|
||||
|
||||
if smtp.debug:
|
||||
echo("C:" & cmd)
|
||||
await smtp.sock.send(cmd)
|
||||
@@ -95,6 +110,14 @@ else:
|
||||
proc createMessage*(mSubject, mBody: string, mTo, mCc: seq[string],
|
||||
otherHeaders: openarray[tuple[name, value: string]]): Message =
|
||||
## Creates a new MIME compliant message.
|
||||
##
|
||||
## You need to make sure that ``mSubject``, ``mTo`` and ``mCc`` don't contain
|
||||
## any newline characters. Failing to do so will raise ``AssertionDefect``.
|
||||
doAssert(not mSubject.contains({'\c', '\L'}),
|
||||
"'mSubject' shouldn't contain any newline characters")
|
||||
doAssert(not (mTo.containsNewline() or mCc.containsNewline()),
|
||||
"'mTo' and 'mCc' shouldn't contain any newline characters")
|
||||
|
||||
result.msgTo = mTo
|
||||
result.msgCc = mCc
|
||||
result.msgSubject = mSubject
|
||||
@@ -106,6 +129,13 @@ proc createMessage*(mSubject, mBody: string, mTo, mCc: seq[string],
|
||||
proc createMessage*(mSubject, mBody: string, mTo,
|
||||
mCc: seq[string] = @[]): Message =
|
||||
## Alternate version of the above.
|
||||
##
|
||||
## You need to make sure that ``mSubject``, ``mTo`` and ``mCc`` don't contain
|
||||
## any newline characters. Failing to do so will raise ``AssertionDefect``.
|
||||
doAssert(not mSubject.contains({'\c', '\L'}),
|
||||
"'mSubject' shouldn't contain any newline characters")
|
||||
doAssert(not (mTo.containsNewline() or mCc.containsNewline()),
|
||||
"'mTo' and 'mCc' shouldn't contain any newline characters")
|
||||
result.msgTo = mTo
|
||||
result.msgCc = mCc
|
||||
result.msgSubject = mSubject
|
||||
@@ -213,6 +243,11 @@ proc sendMail*(smtp: Smtp | AsyncSmtp, fromAddr: string,
|
||||
## Sends ``msg`` from ``fromAddr`` to the addresses specified in ``toAddrs``.
|
||||
## Messages may be formed using ``createMessage`` by converting the
|
||||
## Message into a string.
|
||||
##
|
||||
## You need to make sure that ``fromAddr`` and ``toAddrs`` don't contain
|
||||
## any newline characters. Failing to do so will raise ``AssertionDefect``.
|
||||
doAssert(not (toAddrs.containsNewline() or fromAddr.contains({'\c', '\L'})),
|
||||
"'toAddrs' and 'fromAddr' shouldn't contain any newline characters")
|
||||
|
||||
await smtp.debugSend("MAIL FROM:<" & fromAddr & ">\c\L")
|
||||
await smtp.checkReply("250")
|
||||
|
||||
@@ -687,10 +687,9 @@ template styledEchoProcessArg(f: File, color: Color) =
|
||||
template styledEchoProcessArg(f: File, cmd: TerminalCmd) =
|
||||
when cmd == resetStyle:
|
||||
resetAttributes(f)
|
||||
when cmd == fgColor:
|
||||
fgSetColor = true
|
||||
when cmd == bgColor:
|
||||
fgSetColor = false
|
||||
elif cmd in {fgColor, bgColor}:
|
||||
let term = getTerminal()
|
||||
term.fgSetColor = cmd == fgColor
|
||||
|
||||
macro styledWrite*(f: File, m: varargs[typed]): untyped =
|
||||
## Similar to ``write``, but treating terminal style arguments specially.
|
||||
|
||||
@@ -933,27 +933,23 @@ proc stringHasSep(s: string, index: int, sep: Rune): bool =
|
||||
fastRuneAt(s, index, rune, false)
|
||||
return sep == rune
|
||||
|
||||
template splitCommon(s, sep, maxsplit: untyped, sepLen: int = -1) =
|
||||
template splitCommon(s, sep, maxsplit: untyped) =
|
||||
## Common code for split procedures.
|
||||
let
|
||||
sLen = len(s)
|
||||
var
|
||||
last = 0
|
||||
splits = maxsplit
|
||||
if len(s) > 0:
|
||||
while last <= len(s):
|
||||
if sLen > 0:
|
||||
while last <= sLen:
|
||||
var first = last
|
||||
while last < len(s) and not stringHasSep(s, last, sep):
|
||||
when sep is Rune:
|
||||
inc(last, sepLen)
|
||||
else:
|
||||
inc(last, runeLenAt(s, last))
|
||||
if splits == 0: last = len(s)
|
||||
while last < sLen and not stringHasSep(s, last, sep):
|
||||
inc(last, runeLenAt(s, last))
|
||||
if splits == 0: last = sLen
|
||||
yield s[first .. (last - 1)]
|
||||
if splits == 0: break
|
||||
dec(splits)
|
||||
when sep is Rune:
|
||||
inc(last, sepLen)
|
||||
else:
|
||||
inc(last, if last < len(s): runeLenAt(s, last) else: 1)
|
||||
inc(last, if last < sLen: runeLenAt(s, last) else: 1)
|
||||
|
||||
iterator split*(s: string, seps: openArray[Rune] = unicodeSpaces,
|
||||
maxsplit: int = -1): string =
|
||||
@@ -1037,7 +1033,7 @@ iterator split*(s: string, sep: Rune, maxsplit: int = -1): string =
|
||||
## ""
|
||||
## ""
|
||||
##
|
||||
splitCommon(s, sep, maxsplit, sep.size)
|
||||
splitCommon(s, sep, maxsplit)
|
||||
|
||||
proc split*(s: string, seps: openArray[Rune] = unicodeSpaces, maxsplit: int = -1):
|
||||
seq[string] {.noSideEffect, rtl, extern: "nucSplitRunes".} =
|
||||
@@ -1424,6 +1420,7 @@ when isMainModule:
|
||||
"an", "example", "", ""]
|
||||
doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example "]
|
||||
doAssert s.split(' '.Rune, maxsplit = 1) == @["", "this is an example "]
|
||||
doAssert s3.split("×".runeAt(0)) == @[":this", "is", "an:example", "", ""]
|
||||
|
||||
block stripTests:
|
||||
doAssert(strip("") == "")
|
||||
|
||||
@@ -37,7 +37,9 @@
|
||||
## else:
|
||||
## echo "Wrong format"
|
||||
|
||||
import strutils, parseutils
|
||||
import strutils, parseutils, base64
|
||||
include includes/decode_helpers
|
||||
|
||||
type
|
||||
Url* = distinct string
|
||||
|
||||
@@ -81,6 +83,7 @@ proc decodeUrl*(s: string, decodePlus = true): string =
|
||||
## This means that any ``%xx`` (where ``xx`` denotes a hexadecimal
|
||||
## value) are converted to the character with ordinal number ``xx``,
|
||||
## and every other character is carried over.
|
||||
## If ``xx`` is not a valid hexadecimal value, it is left intact.
|
||||
##
|
||||
## As a special rule, when the value of ``decodePlus`` is true, ``+``
|
||||
## characters are converted to a space.
|
||||
@@ -92,12 +95,7 @@ proc decodeUrl*(s: string, decodePlus = true): string =
|
||||
assert decodeUrl("https%3A%2F%2Fnim-lang.org%2Fthis+is+a+test") == "https://nim-lang.org/this is a test"
|
||||
assert decodeUrl("https%3A%2F%2Fnim-lang.org%2Fthis%20is%20a%20test",
|
||||
false) == "https://nim-lang.org/this is a test"
|
||||
proc handleHexChar(c: char, x: var int) {.inline.} =
|
||||
case c
|
||||
of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
|
||||
of 'a'..'f': x = (x shl 4) or (ord(c) - ord('a') + 10)
|
||||
of 'A'..'F': x = (x shl 4) or (ord(c) - ord('A') + 10)
|
||||
else: assert(false)
|
||||
assert decodeUrl("abc%xyz") == "abc%xyz"
|
||||
|
||||
result = newString(s.len)
|
||||
var i = 0
|
||||
@@ -105,11 +103,7 @@ proc decodeUrl*(s: string, decodePlus = true): string =
|
||||
while i < s.len:
|
||||
case s[i]
|
||||
of '%':
|
||||
var x = 0
|
||||
handleHexChar(s[i+1], x)
|
||||
handleHexChar(s[i+2], x)
|
||||
inc(i, 2)
|
||||
result[j] = chr(x)
|
||||
result[j] = decodePercent(s, i)
|
||||
of '+':
|
||||
if decodePlus:
|
||||
result[j] = ' '
|
||||
|
||||
@@ -51,11 +51,6 @@ when defined(macosx):
|
||||
proc mach_timebase_info(info: var MachTimebaseInfoData) {.importc,
|
||||
header: "<mach/mach_time.h>".}
|
||||
|
||||
let machAbsoluteTimeFreq = block:
|
||||
var freq: MachTimebaseInfoData
|
||||
mach_timebase_info(freq)
|
||||
freq
|
||||
|
||||
when defined(js):
|
||||
proc getJsTicks: float =
|
||||
## Returns ticks in the unit seconds
|
||||
@@ -88,11 +83,6 @@ elif defined(windows):
|
||||
proc QueryPerformanceFrequency(res: var uint64) {.
|
||||
importc: "QueryPerformanceFrequency", stdcall, dynlib: "kernel32".}
|
||||
|
||||
let queryPerformanceCounterFreq = block:
|
||||
var freq: uint64
|
||||
QueryPerformanceFrequency(freq)
|
||||
1_000_000_000'u64 div freq
|
||||
|
||||
proc getMonoTime*(): MonoTime {.tags: [TimeEffect].} =
|
||||
## Get the current `MonoTime` timestamp.
|
||||
##
|
||||
@@ -105,6 +95,8 @@ proc getMonoTime*(): MonoTime {.tags: [TimeEffect].} =
|
||||
result = MonoTime(ticks: (ticks * 1_000_000_000).int64)
|
||||
elif defined(macosx):
|
||||
let ticks = mach_absolute_time()
|
||||
var machAbsoluteTimeFreq: MachTimebaseInfoData
|
||||
mach_timebase_info(machAbsoluteTimeFreq)
|
||||
result = MonoTime(ticks: ticks * machAbsoluteTimeFreq.numer div
|
||||
machAbsoluteTimeFreq.denom)
|
||||
elif defined(posix):
|
||||
@@ -115,6 +107,10 @@ proc getMonoTime*(): MonoTime {.tags: [TimeEffect].} =
|
||||
elif defined(windows):
|
||||
var ticks: uint64
|
||||
QueryPerformanceCounter(ticks)
|
||||
|
||||
var freq: uint64
|
||||
QueryPerformanceFrequency(freq)
|
||||
let queryPerformanceCounterFreq = 1_000_000_000'u64 div freq
|
||||
result = MonoTime(ticks: (ticks * queryPerformanceCounterFreq).int64)
|
||||
|
||||
proc ticks*(t: MonoTime): int64 =
|
||||
|
||||
@@ -3584,7 +3584,7 @@ const
|
||||
NimMinor* {.intdefine.}: int = 0
|
||||
## is the minor number of Nim's version.
|
||||
|
||||
NimPatch* {.intdefine.}: int = 6
|
||||
NimPatch* {.intdefine.}: int = 11
|
||||
## is the patch number of Nim's version.
|
||||
|
||||
NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
|
||||
|
||||
@@ -247,7 +247,7 @@ proc llAlloc(a: var MemRegion, size: int): pointer =
|
||||
sysAssert roundup(size+sizeof(LLChunk), PageSize) == PageSize, "roundup 6"
|
||||
var old = a.llmem # can be nil and is correct with nil
|
||||
a.llmem = cast[PLLChunk](osAllocPages(PageSize))
|
||||
when defined(avlcorruption):
|
||||
when defined(nimAvlcorruption):
|
||||
trackLocation(a.llmem, PageSize)
|
||||
incCurrMem(a, PageSize)
|
||||
a.llmem.size = PageSize - sizeof(LLChunk)
|
||||
@@ -270,7 +270,7 @@ proc allocAvlNode(a: var MemRegion, key, upperBound: int): PAvlNode =
|
||||
a.freeAvlNodes = a.freeAvlNodes.link[0]
|
||||
else:
|
||||
result = cast[PAvlNode](llAlloc(a, sizeof(AvlNode)))
|
||||
when defined(avlcorruption):
|
||||
when defined(nimAvlcorruption):
|
||||
cprintf("tracking location: %p\n", result)
|
||||
result.key = key
|
||||
result.upperBound = upperBound
|
||||
@@ -278,7 +278,7 @@ proc allocAvlNode(a: var MemRegion, key, upperBound: int): PAvlNode =
|
||||
result.link[0] = bottom
|
||||
result.link[1] = bottom
|
||||
result.level = 1
|
||||
#when defined(avlcorruption):
|
||||
#when defined(nimAvlcorruption):
|
||||
# track("allocAvlNode", result, sizeof(AvlNode))
|
||||
sysAssert(bottom == addr(a.bottomData), "bottom data")
|
||||
sysAssert(bottom.link[0] == bottom, "bottom link[0]")
|
||||
@@ -987,7 +987,7 @@ when defined(nimTypeNames):
|
||||
template instantiateForRegion(allocator: untyped) {.dirty.} =
|
||||
{.push stackTrace: off.}
|
||||
|
||||
when defined(fulldebug):
|
||||
when defined(nimFulldebug):
|
||||
proc interiorAllocatedPtr*(p: pointer): pointer =
|
||||
result = interiorAllocatedPtr(allocator, p)
|
||||
|
||||
|
||||
@@ -281,10 +281,7 @@ static int __tcc_cas(int *ptr, int oldVal, int newVal)
|
||||
: "r" (newVal), "m" (*ptr), "a" (oldVal)
|
||||
: "memory");
|
||||
|
||||
if (ret)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
""".}
|
||||
else:
|
||||
@@ -301,10 +298,7 @@ static int __tcc_cas(int *ptr, int oldVal, int newVal)
|
||||
: "r" (newVal), "m" (*ptr), "a" (oldVal)
|
||||
: "memory");
|
||||
|
||||
if (ret)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
""".}
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This is a part of ``system.nim``, you should not manually import it.
|
||||
|
||||
|
||||
include inclrtl
|
||||
import formatfloat
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ const
|
||||
debugGC = false # we wish to debug the GC...
|
||||
logGC = false
|
||||
traceGC = false # extensive debugging
|
||||
alwaysCycleGC = defined(smokeCycles)
|
||||
alwaysGC = defined(fulldebug) # collect after every memory
|
||||
alwaysCycleGC = defined(nimSmokeCycles)
|
||||
alwaysGC = defined(nimFulldebug) # collect after every memory
|
||||
# allocation (for debugging)
|
||||
leakDetector = defined(leakDetector)
|
||||
leakDetector = defined(nimLeakDetector)
|
||||
overwriteFree = defined(nimBurnFree) # overwrite memory with 0xFF before free
|
||||
trackAllocationSource = leakDetector
|
||||
|
||||
@@ -30,7 +30,7 @@ const
|
||||
coalescRight = true
|
||||
coalescLeft = true
|
||||
logAlloc = false
|
||||
useCellIds = defined(corruption)
|
||||
useCellIds = defined(nimCorruption)
|
||||
|
||||
type
|
||||
PPointer = ptr pointer
|
||||
|
||||
@@ -376,11 +376,26 @@ when not defined(nimble):
|
||||
template `==?`(a, b: string): bool = cmpIgnoreStyle(a, b) == 0
|
||||
template task*(name: untyped; description: string; body: untyped): untyped =
|
||||
## Defines a task. Hidden tasks are supported via an empty description.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## task build, "default build is via the C backend":
|
||||
## setCommand "c"
|
||||
##
|
||||
## For a task named ``foo``, this template generates a ``proc`` named
|
||||
## ``fooTask``. This is useful if you need to call one task in
|
||||
## another in your Nimscript.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## task foo, "foo": # > nim foo
|
||||
## echo "Running foo" # Running foo
|
||||
##
|
||||
## task bar, "bar": # > nim bar
|
||||
## echo "Running bar" # Running bar
|
||||
## fooTask() # Running foo
|
||||
proc `name Task`*() =
|
||||
setCommand "nop"
|
||||
body
|
||||
|
||||
@@ -245,15 +245,16 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
|
||||
var ti = 0
|
||||
let maxlen = t.high - "e+000".len # reserve enough space for exponent
|
||||
|
||||
result = i - start
|
||||
let endPos = i
|
||||
result = endPos - start
|
||||
i = start
|
||||
# re-parse without error checking, any error should be handled by the code above.
|
||||
if i < s.len and s[i] == '.': i.inc
|
||||
while i < s.len and s[i] in {'0'..'9','+','-'}:
|
||||
if i < endPos and s[i] == '.': i.inc
|
||||
while i < endPos and s[i] in {'0'..'9','+','-'}:
|
||||
if ti < maxlen:
|
||||
t[ti] = s[i]; inc(ti)
|
||||
inc(i)
|
||||
while i < s.len and s[i] in {'.', '_'}: # skip underscore and decimal point
|
||||
while i < endPos and s[i] in {'.', '_'}: # skip underscore and decimal point
|
||||
inc(i)
|
||||
|
||||
# insert exponent
|
||||
|
||||
@@ -145,13 +145,13 @@ else:
|
||||
SysCond = ptr SysCondObj
|
||||
|
||||
when not declared(c_malloc):
|
||||
proc c_malloc(size: csize): pointer {.
|
||||
proc c_malloc(size: csize_t): pointer {.
|
||||
importc: "malloc", header: "<stdlib.h>".}
|
||||
proc c_free(p: pointer) {.
|
||||
importc: "free", header: "<stdlib.h>".}
|
||||
|
||||
proc initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) =
|
||||
L = cast[SysLock](c_malloc(sizeof(SysLockObj)))
|
||||
L = cast[SysLock](c_malloc(csize_t(sizeof(SysLockObj))))
|
||||
initSysLockAux(L[], attr)
|
||||
|
||||
proc deinitSys(L: var SysLock) =
|
||||
@@ -201,7 +201,7 @@ else:
|
||||
|
||||
when defined(ios):
|
||||
proc initSysCond(cond: var SysCond, cond_attr: ptr SysCondAttr = nil) =
|
||||
cond = cast[SysCond](c_malloc(sizeof(SysCondObj)))
|
||||
cond = cast[SysCond](c_malloc(csize_t(sizeof(SysCondObj))))
|
||||
initSysCondAux(cond[], cond_attr)
|
||||
|
||||
proc deinitSysCond(cond: var SysCond) =
|
||||
|
||||
@@ -33,6 +33,8 @@ type
|
||||
ULONG* = int32
|
||||
PULONG* = ptr int
|
||||
WINBOOL* = int32
|
||||
## `WINBOOL` uses opposite convention as posix, !=0 meaning success.
|
||||
# xxx this should be distinct int32, distinct would make code less error prone
|
||||
DWORD* = int32
|
||||
PDWORD* = ptr DWORD
|
||||
LPINT* = ptr int32
|
||||
|
||||
@@ -47,8 +47,10 @@ type
|
||||
SqlHDBC* = SqlHandle
|
||||
SqlHStmt* = SqlHandle
|
||||
SqlHDesc* = SqlHandle
|
||||
TSqlInteger* = int
|
||||
SqlUInteger* = int
|
||||
TSqlInteger* = int32
|
||||
SqlUInteger* = int32
|
||||
TSqlLen* = int
|
||||
TSqlULen* = uint
|
||||
SqlPointer* = pointer
|
||||
TSqlReal* = cfloat
|
||||
TSqlDouble* = cdouble
|
||||
@@ -668,7 +670,7 @@ proc SQLAllocHandle*(HandleType: TSqlSmallInt, InputHandle: SqlHandle,
|
||||
OutputHandlePtr: var SqlHandle): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLSetEnvAttr*(EnvironmentHandle: SqlHEnv, Attribute: TSqlInteger,
|
||||
Value: TSqlInteger, StringLength: TSqlInteger): TSqlSmallInt{.
|
||||
Value: SqlPointer, StringLength: TSqlInteger): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLGetEnvAttr*(EnvironmentHandle: SqlHEnv, Attribute: TSqlInteger,
|
||||
Value: SqlPointer, BufferLength: TSqlInteger,
|
||||
@@ -718,14 +720,14 @@ proc SQLNumResultCols*(StatementHandle: SqlHStmt, ColumnCount: var TSqlSmallInt)
|
||||
proc SQLDescribeCol*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
|
||||
ColumnName: PSQLCHAR, BufferLength: TSqlSmallInt,
|
||||
NameLength: var TSqlSmallInt, DataType: var TSqlSmallInt,
|
||||
ColumnSize: var SqlUInteger,
|
||||
ColumnSize: var TSQLULEN,
|
||||
DecimalDigits: var TSqlSmallInt, Nullable: var TSqlSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLFetchScroll*(StatementHandle: SqlHStmt, FetchOrientation: TSqlSmallInt,
|
||||
FetchOffset: TSqlInteger): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLExtendedFetch*(hstmt: SqlHStmt, fFetchType: SqlUSmallInt,
|
||||
irow: TSqlInteger, pcrow: PSQLUINTEGER,
|
||||
irow: TSqlInteger, pcrow: var TSQLULEN,
|
||||
rgfRowStatus: PSQLUSMALLINT): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLGetData*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
|
||||
@@ -743,13 +745,13 @@ proc SQLGetInfo*(ConnectionHandle: SqlHDBC, InfoType: SqlUSmallInt,
|
||||
InfoValue: SqlPointer, BufferLength: TSqlSmallInt,
|
||||
StringLength: PSQLSMALLINT): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLBulkOperations*(StatementHandle: SqlHStmt, Operation: TSqlSmallInt): TSqlSmallInt{.
|
||||
proc SQLBulkOperations*(StatementHandle: SqlHStmt, Operation: SqlUSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLPutData*(StatementHandle: SqlHStmt, Data: SqlPointer,
|
||||
StrLen_or_Ind: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
StrLen_or_Ind: TSQLLEN): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
proc SQLBindCol*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
|
||||
TargetType: TSqlSmallInt, TargetValue: SqlPointer,
|
||||
BufferLength: TSqlInteger, StrLen_or_Ind: PSQLINTEGER): TSqlSmallInt{.
|
||||
BufferLength: TSqlLEN, StrLen_or_Ind: PSQLINTEGER): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLSetPos*(hstmt: SqlHStmt, irow: SqlUSmallInt, fOption: SqlUSmallInt,
|
||||
fLock: SqlUSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
|
||||
@@ -772,13 +774,13 @@ proc SQLGetCursorName*(StatementHandle: SqlHStmt, CursorName: PSQLCHAR,
|
||||
proc SQLSetCursorName*(StatementHandle: SqlHStmt, CursorName: PSQLCHAR,
|
||||
NameLength: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
|
||||
importc.}
|
||||
proc SQLRowCount*(StatementHandle: SqlHStmt, RowCount: var TSqlInteger): TSqlSmallInt{.
|
||||
proc SQLRowCount*(StatementHandle: SqlHStmt, RowCount: var TSQLLEN): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLBindParameter*(hstmt: SqlHStmt, ipar: SqlUSmallInt,
|
||||
fParamType: TSqlSmallInt, fCType: TSqlSmallInt,
|
||||
fSqlType: TSqlSmallInt, cbColDef: SqlUInteger,
|
||||
fSqlType: TSqlSmallInt, cbColDef: TSQLULEN,
|
||||
ibScale: TSqlSmallInt, rgbValue: SqlPointer,
|
||||
cbValueMax: TSqlInteger, pcbValue: PSQLINTEGER): TSqlSmallInt{.
|
||||
cbValueMax: TSQLLEN, pcbValue: var TSQLLEN): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLFreeStmt*(StatementHandle: SqlHStmt, Option: SqlUSmallInt): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
@@ -786,7 +788,7 @@ proc SQLColAttribute*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
|
||||
FieldIdentifier: SqlUSmallInt,
|
||||
CharacterAttribute: PSQLCHAR, BufferLength: TSqlSmallInt,
|
||||
StringLength: PSQLSMALLINT,
|
||||
NumericAttribute: SqlPointer): TSqlSmallInt{.
|
||||
NumericAttribute: TSQLLEN): TSqlSmallInt{.
|
||||
dynlib: odbclib, importc.}
|
||||
proc SQLEndTran*(HandleType: TSqlSmallInt, Handle: SqlHandle,
|
||||
CompletionType: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
|
||||
|
||||
@@ -240,7 +240,7 @@ proc TLSv1_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
|
||||
# and support SSLv3, TLSv1, TLSv1.1 and TLSv1.2
|
||||
# SSLv23_method(), SSLv23_server_method(), SSLv23_client_method() are removed in 1.1.0
|
||||
|
||||
when compileOption("dynlibOverride", "ssl"):
|
||||
when compileOption("dynlibOverride", "ssl") or defined(noOpenSSLHacks):
|
||||
# Static linking
|
||||
|
||||
when defined(openssl10):
|
||||
@@ -281,40 +281,59 @@ else:
|
||||
proc thisModule(): LibHandle {.inline.} =
|
||||
var thisMod {.global.}: LibHandle
|
||||
if thisMod.isNil: thisMod = loadLib()
|
||||
|
||||
result = thisMod
|
||||
|
||||
proc sslModule(): LibHandle {.inline.} =
|
||||
var sslMod {.global.}: LibHandle
|
||||
if sslMod.isNil: sslMod = loadLibPattern(DLLSSLName)
|
||||
|
||||
result = sslMod
|
||||
|
||||
proc sslSym(name: string): pointer =
|
||||
var dl = thisModule()
|
||||
if not dl.isNil:
|
||||
result = symAddr(dl, name)
|
||||
proc sslSymNullable(name: string, alternativeName = ""): pointer =
|
||||
# Load from DLL.
|
||||
var sslDynlib = sslModule()
|
||||
if not sslDynlib.isNil:
|
||||
result = symAddr(sslDynlib, name)
|
||||
if result.isNil and alternativeName.len > 0:
|
||||
result = symAddr(sslDynlib, alternativeName)
|
||||
|
||||
# Attempt to load from current exe.
|
||||
if result.isNil:
|
||||
dl = sslModule()
|
||||
if not dl.isNil:
|
||||
result = symAddr(dl, name)
|
||||
let thisDynlib = thisModule()
|
||||
if thisDynlib.isNil: return nil
|
||||
result = symAddr(thisDynlib, name)
|
||||
if result.isNil and alternativeName.len > 0:
|
||||
result = symAddr(sslDynlib, alternativeName)
|
||||
|
||||
proc sslSymThrows(name: string, alternativeName = ""): pointer =
|
||||
result = sslSymNullable(name, alternativeName)
|
||||
if result.isNil: raiseInvalidLibrary(name)
|
||||
|
||||
proc loadPSSLMethod(method1, method2: string): PSSL_METHOD =
|
||||
## Load <method1> from OpenSSL if available, otherwise <method2>
|
||||
let m1 = cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](sslSym(method1))
|
||||
if not m1.isNil:
|
||||
return m1()
|
||||
cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](sslSym(method2))()
|
||||
##
|
||||
let methodSym = sslSymNullable(method1, method2)
|
||||
if methodSym.isNil:
|
||||
raise newException(LibraryError, "Could not load " & method1 & " nor " & method2)
|
||||
|
||||
let method2Proc = cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](methodSym)
|
||||
return method2Proc()
|
||||
|
||||
proc SSL_library_init*(): cint {.discardable.} =
|
||||
## Initialize SSL using OPENSSL_init_ssl for OpenSSL >= 1.1.0 otherwise
|
||||
## SSL_library_init
|
||||
let theProc = cast[proc(opts: uint64, settings: uint8): cint {.cdecl.}](sslSym("OPENSSL_init_ssl"))
|
||||
if not theProc.isNil:
|
||||
return theProc(0, 0)
|
||||
let olderProc = cast[proc(): cint {.cdecl.}](sslSym("SSL_library_init"))
|
||||
let newInitSym = sslSymNullable("OPENSSL_init_ssl")
|
||||
if not newInitSym.isNil:
|
||||
let newInitProc =
|
||||
cast[proc(opts: uint64, settings: uint8): cint {.cdecl.}](newInitSym)
|
||||
return newInitProc(0, 0)
|
||||
let olderProc = cast[proc(): cint {.cdecl.}](sslSymThrows("SSL_library_init"))
|
||||
if not olderProc.isNil: result = olderProc()
|
||||
|
||||
proc SSL_load_error_strings*() =
|
||||
let theProc = cast[proc() {.cdecl.}](sslSym("SSL_load_error_strings"))
|
||||
# TODO: Are we ignoring this on purpose? SSL GitHub CI fails otherwise.
|
||||
let theProc = cast[proc() {.cdecl.}](sslSymNullable("SSL_load_error_strings"))
|
||||
if not theProc.isNil: theProc()
|
||||
|
||||
proc SSLv23_client_method*(): PSSL_METHOD =
|
||||
@@ -339,12 +358,13 @@ else:
|
||||
loadPSSLMethod("TLS_server_method", "SSLv23_server_method")
|
||||
|
||||
proc OpenSSL_add_all_algorithms*() =
|
||||
let theProc = cast[proc() {.cdecl.}](sslSym("OPENSSL_add_all_algorithms_conf"))
|
||||
# TODO: Are we ignoring this on purpose? SSL GitHub CI fails otherwise.
|
||||
let theProc = cast[proc() {.cdecl.}](sslSymNullable("OPENSSL_add_all_algorithms_conf"))
|
||||
if not theProc.isNil: theProc()
|
||||
|
||||
proc getOpenSSLVersion*(): culong =
|
||||
## Return OpenSSL version as unsigned long or 0 if not available
|
||||
let theProc = cast[proc(): culong {.cdecl.}](sslSym("OpenSSL_version_num"))
|
||||
let theProc = cast[proc(): culong {.cdecl.}](sslSymNullable("OpenSSL_version_num"))
|
||||
result =
|
||||
if theProc.isNil: 0.culong
|
||||
else: theProc()
|
||||
|
||||
8
nimsuggest/tests/tchk_compiles.nim
Normal file
8
nimsuggest/tests/tchk_compiles.nim
Normal file
@@ -0,0 +1,8 @@
|
||||
discard compiles(2 + "hello")
|
||||
|
||||
#[!]#
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>chk $1
|
||||
chk;;skUnknown;;;;Hint;;???;;0;;-1;;"tchk_compiles [Processing]";;0
|
||||
"""
|
||||
13
nimsuggest/tests/ttempl_inst.nim
Normal file
13
nimsuggest/tests/ttempl_inst.nim
Normal file
@@ -0,0 +1,13 @@
|
||||
template foo() =
|
||||
{.warning: "foo".}
|
||||
|
||||
foo()
|
||||
|
||||
#[!]#
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>chk $1
|
||||
chk;;skUnknown;;;;Hint;;???;;0;;-1;;"ttempl_inst [Processing]";;0
|
||||
chk;;skUnknown;;;;Hint;;$file;;4;;3;;"template/generic instantiation from here";;0
|
||||
chk;;skUnknown;;;;Warning;;$file;;2;;11;;"foo [User]";;0
|
||||
"""
|
||||
@@ -11,19 +11,18 @@ pkg "ast_pattern_matching", "nim c -r --oldgensym:on tests/test1.nim"
|
||||
pkg "asyncmysql", "", true
|
||||
pkg "bigints"
|
||||
pkg "binaryheap", "nim c -r binaryheap.nim"
|
||||
pkg "blscurve", "", true
|
||||
# pkg "blscurve", "", true
|
||||
pkg "bncurve", "", true
|
||||
pkg "c2nim", "nim c testsuite/tester.nim"
|
||||
pkg "cascade"
|
||||
pkg "chroma"
|
||||
pkg "chronicles", "nim c -o:chr -r chronicles.nim", true
|
||||
pkg "chronos", "", true
|
||||
# pkg "chroma"
|
||||
# pkg "chronicles", "nim c -o:chr -r chronicles.nim", true
|
||||
pkg "cligen", "nim c -o:cligenn -r cligen.nim"
|
||||
pkg "coco", "", true
|
||||
pkg "combparser"
|
||||
pkg "compactdict"
|
||||
pkg "comprehension", "", false, "https://github.com/alehander42/comprehension"
|
||||
pkg "criterion"
|
||||
# pkg "criterion"
|
||||
pkg "dashing", "nim c tests/functional.nim"
|
||||
pkg "docopt"
|
||||
pkg "easygl", "nim c -o:egl -r src/easygl.nim", true, "https://github.com/jackmott/easygl"
|
||||
@@ -33,41 +32,40 @@ pkg "gara"
|
||||
pkg "glob"
|
||||
pkg "gnuplot"
|
||||
# pkg "godot", "nim c -r godot/godot.nim" # not yet compatible with Nim 0.19
|
||||
pkg "hts", "nim c -o:htss src/hts.nim"
|
||||
# pkg "hts", "nim c -o:htss src/hts.nim"
|
||||
pkg "illwill", "nimble examples"
|
||||
pkg "inim"
|
||||
# pkg "inim", "", true
|
||||
pkg "itertools", "nim doc src/itertools.nim"
|
||||
pkg "iterutils"
|
||||
pkg "jstin"
|
||||
pkg "karax", "nim c -r tests/tester.nim"
|
||||
pkg "loopfusion"
|
||||
pkg "msgpack4nim"
|
||||
pkg "nake", "nim c nakefile.nim"
|
||||
# pkg "nake", "nim c nakefile.nim"
|
||||
pkg "neo", "nim c -d:blas=openblas tests/all.nim", true
|
||||
# pkg "nico", "", true
|
||||
pkg "nicy", "nim c src/nicy.nim"
|
||||
# pkg "nicy", "nim c src/nicy.nim"
|
||||
pkg "nigui", "nim c -o:niguii -r src/nigui.nim"
|
||||
pkg "nimcrypto", "nim c -r tests/testall.nim"
|
||||
pkg "NimData", "nim c -o:nimdataa src/nimdata.nim", true
|
||||
# pkg "NimData", "nim c -o:nimdataa src/nimdata.nim", true
|
||||
pkg "nimes", "nim c src/nimes.nim", true
|
||||
pkg "nimfp", "nim c -o:nfp -r src/fp.nim", true
|
||||
pkg "nimgame2", "nim c nimgame2/nimgame.nim", true
|
||||
pkg "nimgen", "nim c -o:nimgenn -r src/nimgen/runcfg.nim", true
|
||||
# pkg "nimgame2", "nim c nimgame2/nimgame.nim", true
|
||||
# pkg "nimgen", "nim c -o:nimgenn -r src/nimgen/runcfg.nim", true
|
||||
# pkg "nimlsp", "", true
|
||||
pkg "nimly", "nim c -r tests/test_nimly", true
|
||||
# pkg "nimly", "", true
|
||||
# pkg "nimongo", "nimble test_ci", true
|
||||
pkg "nimpy", "nim c -r tests/nimfrompy.nim"
|
||||
pkg "nimquery"
|
||||
# pkg "nimquery"
|
||||
pkg "nimsl", "", true
|
||||
pkg "nimsvg"
|
||||
# pkg "nimterop", "", true
|
||||
pkg "nimx", "nim c --threads:on test/main.nim", true
|
||||
pkg "norm", "nim c -r tests/tsqlite.nim", true
|
||||
# pkg "nimx", "nim c --threads:on test/main.nim", true
|
||||
pkg "npeg"
|
||||
pkg "ormin", "nim c -o:orminn ormin.nim", true
|
||||
pkg "parsetoml"
|
||||
pkg "patty"
|
||||
pkg "plotly", "nim c --oldgensym:on examples/all.nim", true
|
||||
# pkg "plotly", "nim c --oldgensym:on examples/all.nim", true
|
||||
pkg "pnm"
|
||||
pkg "polypbren"
|
||||
pkg "protobuf", "nim c -o:protobuff -r src/protobuf.nim", true
|
||||
@@ -79,10 +77,10 @@ pkg "rosencrantz", "nim c -o:rsncntz -r rosencrantz.nim"
|
||||
pkg "sdl1", "nim c -r src/sdl.nim"
|
||||
pkg "sdl2_nim", "nim c -r sdl2/sdl.nim"
|
||||
pkg "snip", "", false, "https://github.com/genotrance/snip"
|
||||
pkg "stint", "nim c -o:stintt -r stint.nim"
|
||||
# pkg "stint", "nim c -o:stintt -r stint.nim"
|
||||
pkg "strunicode", "nim c -r src/strunicode.nim", true
|
||||
pkg "telebot", "nim c -o:tbot --oldgensym:on -r telebot.nim", true
|
||||
pkg "tempdir"
|
||||
pkg "telebot", "nim c -o:tbot -r src/telebot.nim", true
|
||||
# pkg "tempdir"
|
||||
pkg "tensordsl", "nim c -r tests/tests.nim", false, "https://krux02@bitbucket.org/krux02/tensordslnim.git"
|
||||
pkg "tiny_sqlite"
|
||||
pkg "unicodedb"
|
||||
@@ -90,6 +88,6 @@ pkg "unicodeplus", "", true
|
||||
pkg "unpack"
|
||||
# pkg "winim", "", true
|
||||
pkg "with"
|
||||
pkg "ws"
|
||||
# pkg "ws"
|
||||
pkg "yaml"
|
||||
pkg "zero_functional", "nim c -r test.nim"
|
||||
|
||||
@@ -590,3 +590,14 @@ block t12466:
|
||||
a[0'u16 + i] = i
|
||||
for i in 0'u16 ..< 8'u16:
|
||||
a[0'u16 + i] = i
|
||||
|
||||
block t18643:
|
||||
# https://github.com/nim-lang/Nim/issues/18643
|
||||
let a: array[0, int] = []
|
||||
var caught = false
|
||||
let b = 9999999
|
||||
try:
|
||||
echo a[b]
|
||||
except IndexError:
|
||||
caught = true
|
||||
doAssert caught, "IndexDefect not caught!"
|
||||
|
||||
27
tests/async/t13889.nim
Normal file
27
tests/async/t13889.nim
Normal file
@@ -0,0 +1,27 @@
|
||||
discard """
|
||||
output: '''
|
||||
believer Foo is saved:true
|
||||
believer Bar is saved:true
|
||||
believer Baz is saved:true
|
||||
'''
|
||||
"""
|
||||
|
||||
import asyncdispatch
|
||||
|
||||
var
|
||||
promise = newFuture[bool]()
|
||||
|
||||
proc believers(name: string) {.async.} =
|
||||
let v = await promise
|
||||
echo "believer " & name & " is saved:" & $v
|
||||
|
||||
asyncCheck believers("Foo")
|
||||
asyncCheck believers("Bar")
|
||||
asyncCheck believers("Baz")
|
||||
|
||||
proc savior() {.async.} =
|
||||
await sleepAsync(50)
|
||||
complete(promise, true)
|
||||
await sleepAsync(50) # give enough time to see who was saved
|
||||
|
||||
waitFor(savior())
|
||||
@@ -10,6 +10,6 @@ proc main() =
|
||||
inc(counter)
|
||||
poll(10)
|
||||
|
||||
doAssert counter <= 4
|
||||
doAssert counter <= 5
|
||||
|
||||
for i in 0 .. 10: main()
|
||||
|
||||
@@ -13,8 +13,8 @@ else:
|
||||
# This reproduces a case where a socket remains stuck waiting for writes
|
||||
# even when the socket is closed.
|
||||
const
|
||||
port = Port(50726)
|
||||
timeout = 5000
|
||||
timeout = 8000
|
||||
var port = Port(0)
|
||||
|
||||
var sent = 0
|
||||
|
||||
@@ -86,6 +86,8 @@ proc server() {.async.} =
|
||||
s.setSockOpt(OptReuseAddr, true)
|
||||
s.bindAddr(port)
|
||||
s.listen()
|
||||
let (addr2, port2) = s.getLocalAddr
|
||||
port = port2
|
||||
|
||||
# We're now ready to accept connections, so start the client
|
||||
asyncCheck startClient()
|
||||
|
||||
@@ -165,9 +165,14 @@ block tableconstr:
|
||||
block ttables2:
|
||||
proc TestHashIntInt() =
|
||||
var tab = initTable[int,int]()
|
||||
for i in 1..1_000_000:
|
||||
when defined(nimTestsTablesDisableSlow):
|
||||
# helps every single time when this test needs to be debugged
|
||||
let n = 1_000
|
||||
else:
|
||||
let n = 1_000_000
|
||||
for i in 1..n:
|
||||
tab[i] = i
|
||||
for i in 1..1_000_000:
|
||||
for i in 1..n:
|
||||
var x = tab[i]
|
||||
if x != i : echo "not found ", i
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ a: @[4, 2, 3]
|
||||
0
|
||||
30
|
||||
true
|
||||
41 41'''
|
||||
40 40'''
|
||||
"""
|
||||
|
||||
import allocators
|
||||
|
||||
@@ -2,7 +2,7 @@ discard """
|
||||
cmd: '''nim c --newruntime $file'''
|
||||
output: '''button
|
||||
clicked!
|
||||
6 6 alloc/dealloc pairs: 0'''
|
||||
4 4 alloc/dealloc pairs: 0'''
|
||||
"""
|
||||
|
||||
import core / allocators
|
||||
|
||||
47
tests/errmsgs/tsigmatch2.nim
Normal file
47
tests/errmsgs/tsigmatch2.nim
Normal file
@@ -0,0 +1,47 @@
|
||||
discard """
|
||||
cmd: "nim check --showAllMismatches:on --hints:off $file"
|
||||
nimout: '''
|
||||
tsigmatch2.nim(40, 14) Error: type mismatch: got <float64>
|
||||
but expected one of:
|
||||
proc foo(i: Foo): string
|
||||
first type mismatch at position: 1
|
||||
required type for i: Foo
|
||||
but expression '1.2' is of type: float64
|
||||
proc foo(args: varargs[string, myproc]): string
|
||||
first type mismatch at position: 1
|
||||
required type for args: varargs[string]
|
||||
but expression '1.2' is of type: float64
|
||||
|
||||
expression: foo(1.2)
|
||||
tsigmatch2.nim(46, 7) Error: type mismatch: got <int literal(1)>
|
||||
but expected one of:
|
||||
proc foo(args: varargs[string, myproc])
|
||||
first type mismatch at position: 1
|
||||
required type for args: varargs[string]
|
||||
but expression '1' is of type: int literal(1)
|
||||
|
||||
expression: foo 1
|
||||
'''
|
||||
errormsg: "type mismatch"
|
||||
"""
|
||||
|
||||
|
||||
|
||||
# line 30
|
||||
|
||||
block: # issue #13182
|
||||
proc myproc(a: int): string = $("myproc", a)
|
||||
proc foo(args: varargs[string, myproc]): string = $args
|
||||
type Foo = object
|
||||
proc foo(i: Foo): string = "in foo(i)"
|
||||
static: doAssert foo(Foo()) == "in foo(i)"
|
||||
static: doAssert foo(1) == """["(\"myproc\", 1)"]"""
|
||||
doAssert not compiles(foo(1.2))
|
||||
discard foo(1.2)
|
||||
|
||||
block:
|
||||
proc myproc[T](x: T): string =
|
||||
let temp = 12.isNil
|
||||
proc foo(args: varargs[string, myproc]) = discard
|
||||
foo 1
|
||||
static: echo "done"
|
||||
@@ -26,3 +26,14 @@ var output = represent(s)
|
||||
|
||||
for item in output():
|
||||
echo item
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Issue #12747
|
||||
|
||||
type
|
||||
ABC = ref object
|
||||
arr: array[0x40000, pointer]
|
||||
let a = ABC()
|
||||
for a in a.arr:
|
||||
assert a == nil
|
||||
13
tests/misc/tdangerisrelease.nim
Normal file
13
tests/misc/tdangerisrelease.nim
Normal file
@@ -0,0 +1,13 @@
|
||||
discard """
|
||||
cmd: "nim c -d:danger -r $file"
|
||||
output: '''
|
||||
a
|
||||
b
|
||||
c
|
||||
'''
|
||||
"""
|
||||
|
||||
echo "a"
|
||||
when defined(release):
|
||||
echo "b"
|
||||
echo "c"
|
||||
@@ -336,6 +336,21 @@ testinstance:
|
||||
a: int32
|
||||
b: T
|
||||
|
||||
Kind = enum
|
||||
K1, K2
|
||||
|
||||
AnotherEnum = enum
|
||||
X1, X2, X3
|
||||
|
||||
MyObject = object
|
||||
s: string
|
||||
case k: Kind
|
||||
of K1: nil
|
||||
of K2:
|
||||
x: float
|
||||
y: int32
|
||||
z: AnotherEnum
|
||||
|
||||
const trivialSize = sizeof(TrivialType) # needs to be able to evaluate at compile time
|
||||
|
||||
proc main(): void =
|
||||
@@ -350,6 +365,7 @@ testinstance:
|
||||
var ro : RootObj
|
||||
var go : GenericObject[int64]
|
||||
var po : PaddingOfSetEnum33
|
||||
var issue15516: MyObject
|
||||
|
||||
var
|
||||
e1: Enum1
|
||||
@@ -368,8 +384,7 @@ testinstance:
|
||||
else:
|
||||
doAssert sizeof(SimpleAlignment) > 10
|
||||
|
||||
testSizeAlignOf(t,a,b,c,d,e,f,g,ro,go,po, e1, e2, e4, e8, eoa, eob)
|
||||
|
||||
testSizeAlignOf(t,a,b,c,d,e,f,g,ro,go,po, e1, e2, e4, e8, eoa, eob, issue15516)
|
||||
|
||||
type
|
||||
WithBitsize {.objectconfig.} = object
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
discard """
|
||||
output: '''uint'''
|
||||
"""
|
||||
|
||||
# Tests unsigned literals and implicit conversion between uints and ints
|
||||
# Passes if it compiles
|
||||
@@ -43,3 +46,17 @@ block t4176:
|
||||
var yyy: uint8 = 0
|
||||
yyy = yyy - 127
|
||||
doAssert type(yyy) is uint8
|
||||
|
||||
# bug #13661
|
||||
|
||||
proc fun(): uint = cast[uint](-1)
|
||||
const x0 = fun()
|
||||
|
||||
echo typeof(x0)
|
||||
|
||||
discard $x0
|
||||
|
||||
# bug #13671
|
||||
|
||||
const x1 = cast[uint](-1)
|
||||
discard $(x1,)
|
||||
|
||||
@@ -82,3 +82,14 @@ proc newArrayAnimationSampler*[T](): ArrayAnimationSampler[T] =
|
||||
|
||||
discard newArrayAnimationSampler[Foo6]()
|
||||
discard newArrayAnimationSampler[AnotherFoo]()
|
||||
|
||||
type
|
||||
DefaultIsNone* = pointer | ptr | ref | proc {.nimcall.} | cstring | cstringArray
|
||||
OptionKind* {.pure.} = enum None, Some
|
||||
OptionA* [T] = object of RootObj
|
||||
when T is DefaultIsNone:
|
||||
value: T
|
||||
else:
|
||||
value: T
|
||||
kind: OptionKind
|
||||
SomeA* [T] = object of OptionA[T]
|
||||
|
||||
7
tests/proc/tlambdapragma.nim
Normal file
7
tests/proc/tlambdapragma.nim
Normal file
@@ -0,0 +1,7 @@
|
||||
discard """
|
||||
errormsg: "invalid pragma: exportc"
|
||||
"""
|
||||
|
||||
let _ = proc () {.exportc.} =
|
||||
# this would previously cause a codegen error
|
||||
discard
|
||||
@@ -7,9 +7,14 @@ set is empty
|
||||
|
||||
import sets, hashes
|
||||
|
||||
from sequtils import toSeq
|
||||
from algorithm import sorted
|
||||
|
||||
proc sortedPairs[T](t: T): auto = toSeq(t.pairs).sorted
|
||||
template sortedItems(t: untyped): untyped = sorted(toSeq(t))
|
||||
|
||||
block tsetpop:
|
||||
var a = initSet[int]()
|
||||
var a = initHashSet[int]()
|
||||
for i in 1..1000:
|
||||
a.incl(i)
|
||||
doAssert len(a) == 1000
|
||||
@@ -50,7 +55,7 @@ block tsets2:
|
||||
"80"]
|
||||
|
||||
block tableTest1:
|
||||
var t = initSet[tuple[x, y: int]]()
|
||||
var t = initHashSet[tuple[x, y: int]]()
|
||||
t.incl((0,0))
|
||||
t.incl((1,0))
|
||||
assert(not t.containsOrIncl((0,1)))
|
||||
@@ -63,7 +68,7 @@ block tsets2:
|
||||
# "{(x: 0, y: 0), (x: 0, y: 1), (x: 1, y: 0), (x: 1, y: 1)}")
|
||||
|
||||
block setTest2:
|
||||
var t = initSet[string]()
|
||||
var t = initHashSet[string]()
|
||||
t.incl("test")
|
||||
t.incl("111")
|
||||
t.incl("123")
|
||||
@@ -102,9 +107,9 @@ block tsets2:
|
||||
|
||||
block tsets3:
|
||||
let
|
||||
s1: HashSet[int] = toSet([1, 2, 4, 8, 16])
|
||||
s2: HashSet[int] = toSet([1, 2, 3, 5, 8])
|
||||
s3: HashSet[int] = toSet([3, 5, 7])
|
||||
s1: HashSet[int] = toHashSet([1, 2, 4, 8, 16])
|
||||
s2: HashSet[int] = toHashSet([1, 2, 3, 5, 8])
|
||||
s3: HashSet[int] = toHashSet([3, 5, 7])
|
||||
|
||||
block union:
|
||||
let
|
||||
@@ -172,7 +177,7 @@ block tsets3:
|
||||
assert i in s1_s3 xor i in s1
|
||||
assert i in s2_s3 xor i in s2
|
||||
|
||||
assert((s3 -+- s3) == initSet[int]())
|
||||
assert((s3 -+- s3) == initHashSet[int]())
|
||||
assert((s3 -+- s1) == s1_s3)
|
||||
|
||||
block difference:
|
||||
@@ -191,10 +196,61 @@ block tsets3:
|
||||
for i in s2:
|
||||
assert i in s2_s3 xor i in s3
|
||||
|
||||
assert((s2 - s2) == initSet[int]())
|
||||
assert((s2 - s2) == initHashSet[int]())
|
||||
|
||||
block disjoint:
|
||||
assert(not disjoint(s1, s2))
|
||||
assert disjoint(s1, s3)
|
||||
assert(not disjoint(s2, s3))
|
||||
assert(not disjoint(s2, s2))
|
||||
|
||||
block: # https://github.com/nim-lang/Nim/issues/13496
|
||||
template testDel(body) =
|
||||
block:
|
||||
body
|
||||
t.incl(15)
|
||||
t.incl(19)
|
||||
t.incl(17)
|
||||
t.incl(150)
|
||||
t.excl(150)
|
||||
doAssert t.len == 3
|
||||
doAssert sortedItems(t) == @[15, 17, 19]
|
||||
var s = newSeq[int]()
|
||||
for v in t: s.add(v)
|
||||
assert s.len == 3
|
||||
doAssert sortedItems(s) == @[15, 17, 19]
|
||||
when t is OrderedSet:
|
||||
doAssert sortedPairs(t) == @[(a: 0, b: 15), (a: 1, b: 19), (a: 2, b: 17)]
|
||||
doAssert toSeq(t) == @[15, 19, 17]
|
||||
|
||||
testDel(): (var t: HashSet[int])
|
||||
testDel(): (var t: OrderedSet[int])
|
||||
|
||||
block: # test correctness after a number of inserts/deletes
|
||||
template testDel(body) =
|
||||
block:
|
||||
body
|
||||
var expected: seq[int]
|
||||
let n = 100
|
||||
let n2 = n*2
|
||||
for i in 0..<n:
|
||||
t.incl(i)
|
||||
for i in 0..<n:
|
||||
if i mod 3 == 0:
|
||||
t.excl(i)
|
||||
for i in n..<n2:
|
||||
t.incl(i)
|
||||
for i in 0..<n2:
|
||||
if i mod 7 == 0:
|
||||
t.excl(i)
|
||||
|
||||
for i in 0..<n2:
|
||||
if (i>=n or i mod 3 != 0) and i mod 7 != 0:
|
||||
expected.add i
|
||||
|
||||
for i in expected: doAssert i in t
|
||||
doAssert t.len == expected.len
|
||||
doAssert sortedItems(t) == expected
|
||||
|
||||
testDel(): (var t: HashSet[int])
|
||||
testDel(): (var t: OrderedSet[int])
|
||||
|
||||
65
tests/stdlib/tintsets.nim
Normal file
65
tests/stdlib/tintsets.nim
Normal file
@@ -0,0 +1,65 @@
|
||||
import intsets
|
||||
import std/sets
|
||||
|
||||
from sequtils import toSeq
|
||||
from algorithm import sorted
|
||||
|
||||
proc sortedPairs[T](t: T): auto = toSeq(t.pairs).sorted
|
||||
template sortedItems(t: untyped): untyped = sorted(toSeq(t))
|
||||
|
||||
block: # we use HashSet as groundtruth, it's well tested elsewhere
|
||||
template testDel(t, t0) =
|
||||
|
||||
template checkEquals() =
|
||||
doAssert t.len == t0.len
|
||||
for k in t0:
|
||||
doAssert k in t
|
||||
for k in t:
|
||||
doAssert k in t0
|
||||
|
||||
doAssert sortedItems(t) == sortedItems(t0)
|
||||
|
||||
template incl2(i) =
|
||||
t.incl i
|
||||
t0.incl i
|
||||
|
||||
template excl2(i) =
|
||||
t.excl i
|
||||
t0.excl i
|
||||
|
||||
block:
|
||||
var expected: seq[int]
|
||||
let n = 100
|
||||
let n2 = n*2
|
||||
for i in 0..<n:
|
||||
incl2(i)
|
||||
checkEquals()
|
||||
for i in 0..<n:
|
||||
if i mod 3 == 0:
|
||||
if i < n div 2:
|
||||
excl2(i)
|
||||
else:
|
||||
t0.excl i
|
||||
doAssert i in t
|
||||
doAssert not t.missingOrExcl(i)
|
||||
|
||||
checkEquals()
|
||||
for i in n..<n2:
|
||||
incl2(i)
|
||||
checkEquals()
|
||||
for i in 0..<n2:
|
||||
if i mod 7 == 0:
|
||||
excl2(i)
|
||||
checkEquals()
|
||||
|
||||
# notin check
|
||||
for i in 0..<t.len:
|
||||
if i mod 7 == 0:
|
||||
doAssert i notin t0
|
||||
doAssert i notin t
|
||||
# issue #13505
|
||||
doAssert t.missingOrExcl(i)
|
||||
|
||||
var t: IntSet
|
||||
var t0: HashSet[int]
|
||||
testDel(t, t0)
|
||||
@@ -338,6 +338,10 @@ block ospaths:
|
||||
doAssert joinPath("", "lib") == "lib"
|
||||
doAssert joinPath("", "/lib") == unixToNativePath"/lib"
|
||||
doAssert joinPath("usr/", "/lib") == unixToNativePath"usr/lib"
|
||||
doAssert joinPath("", "") == unixToNativePath""
|
||||
doAssert joinPath("/" / "") == unixToNativePath"/"
|
||||
doAssert joinPath("/", "/a/b/c") == unixToNativePath"/a/b/c"
|
||||
doAssert joinPath("foo/","") == unixToNativePath"foo/"
|
||||
|
||||
block getTempDir:
|
||||
block TMPDIR:
|
||||
|
||||
43
tests/stdlib/tparseutils.nim
Normal file
43
tests/stdlib/tparseutils.nim
Normal file
@@ -0,0 +1,43 @@
|
||||
import parseutils, sequtils, sugar
|
||||
|
||||
|
||||
let input = "$test{} $this is ${an{ example}} "
|
||||
let expected = @[(ikVar, "test"), (ikStr, "{} "), (ikVar, "this"),
|
||||
(ikStr, " is "), (ikExpr, "an{ example}"), (ikStr, " ")]
|
||||
doAssert toSeq(interpolatedFragments(input)) == expected
|
||||
|
||||
var value = 0
|
||||
discard parseHex("0x38", value)
|
||||
doAssert value == 56
|
||||
|
||||
value = -1
|
||||
doAssert(parseSaturatedNatural("848", value) == 3)
|
||||
doAssert value == 848
|
||||
|
||||
value = -1
|
||||
discard parseSaturatedNatural("84899999999999999999324234243143142342135435342532453", value)
|
||||
doAssert value == high(int)
|
||||
|
||||
value = -1
|
||||
discard parseSaturatedNatural("9223372036854775808", value)
|
||||
doAssert value == high(int)
|
||||
|
||||
value = -1
|
||||
discard parseSaturatedNatural("9223372036854775807", value)
|
||||
doAssert value == high(int)
|
||||
|
||||
value = -1
|
||||
discard parseSaturatedNatural("18446744073709551616", value)
|
||||
doAssert value == high(int)
|
||||
|
||||
value = -1
|
||||
discard parseSaturatedNatural("18446744073709551615", value)
|
||||
doAssert value == high(int)
|
||||
|
||||
value = -1
|
||||
doAssert(parseSaturatedNatural("1_000_000", value) == 9)
|
||||
doAssert value == 1_000_000
|
||||
|
||||
var i64Value: int64
|
||||
discard parseBiggestInt("9223372036854775807", i64Value)
|
||||
doAssert i64Value == 9223372036854775807
|
||||
@@ -5,10 +5,84 @@ output: '''
|
||||
|
||||
import sharedtables
|
||||
|
||||
var table: SharedTable[int, int]
|
||||
block:
|
||||
var table: SharedTable[int, int]
|
||||
|
||||
init(table)
|
||||
table[1] = 10
|
||||
assert table.mget(1) == 10
|
||||
assert table.mgetOrPut(3, 7) == 7
|
||||
assert table.mgetOrPut(3, 99) == 7
|
||||
init(table)
|
||||
table[1] = 10
|
||||
assert table.mget(1) == 10
|
||||
assert table.mgetOrPut(3, 7) == 7
|
||||
assert table.mgetOrPut(3, 99) == 7
|
||||
deinitSharedTable(table)
|
||||
|
||||
import sequtils, algorithm
|
||||
proc sortedPairs[T](t: T): auto = toSeq(t.pairs).sorted
|
||||
template sortedItems(t: untyped): untyped = sorted(toSeq(t))
|
||||
|
||||
import tables # refs issue #13504
|
||||
|
||||
block: # we use Table as groundtruth, it's well tested elsewhere
|
||||
template testDel(t, t0) =
|
||||
template put2(i) =
|
||||
t[i] = i
|
||||
t0[i] = i
|
||||
|
||||
template add2(i, val) =
|
||||
t.add(i, val)
|
||||
t0.add(i, val)
|
||||
|
||||
template del2(i) =
|
||||
t.del(i)
|
||||
t0.del(i)
|
||||
|
||||
template checkEquals() =
|
||||
doAssert t.len == t0.len
|
||||
for k,v in t0:
|
||||
doAssert t.mgetOrPut(k, -1) == v # sanity check
|
||||
doAssert t.mget(k) == v
|
||||
|
||||
let n = 100
|
||||
let n2 = n*2
|
||||
let n3 = n*3
|
||||
let n4 = n*4
|
||||
let n5 = n*5
|
||||
|
||||
for i in 0..<n:
|
||||
put2(i)
|
||||
for i in 0..<n:
|
||||
if i mod 3 == 0:
|
||||
del2(i)
|
||||
for i in n..<n2:
|
||||
put2(i)
|
||||
for i in 0..<n2:
|
||||
if i mod 7 == 0:
|
||||
del2(i)
|
||||
|
||||
checkEquals()
|
||||
|
||||
for i in n2..<n3:
|
||||
t0[i] = -2
|
||||
doAssert t.mgetOrPut(i, -2) == -2
|
||||
doAssert t.mget(i) == -2
|
||||
|
||||
for i in 0..<n4:
|
||||
let ok = i in t0
|
||||
if not ok: t0[i] = -i
|
||||
doAssert t.hasKeyOrPut(i, -i) == ok
|
||||
|
||||
checkEquals()
|
||||
|
||||
for i in n4..<n5:
|
||||
add2(i, i*10)
|
||||
add2(i, i*11)
|
||||
add2(i, i*12)
|
||||
del2(i)
|
||||
del2(i)
|
||||
|
||||
checkEquals()
|
||||
|
||||
var t: SharedTable[int, int]
|
||||
init(t) # ideally should be auto-init
|
||||
var t0: Table[int, int]
|
||||
testDel(t, t0)
|
||||
deinitSharedTable(t)
|
||||
|
||||
8
tests/stdlib/tterminal.nim
Normal file
8
tests/stdlib/tterminal.nim
Normal file
@@ -0,0 +1,8 @@
|
||||
discard """
|
||||
action: compile
|
||||
"""
|
||||
|
||||
import terminal, colors
|
||||
|
||||
styledEcho fgColor, colRed, "Test"
|
||||
styledEcho bgColor, colBlue, "Test"
|
||||
@@ -1,5 +1,7 @@
|
||||
discard """
|
||||
output: '''
|
||||
output: '''(a: 1)
|
||||
(a: 1)
|
||||
(a: 1, b: 2)
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -75,3 +77,8 @@ block t1986:
|
||||
(var1: test(), var2: 100'u32),
|
||||
(var1: test(), var2: 192'u32)
|
||||
]
|
||||
|
||||
# bug #14911
|
||||
echo (a: 1) # works
|
||||
echo (`a`: 1) # works
|
||||
echo (`a`: 1, `b`: 2) # Error: named expression expected
|
||||
|
||||
@@ -30,3 +30,12 @@ const
|
||||
}.toTable
|
||||
|
||||
#map["test"]()
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# bug
|
||||
const val = 10
|
||||
|
||||
type
|
||||
t = object
|
||||
when val >= 10:
|
||||
a: int
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
discard """
|
||||
targets: "c"
|
||||
nimout: '''13'''
|
||||
output: '''3
|
||||
3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
timeout: "4"
|
||||
timeout: "8"
|
||||
action: "compile"
|
||||
nimout: '''create
|
||||
search
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user