Compare commits

...

61 Commits

Author SHA1 Message Date
Arne Döring
193b3c66bb fix #12426 (#12462)
(cherry picked from commit ec20fd3544)
2019-10-22 07:21:24 +02:00
Andreas Rumpf
0b134412f8 fixes #12310 [backport] (#12470)
(cherry picked from commit 38b3590e40)
2019-10-21 07:32:38 +02:00
ducdetronquito
1526ae8791 Namespace unittest enums to avoid name conflicts (#12468) [backport]
* [backport] Fixes: #12465 - Unittest - Namespace the usage of TestStatus enum to avoid name conflicts.

(cherry picked from commit df4c339cfc)
2019-10-21 07:32:38 +02:00
Andreas Rumpf
b914573d18 fixes #12420 [backport] (#12456)
(cherry picked from commit 832b0a0232)
2019-10-21 07:32:38 +02:00
Juan Carlos
f579d29b68 Fixes #8802 (#12439)
* Fix #8802

* Peer review feedbacks https://github.com/nim-lang/Nim/pull/12439#discussion_r335905397

(cherry picked from commit f5b4d9a2e5)
2019-10-21 07:32:38 +02:00
Juan Carlos
f79f7fed98 Fixes #10824 (#12437)
(cherry picked from commit 4d1f69c7d2)
2019-10-17 22:27:54 +02:00
Juan Carlos
e0c4015bbe Fix #10804 (#12438)
(cherry picked from commit 2cfd58de48)
2019-10-17 22:27:38 +02:00
Miran
7b500cbfad [backport] fix type's case in random.nim (#12445)
(cherry picked from commit a5ab502f08)
2019-10-17 22:25:51 +02:00
Andreas Rumpf
53e4692665 [backport] add back a check that got accidentically removed; fixes #12379 (#12444)
(cherry picked from commit 81125e2029)
2019-10-17 22:25:51 +02:00
Miran
b0e595b3cf [backport] fix #12418, fix random.randomize on JS backend (#12432)
(cherry picked from commit 5f5ac8ce16)
2019-10-17 22:25:51 +02:00
Yuriy Glukhov
4e3c997d40 Fixed yield in nkCheckedFieldExpr (#12429) [backport]
(cherry picked from commit 1aed455e7c)
2019-10-17 22:25:51 +02:00
Alexander Ivanov
f16bb4d85b Fixes semCustomPragma when nkSym (#12414) [backport]
(cherry picked from commit 990aadc43c)
2019-10-12 08:00:44 +02:00
genotrance
8f1dea614e Fixes #12286 - require explicit disabling of boehm interior pointer checking (#12406) [backport]
(cherry picked from commit 9e62876647)
2019-10-12 08:00:44 +02:00
Arne Döring
63d710f5a1 fix #12332 (#12402) [backport]
(cherry picked from commit 0a29c05a1b)
2019-10-12 08:00:44 +02:00
Andreas Rumpf
2ebd47089a fixes a koch regression that made 'koch boot --listcmd' not work anymore [backport] (#12400)
(cherry picked from commit d783c0f7ff)
2019-10-12 08:00:43 +02:00
Araq
535f0b9c9d fixes #12244 [backport]
(cherry picked from commit 7f904e2c66)
2019-10-12 08:00:43 +02:00
awr1
813b371758 [backport] Mention "lambdas" and => in the manual (#12397) [ci skip]
(so that "lambda" can be CTRL+F'd)

(cherry picked from commit 3b1760df72)
2019-10-12 08:00:43 +02:00
Andreas Rumpf
a09379f5fd fixes #12366 [backport] (#12393)
(cherry picked from commit f728614ef8)
2019-10-12 08:00:43 +02:00
narimiran
e9f7455bd6 bump version to 1.0.2 2019-10-09 06:42:54 +02:00
Andrew Smith
e03b1b79ae Updated the code example in the os module to use better grammar. (#12328)
(cherry picked from commit 0d94ee15c0)
2019-10-09 06:39:41 +02:00
Jasper Jenkins
0ea770c8f0 Macro docs additions (#12270)
* small macros doc additions

* more changes

* fixes [ci skip]

* capitalization, couple additions

* nkNodeKind to nnkNodeKind

(cherry picked from commit c20778d2d3)
2019-10-09 06:39:16 +02:00
Nindaleth
8a0012de42 fix a few dead links and a missing sentence in documentation (#12387)
(cherry picked from commit 84c956d9da)
2019-10-09 06:36:39 +02:00
treeform
1d4916b481 Easier build instructions for windows - just run build_all.bat. (#12276)
* Easier build instructions for windows.

* title letter

* Update build_all.bat to be like build_all.sh

(cherry picked from commit dbcffcfccb)
2019-10-09 06:36:19 +02:00
Ray Imber
2de758e68a Documentation improvements around the db interface (#12362)
Added more details about the limits and reasoning behind the API.
Came about from this discussion on IRC: https://irclogs.nim-lang.org/04-10-2019.html#16:58:04

(cherry picked from commit 7c23522b29)
2019-10-09 06:35:37 +02:00
pietroppeter
c8c9699850 [doc/tut1] removed discard discussion in comments (#12352)
(cherry picked from commit 89c37fada7)
2019-10-09 06:34:06 +02:00
kraptor
5df7f3fd5c Fix reference to parseSpec proc in readme (#12359)
(cherry picked from commit 412011eb96)
2019-10-09 06:33:45 +02:00
Andreas Rumpf
44d45b763c fixes #12315 [backport]; refs #12314 (#12385)
(cherry picked from commit f30da2f266)
2019-10-09 06:28:27 +02:00
alaviss
f7c150766a nimsuggest: fix tcp socket leak for epc backend (#12384) [backport]
Same as e9fa4c9b9c, but for the epc
backend which is used by emacs and vscode plugin.

Since the EPC backend only deal with one connection per nimsuggest
instance, only one socket is leaked, thus not as servere as with the tcp
backend.

(cherry picked from commit edb24b7ce0)
2019-10-09 06:28:27 +02:00
alaviss
4ae143ca60 nimsuggest: fix tcp socket leak (#12377) [backport]
A new socket is created for each iteration and leak immediately thanks
to the accept() call replacing the created socket with the client socket.

This commit fixes that.

(cherry picked from commit e9fa4c9b9c)
2019-10-09 06:28:27 +02:00
Leorize
0a8dcd5e11 azure: disable failing tests
(cherry picked from commit 73c8391fd3)
2019-10-08 11:43:16 +02:00
Leorize
929aa99665 testament: add azure integration
(cherry picked from commit acebcd7899)
2019-10-08 11:41:44 +02:00
Leorize
bae10d44fa azure-pipelines: add pipelines for linux, mac and win
This is the equivalent to the current AppVeyor + Travis setup.

(cherry picked from commit 880df4de62)
2019-10-08 11:41:38 +02:00
Andreas Rumpf
4632e8b26e fixes #12323 [backport]
(cherry picked from commit a60f18d025)
2019-10-07 18:40:07 +02:00
Andreas Rumpf
97e2e06b00 VM: no special casing for big endian machines; refs #9690 [backport] (#12364)
(cherry picked from commit 5be8e0b088)
2019-10-07 18:40:07 +02:00
Miran
b827431499 [backport] bundle nimpretty on Windows (#12358)
(cherry picked from commit 2909e41370)
2019-10-04 17:53:27 +02:00
Andrew Owen
99d448deeb [backport] Fix typo in docs (#12356) [ci skip]
(cherry picked from commit 64acc9dbfb)
2019-10-04 17:53:27 +02:00
Andreas Rumpf
9afd19b236 fixes #12291 [backport] (#12338)
(cherry picked from commit c51857f434)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
0d0cf86401 fixes #12336 [backport]
(cherry picked from commit 98e76a1058)
2019-10-03 09:32:46 +02:00
Tomohiro
5785444520 Fix how relativePath handle case sensitiviy (#12312) [backport]
(cherry picked from commit 64d5e25821)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
1b3f5eed70 fixes #12240 [backport] (#12308)
(cherry picked from commit 6dd4cbc3af)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
517538dcf8 fixes #12264 [backport] (#12302)
(cherry picked from commit dd082b6ec8)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
59916007cc fixes #12281 [backport]
(cherry picked from commit 72acf5de94)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
a5bcbe6dff fixes #12294 [backport]
(cherry picked from commit 1964589a29)
2019-10-03 09:32:46 +02:00
narimiran
cd3d4b5e05 [backport] run nimpretty on the remaining files
(cherry picked from commit 5732bb41ef)
2019-09-30 18:43:36 +02:00
narimiran
ac2181c5b9 [backport] run nimpretty on os-related stuff
(cherry picked from commit 34d0be2ec1)
2019-09-30 18:43:36 +02:00
narimiran
4675aae90b [backport] run nimpretty on string stuff
(cherry picked from commit dcf3181bd1)
2019-09-30 18:43:36 +02:00
narimiran
a0402b2012 [backport] run nimpretty on web stuff
(cherry picked from commit 0ca9cc7419)
2019-09-30 18:43:36 +02:00
narimiran
cbdc48ec66 [backport] run nimpretty on hashes
(cherry picked from commit 15895ebc3f)
2019-09-30 18:43:36 +02:00
narimiran
f19edae1b8 [backport] run nimpretty on parsers
(cherry picked from commit b17ed2ca9c)
2019-09-30 18:43:36 +02:00
narimiran
c5b9a44894 [backport] run nimpretty on numbers stuff
(cherry picked from commit 6c994b2498)
2019-09-30 18:43:36 +02:00
narimiran
3009eafc89 [backport] run nimpretty on async
(cherry picked from commit aa513d78e7)
2019-09-30 18:43:35 +02:00
Araq
1e97abec96 JS: gensym is stricter for 'this'; refs #12246 [backport]
(cherry picked from commit 63bcbea700)
2019-09-30 18:43:35 +02:00
Araq
95a655a975 different fix for #12279 [backport]
(cherry picked from commit c5a1149e00)
2019-09-30 18:43:35 +02:00
Araq
39f5a2b218 fixes #12279 [backport]
(cherry picked from commit 86de2cddf6)
2019-09-30 18:43:35 +02:00
narimiran
6c1f389d72 [backport] fix nimpretty removing space before pragma
(cherry picked from commit f804245087)
2019-09-30 18:43:35 +02:00
narimiran
1ae9cac3a4 [backport] fix #12278, don't expose internal PCRE documentation
(cherry picked from commit e0cd52365c)
2019-09-30 18:43:35 +02:00
Federico Ceratto
fa7f5742d3 Fix spellings (#12277) [backport]
(cherry picked from commit 39290cf88c)
2019-09-30 18:43:35 +02:00
Endeg
c8314b7c9c Fix #12242, replacing ":" with "@c" in packages [backport] (#12265)
(cherry picked from commit 657e09e79d)
2019-09-30 18:40:12 +02:00
Jjp137
52ea15cc24 threadpool: fix link in docs [ci skip] (#12258) [backport]
[backport]

(cherry picked from commit e065e51245)
2019-09-30 18:40:00 +02:00
Andreas Rumpf
7926440ae3 fixes the --verbosity:2 regression [backport]
(cherry picked from commit 13960066cb)
2019-09-30 18:39:48 +02:00
narimiran
bda6e071cd nightly version is 1.0.1 2019-09-30 18:38:14 +02:00
204 changed files with 2572 additions and 1955 deletions

148
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,148 @@
strategy:
matrix:
Linux_amd64:
vmImage: 'ubuntu-16.04'
CPU: amd64
Linux_i386:
vmImage: 'ubuntu-16.04'
CPU: i386
OSX_amd64:
vmImage: 'macOS-10.14'
CPU: amd64
OSX_amd64_cpp:
vmImage: 'macOS-10.14'
CPU: amd64
NIM_COMPILE_TO_CPP: true
Windows_amd64:
vmImage: 'windows-2019'
CPU: amd64
Windows_amd64_pkg:
vmImage: 'windows-2019'
CPU: amd64
NIM_TEST_PACKAGES: true
pool:
vmImage: $(vmImage)
workspace:
clean: all
steps:
- bash: git config --global core.autocrlf false
displayName: 'Disable auto conversion to CRLF by git (Windows-only)'
condition: eq(variables['Agent.OS'], 'Windows_NT')
- checkout: self
- bash: git clone --depth 1 https://github.com/nim-lang/csources.git
displayName: 'Checkout csources'
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install node.js 8.x'
- bash: |
sudo apt-fast update -qq
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends -yq \
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev
displayName: 'Install dependencies (amd64 Linux)'
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'amd64'))
- bash: |
sudo dpkg --add-architecture i386
# Downgrade llvm, libgcc and libstdc++:
# - 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
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
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends --allow-downgrades -yq \
g++-multilib gcc-multilib libcurl4-openssl-dev:i386 libgc-dev:i386 \
libsdl1.2-dev:i386 libsfml-dev:i386 libglib2.0-dev:i386
cat << EOF > bin/gcc
#!/bin/bash
exec $(which gcc) -m32 "\$@"
EOF
cat << EOF > bin/g++
#!/bin/bash
exec $(which g++) -m32 "\$@"
EOF
chmod 755 bin/gcc
chmod 755 bin/g++
displayName: 'Install dependencies (i386 Linux)'
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'i386'))
- bash: brew install boehmgc make sfml
displayName: 'Install dependencies (OSX)'
condition: eq(variables['Agent.OS'], 'Darwin')
- bash: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64-6.3.0.7z -o dist/mingw64.7z
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
7z x dist/mingw64.7z -odist
7z x dist/dlls.zip -obin
echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/dist/mingw64/bin'
displayName: 'Install dependencies (Windows)'
condition: eq(variables['Agent.OS'], 'Windows_NT')
- bash: echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/bin'
displayName: 'Add build binaries to PATH'
- bash: |
echo 'PATH:' "$PATH"
echo '##[section]gcc version'
gcc -v
echo '##[section]nodejs version'
node -v
echo '##[section]make version'
make -v
displayName: 'System information'
- bash: |
ncpu=
case '$(Agent.OS)' in
'Linux')
ncpu=$(nproc)
;;
'Darwin')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows_NT')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu=$(CPU)
displayName: 'Build 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]'
displayName: 'Run CI'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)

16
build_all.bat Normal file
View File

@@ -0,0 +1,16 @@
@echo off
rem build development version of the compiler; can be rerun safely
if not exist csources (
git clone --depth 1 https://github.com/nim-lang/csources.git
)
if not exist bin\nim.exe (
cd csources
if PROCESSOR_ARCHITECTURE == AMD64 (
SET ARCH=64
)
CALL build.bat
cd ..
)
bin\nim.exe c --skipUserCfg --skipParentCfg koch
koch.exe boot -d:release
koch.exe tools

View File

@@ -71,7 +71,7 @@ iterator parseTableCells*(s: string, delim = '\t'): Cell =
proc alignTable*(s: string, delim = '\t', fill = ' ', sep = " "): string =
## formats a `delim`-delimited `s` representing a table; each cell is aligned
## to a width that's computed for each column; consecutive columns are
## delimted by `sep`, and alignment space is filled using `fill`.
## delimited by `sep`, and alignment space is filled using `fill`.
## More customized formatting can be done by calling `parseTableCells` directly.
for cell in parseTableCells(s, delim):
result.add cell.text

View File

@@ -185,7 +185,7 @@ type
nkStmtListExpr, # a statement list followed by an expr; this is used
# to allow powerful multi-line templates
nkBlockExpr, # a statement block ending in an expr; this is used
# to allowe powerful multi-line templates that open a
# to allow powerful multi-line templates that open a
# temporary scope
nkStmtListType, # a statement list ending in a type; for macros
nkBlockType, # a statement block ending in a type; for macros
@@ -272,7 +272,7 @@ type
sfNamedParamCall, # symbol needs named parameter call syntax in target
# language; for interfacing with Objective C
sfDiscardable, # returned value may be discarded implicitly
sfOverriden, # proc is overriden
sfOverriden, # proc is overridden
sfCallsite # A flag for template symbols to tell the
# compiler it should use line information from
# the calling side of the macro, not from the
@@ -535,8 +535,8 @@ type
tfTriggersCompileTime # uses the NimNode type which make the proc
# implicitly '.compiletime'
tfRefsAnonObj # used for 'ref object' and 'ptr object'
tfCovariant # covariant generic param mimicing a ptr type
tfWeakCovariant # covariant generic param mimicing a seq/array type
tfCovariant # covariant generic param mimicking a ptr type
tfWeakCovariant # covariant generic param mimicking a seq/array type
tfContravariant # contravariant generic param
tfCheckedForDestructor # type was checked for having a destructor.
# If it has one, t.destructor is not nil.
@@ -1250,7 +1250,7 @@ proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode =
# this is dirty. abstractVarRange isn't defined yet and therefor it
# this is dirty. abstractVarRange isn't defined yet and therefore it
# is duplicated here.
const abstractVarRange = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
tyTypeDesc, tyAlias, tyInferred, tySink, tyOwned}

View File

@@ -1027,7 +1027,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
dec p.splitDecls
proc genEcho(p: BProc, n: PNode) =
# this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
# this unusual way of implementing it ensures that e.g. ``echo("hallo", 45)``
# is threadsafe.
internalAssert p.config, n.kind == nkBracket
if p.config.target.targetOS == osGenode:

View File

@@ -784,7 +784,7 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
var branches: seq[Rope]
newSeq(branches, bitMask + 1)
var a: TLoc
initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto:
initLocExpr(p, t.sons[0], a) # fist pass: generate ifs+goto:
var labId = p.labels
for i in 1 ..< len(t):
inc(p.labels)

View File

@@ -61,7 +61,7 @@ proc mangleParamName(m: BModule; s: PSym): Rope =
var res = s.name.s.mangle
# Take into account if HCR is on because of the following scenario:
# if a module gets imported and it has some more importc symbols in it,
# some param names might recieve the "_0" suffix to distinguish from what
# some param names might receive the "_0" suffix to distinguish from what
# is newly available. That might lead to changes in the C code in nimcache
# that contain only a parameter name change, but that is enough to mandate
# recompilation of that source file and thus a new shared object will be
@@ -287,6 +287,7 @@ proc fillResult(conf: ConfigRef; param: PNode) =
proc typeNameOrLiteral(m: BModule; t: PType, literal: string): Rope =
if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone:
useHeader(m, t.sym)
result = t.sym.loc.r
else:
result = rope(literal)

View File

@@ -997,13 +997,14 @@ proc genProcAux(m: BModule, prc: PSym) =
closureSetup(p, prc)
genStmts(p, procBody) # modifies p.locals, p.init, etc.
var generatedProc: Rope
generatedProc.genCLineDir prc.info, m.config
if sfNoReturn in prc.flags:
if hasDeclspec in extccomp.CC[p.config.cCompiler].props:
header = "__declspec(noreturn) " & header
if sfPure in prc.flags:
if hasDeclspec in extccomp.CC[p.config.cCompiler].props:
header = "__declspec(naked) " & header
generatedProc = ropecg(p.module, "$N$1 {$n$2$3$4}$N$N",
generatedProc.add ropecg(p.module, "$1 {$n$2$3$4}$N$N",
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)])
else:
if m.hcrOn and isReloadable(m, prc):
@@ -1011,7 +1012,7 @@ proc genProcAux(m: BModule, prc: PSym) =
# This fixes the use of methods and also the case when 2 functions within the same module
# call each other using directly the "_actual" versions (an optimization) - see issue #11608
addf(m.s[cfsProcHeaders], "$1;\n", [header])
generatedProc = ropecg(p.module, "$N$1 {$N", [header])
generatedProc.add ropecg(p.module, "$1 {", [header])
add(generatedProc, initGCFrame(p))
if optStackTrace in prc.options:
add(generatedProc, p.s(cpsLocals))
@@ -1255,7 +1256,7 @@ proc hcrGetProcLoadCode(m: BModule, sym, prefix, handle, getProcFunc: string): R
proc genMainProc(m: BModule) =
## this function is called in cgenWriteModules after all modules are closed,
## it means raising dependency on the symbols is too late as it will not propogate
## it means raising dependency on the symbols is too late as it will not propagate
## into other modules, only simple rope manipulations are allowed
var preMainCode: Rope
@@ -1514,7 +1515,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
proc genDatInitCode(m: BModule) =
## this function is called in cgenWriteModules after all modules are closed,
## it means raising dependency on the symbols is too late as it will not propogate
## it means raising dependency on the symbols is too late as it will not propagate
## into other modules, only simple rope manipulations are allowed
var moduleDatInitRequired = m.hcrOn
@@ -1558,7 +1559,7 @@ proc hcrGetProcLoadCode(m: BModule, sym, prefix, handle, getProcFunc: string): R
proc genInitCode(m: BModule) =
## this function is called in cgenWriteModules after all modules are closed,
## it means raising dependency on the symbols is too late as it will not propogate
## it means raising dependency on the symbols is too late as it will not propagate
## into other modules, only simple rope manipulations are allowed
var moduleInitRequired = m.hcrOn
let initname = getInitName(m)
@@ -1746,7 +1747,7 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: AbsoluteFile): BModule
result.typeNodesName = getTempName(result)
result.nimTypesName = getTempName(result)
# no line tracing for the init sections of the system module so that we
# don't generate a TFrame which can confuse the stack botton initialization:
# don't generate a TFrame which can confuse the stack bottom initialization:
if sfSystemModule in module.flags:
incl result.flags, preventStackTrace
excl(result.preInitProc.options, optStackTrace)

View File

@@ -58,7 +58,7 @@ type
id*: int # the ID of the label; positive means that it
label*: Rope # generated text for the label
# nil if label is not used
sections*: TCProcSections # the code beloging
sections*: TCProcSections # the code belonging
isLoop*: bool # whether block is a loop
nestedTryStmts*: int16 # how many try statements is it nested into
nestedExceptStmts*: int16 # how many except statements is it nested into
@@ -150,7 +150,7 @@ type
initProc*: BProc # code for init procedure
preInitProc*: BProc # code executed before the init proc
hcrCreateTypeInfosProc*: Rope # type info globals are in here when HCR=on
inHcrInitGuard*: bool # We are currently withing a HCR reloading guard.
inHcrInitGuard*: bool # We are currently within a HCR reloading guard.
typeStack*: TTypeSeq # used for type generation
dataCache*: TNodeTable
typeNodes*, nimTypes*: int # used for type info generation

View File

@@ -683,7 +683,8 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
n[0] = ex
result.add(n)
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv:
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv,
nkDerefExpr, nkHiddenDeref:
var ns = false
for i in 0 ..< n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
@@ -757,7 +758,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
n[0] = newSymNode(ctx.g.getSysSym(n[0].info, "true"))
n[1] = newBody
of nkDotExpr:
of nkDotExpr, nkCheckedFieldExpr:
var ns = false
n[0] = ctx.lowerStmtListExprs(n[0], ns)
if ns:
@@ -1288,7 +1289,7 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
if getEnvParam(fn).isNil:
# Lambda lifting was not done yet. Use temporary :state sym, which will
# be handled specially by lambda lifting. Local temp vars (if needed)
# should folllow the same logic.
# should follow the same logic.
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info)
ctx.stateVarSym.typ = g.createClosureIterStateType(fn)
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info)
@@ -1309,7 +1310,7 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
# Optimize empty states away
ctx.deleteEmptyStates()
# Make new body by concating the list of states
# Make new body by concatenating the list of states
result = newNodeI(nkStmtList, n.info)
for s in ctx.states:
assert(s.len == 2)

View File

@@ -87,7 +87,7 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
discard
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
# command line can overwrite the config file's settings
extccomp.initVars(conf)
self.processCmdLine(passCmd2, "", conf)
if conf.command == "":

View File

@@ -513,7 +513,7 @@ proc genTry(c: var Con; n: PNode) =
let f = c.tryStmtFixups[i]
c.patch(f)
# we also need to produce join instructions
# for the 'fork' that might preceed the goto instruction
# for the 'fork' that might precede the goto instruction
if f.int-1 >= 0 and c.code[f.int-1].kind == fork:
c.joinI(TPosition(f.int-1), n)

View File

@@ -135,7 +135,7 @@ proc evalTemplateArgs(n: PNode, s: PSym; conf: ConfigRef; fromHlo: bool): PNode
else:
addSon(result, default.copyTree)
# add any generic paramaters
# add any generic parameters
for i in 1 .. genericParams:
result.addSon n.sons[givenRegularParams + i]

View File

@@ -404,7 +404,7 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
CC[c].name & fullSuffix
result = getConfigVar(conf, fullCCname)
if result.len == 0:
# not overriden for this cross compilation setting?
# not overridden for this cross compilation setting?
result = getConfigVar(conf, CC[c].name & fullSuffix)
else:
result = getConfigVar(conf, CC[c].name & fullSuffix)
@@ -757,7 +757,7 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
# way of being able to debug and rebuild the program at the same time. This
# is accomplished using the /PDB:<filename> flag (there also exists the
# /PDBALTPATH:<filename> flag). The only downside is that the .pdb files are
# atleast 300kb big (when linking statically to the runtime - or else 5mb+)
# at least 300kb big (when linking statically to the runtime - or else 5mb+)
# and will quickly accumulate. There is a hacky solution: we could try to
# delete all .pdb files with a pattern and swallow exceptions.
#

View File

@@ -22,7 +22,7 @@ type
info: TLineInfo
indent, emitPar: int
x: string # the current input line
outp: PLLStream # the ouput will be parsed by pnimsyn
outp: PLLStream # the output will be parsed by pnimsyn
subsChar, nimDirective: char
emit, conc, toStr: string
curly, bracket, par: int

View File

@@ -14,7 +14,7 @@ proc hlo(c: PContext, n: PNode): PNode
proc evalPattern(c: PContext, n, orig: PNode): PNode =
internalAssert c.config, n.kind == nkCall and n.sons[0].kind == nkSym
# we need to ensure that the resulting AST is semchecked. However, it's
# aweful to semcheck before macro invocation, so we don't and treat
# awful to semcheck before macro invocation, so we don't and treat
# templates and macros as immediate in this context.
var rule: string
if optHints in c.config.options and hintPattern in c.config.notes:

View File

@@ -27,7 +27,7 @@ proc importPureEnumField*(c: PContext; s: PSym) =
if checkB == nil:
strTableAdd(c.pureEnumFields, s)
else:
# mark as ambigous:
# mark as ambiguous:
incl(c.ambiguousSymbols, checkB.id)
incl(c.ambiguousSymbols, s.id)

View File

@@ -256,7 +256,7 @@ proc isLastRead(n: PNode; c: var Con): bool =
proc initialized(code: ControlFlowGraph; pc: int,
init, uninit: var IntSet; comesFrom: int): int =
## Computes the set of definitely initialized variables accross all code paths
## Computes the set of definitely initialized variables across all code paths
## as an IntSet of IDs.
var pc = pc
while pc < code.len:
@@ -492,7 +492,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
result.add pArg(arg[i], c, i < L and isSinkTypeForParam(parameters[i]))
elif arg.containsConstSeq:
# const sequences are not mutable and so we need to pass a copy to the
# sink parameter (bug #11524). Note that the string implemenation is
# sink parameter (bug #11524). Note that the string implementation is
# different and can deal with 'const string sunk into var'.
result = passCopyToSink(arg, c)
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkCharLit..nkTripleStrLit}:

View File

@@ -73,6 +73,15 @@ proc toInt64*(arg: Int128): int64 =
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc toInt64Checked*(arg: Int128; onError: int64): int64 =
if isNegative(arg):
if arg.sdata(3) != -1 or arg.sdata(2) != -1:
return onError
else:
if arg.sdata(3) != 0 or arg.sdata(2) != 0:
return onError
return cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc toInt32*(arg: Int128): int32 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
@@ -427,7 +436,7 @@ proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
result.quotient = -quotient
else:
result.quotient = quotient
if isNegativeB:
if isNegativeA:
result.remainder = -dividend
else:
result.remainder = dividend
@@ -667,3 +676,12 @@ when isMainModule:
doAssert $high(Int128) == "170141183460469231731687303715884105727"
doAssert $low(Int128) == "-170141183460469231731687303715884105728"
var ma = 100'i64
var mb = 13
# sign correctness
doAssert divMod(toInt128( ma),toInt128( mb)) == (toInt128( ma div mb), toInt128( ma mod mb))
doAssert divMod(toInt128(-ma),toInt128( mb)) == (toInt128(-ma div mb), toInt128(-ma mod mb))
doAssert divMod(toInt128( ma),toInt128(-mb)) == (toInt128( ma div -mb), toInt128( ma mod -mb))
doAssert divMod(toInt128(-ma),toInt128(-mb)) == (toInt128(-ma div -mb), toInt128(-ma mod -mb))

View File

@@ -1295,12 +1295,16 @@ proc genCopyForParamIfNeeded(p: PProc, n: PNode) =
return
owner = owner.up
proc genVarInit(p: PProc, v: PSym, n: PNode)
proc genSym(p: PProc, n: PNode, r: var TCompRes) =
var s = n.sym
case s.kind
of skVar, skLet, skParam, skTemp, skResult, skForVar:
if s.loc.r == nil:
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
if sfCompileTime in s.flags:
genVarInit(p, s, if s.ast != nil: s.ast else: newNodeI(nkEmpty, s.info))
if s.kind == skParam:
genCopyForParamIfNeeded(p, n)
let k = mapType(p, s.typ)
@@ -1732,7 +1736,11 @@ proc genVarStmt(p: PProc, n: PNode) =
var v = a.sons[0].sym
if lfNoDecl notin v.loc.flags and sfImportc notin v.flags:
genLineDir(p, a)
genVarInit(p, v, a.sons[2])
if sfCompileTime notin v.flags:
genVarInit(p, v, a.sons[2])
else:
# lazy emit, done when it's actually used.
if v.ast == nil: v.ast = a[2]
proc genConstant(p: PProc, c: PSym) =
if lfNoDecl notin c.loc.flags and not p.g.generatedSyms.containsOrIncl(c.id):

View File

@@ -477,7 +477,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
w = up
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef,
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt:
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt, nkTypeOfExpr:
discard
of nkLambdaKinds, nkIteratorDef:
if n.typ != nil:
@@ -760,6 +760,8 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
n[0].sons[1] = liftCapturedVars(n[0].sons[1], owner, d, c)
else:
n.sons[0] = liftCapturedVars(n[0], owner, d, c)
of nkTypeOfExpr:
result = n
else:
if owner.isIterator:
if nfLL in n.flags:

View File

@@ -499,7 +499,8 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
rememberSplit(splitComma)
wrSpace em
of openPars:
if tok.strongSpaceA > 0 and not em.endsInWhite and not em.wasExportMarker:
if tok.strongSpaceA > 0 and not em.endsInWhite and
(not em.wasExportMarker or tok.tokType == tkCurlyDotLe):
wrSpace em
wr(em, TokTypeToStr[tok.tokType], ltSomeParLe)
rememberSplit(splitParLe)

View File

@@ -134,7 +134,7 @@ type
TErrorHandler* = proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string)
TLexer* = object of TBaseLexer
fileIdx*: FileIndex
indentAhead*: int # if > 0 an indendation has already been read
indentAhead*: int # if > 0 an indentation has already been read
# this is needed because scanning comments
# needs so much look-ahead
currLineIndent*: int

View File

@@ -233,7 +233,7 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
addInterfaceDeclAux(c, sym)
when defined(nimfix):
# when we cannot find the identifier, retry with a changed identifer:
# when we cannot find the identifier, retry with a changed identifier:
proc altSpelling(x: PIdent): PIdent =
case x.s[0]
of 'A'..'Z': result = getIdent(toLowerAscii(x.s[0]) & x.s.substr(1))

View File

@@ -64,7 +64,7 @@ type
importModuleCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PSym {.nimcall.}
includeFileCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PNode {.nimcall.}
recordStmt*: proc (graph: ModuleGraph; m: PSym; n: PNode) {.nimcall.}
cacheSeqs*: Table[string, PNode] # state that is shared to suppor the 'macrocache' API
cacheSeqs*: Table[string, PNode] # state that is shared to support the 'macrocache' API
cacheCounters*: Table[string, BiggestInt]
cacheTables*: Table[string, BTree[string, PNode]]
passes*: seq[TPass]
@@ -215,7 +215,7 @@ proc addDep*(g: ModuleGraph; m: PSym, dep: FileIndex) =
addModuleDep(g.incr, g.config, m.info.fileIndex, dep, isIncludeFile = false)
if g.suggestMode:
g.deps.incl m.position.dependsOn(dep.int)
# we compute the transitive closure later when quering the graph lazily.
# we compute the transitive closure later when querying the graph lazily.
# this improves efficiency quite a lot:
#invalidTransitiveClosure = true

View File

@@ -46,7 +46,7 @@ proc selectUniqueSymbol*(i: Interpreter; name: string;
s = nextIdentIter(it, i.mainModule.tab)
proc selectRoutine*(i: Interpreter; name: string): PSym =
## Selects a declared rountine (proc/func/etc) from the main module.
## Selects a declared routine (proc/func/etc) from the main module.
## The routine needs to have the export marker ``*``. The only matching
## routine is returned and ``nil`` if it is overloaded.
result = selectUniqueSymbol(i, name, {skTemplate, skMacro, skFunc,

View File

@@ -98,7 +98,7 @@ proc handleCmdLine(config: ConfigRef) =
gProjectPath = getCurrentDir()
loadConfigs(DefaultConfig, config) # load all config files
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
# command line can overwrite the config file's settings
extccomp.initVars()
processCmdLine(passCmd2, "", config)
mainCommand()

View File

@@ -15,6 +15,6 @@ const
VersionAsString* = system.NimVersion
RodFileVersion* = "1223" # modify this if the rod-format changes!
NimCompilerApiVersion* = 3 ## Check for the existance of this before accessing it
NimCompilerApiVersion* = 3 ## Check for the existence of this before accessing it
## as older versions of the compiler API do not
## declare this.

View File

@@ -138,7 +138,7 @@ type
LegacyFeature* = enum
allowSemcheckedAstModification,
## Allows to modify a NimNode where the type has already been
## flaged with nfSem. If you actually do this, it will cause
## flagged with nfSem. If you actually do this, it will cause
## bugs.
SymbolFilesOption* = enum
@@ -727,7 +727,7 @@ proc `$`*(c: IdeCmd): string =
proc floatInt64Align*(conf: ConfigRef): int16 =
## Returns either 4 or 8 depending on reasons.
if conf.target.targetCPU == cpuI386:
if conf != nil and conf.target.targetCPU == cpuI386:
#on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
if conf.target.targetOS != osWindows:
# on i386 for all known POSIX systems, 64bits ints are aligned

View File

@@ -40,19 +40,16 @@ proc getPackageName*(conf: ConfigRef; path: string): string =
proc fakePackageName*(conf: ConfigRef; path: AbsoluteFile): string =
# foo-#head/../bar becomes @foo-@hhead@s..@sbar
result = "@m" & relativeTo(path, conf.projectPath, '/').string.multiReplace({"/": "@s", "#": "@h", "@": "@@"})
result = "@m" & relativeTo(path, conf.projectPath, '/').string.multiReplace({"/": "@s", "#": "@h", "@": "@@", ":": "@c"})
proc demanglePackageName*(path: string): string =
result = path.multiReplace({"@@": "@", "@h": "#", "@s": "/", "@m": ""})
result = path.multiReplace({"@@": "@", "@h": "#", "@s": "/", "@m": "", "@c": ":"})
proc withPackageName*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
let x = getPackageName(conf, path.string)
if x.len == 0:
result = path
let (p, file, ext) = path.splitFile
if x == "stdlib":
# Hot code reloading now relies on 'stdlib_system' names etc.
result = p / RelativeFile((x & '_' & file) & ext)
else:
let (p, file, ext) = path.splitFile
if x == "stdlib":
# Hot code reloading now relies on 'stdlib_system' names etc.
result = p / RelativeFile((x & '_' & file) & ext)
else:
result = p / RelativeFile(fakePackageName(conf, path))
result = p / RelativeFile(fakePackageName(conf, path))

View File

@@ -710,7 +710,7 @@ proc identOrLiteral(p: var TParser, mode: TPrimaryMode): PNode =
result = parseCast(p)
else:
parMessage(p, errExprExpected, p.tok)
getTok(p) # we must consume a token here to prevend endless loops!
getTok(p) # we must consume a token here to prevent endless loops!
result = p.emptyNode
proc namedParams(p: var TParser, callee: PNode,

View File

@@ -720,7 +720,7 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
proc semCustomPragma(c: PContext, n: PNode): PNode =
var callNode: PNode
if n.kind == nkIdent:
if n.kind in {nkIdent, nkSym}:
# pragma -> pragma()
callNode = newTree(nkCall, n)
elif n.kind == nkExprColonExpr:

View File

@@ -29,7 +29,7 @@ proc equalGenericParams(procA, procB: PNode): bool =
result = true
proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym =
# Searchs for a forward declaration or a "twin" symbol of fn
# Searches for a forward declaration or a "twin" symbol of fn
# in the symbol table. If the parameter lists are exactly
# the same the sym in the symbol table is returned, else nil.
var it: TIdentIter
@@ -108,7 +108,7 @@ when false:
result = true
proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
# Searchs for the fn in the symbol table. If the parameter lists are suitable
# Searches for the fn in the symbol table. If the parameter lists are suitable
# for borrowing the sym in the symbol table is returned, else nil.
var it: TIdentIter
for scope in walkScopes(startScope):

View File

@@ -640,7 +640,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
result = explicitGenericInstError(c, n)
proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
# Searchs for the fn in the symbol table. If the parameter lists are suitable
# Searches for the fn in the symbol table. If the parameter lists are suitable
# for borrowing the sym in the symbol table is returned, else nil.
# New approach: generate fn(x, y, z) where x, y, z have the proper types
# and use the overloading resolution mechanism:

View File

@@ -2038,7 +2038,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
let oldErrorMax = c.config.errorMax
let oldCompilesId = c.compilesContextId
# if this is a nested 'when compiles', do not increase the ID so that
# generic instantations can still be cached for this level.
# generic instantiations can still be cached for this level.
if c.compilesContextId == 0:
inc c.compilesContextIdGenerator
c.compilesContextId = c.compilesContextIdGenerator

View File

@@ -211,7 +211,7 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
param.typ = makeTypeDesc(c, header[i+1])
# this scope was not created by the user,
# unused params shoudn't be reported.
# unused params shouldn't be reported.
param.flags.incl sfUsed
addDecl(c, param)

View File

@@ -279,7 +279,7 @@ proc semDynamicBindSym(c: PContext, n: PNode): PNode =
a.setResult opBindSym(c, scope, a.getNode(0), a.getInt(1).int, a.getNode(2))
let
# altough we use VM callback here, it is not
# although we use VM callback here, it is not
# executed like 'normal' VM callback
idx = vm.registerCallback("bindSymImpl", bindSymWrapper)
# dummy node to carry idx information to VM

View File

@@ -339,7 +339,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
result = initPartial
if discriminatorVal.kind == nkIntLit:
# When the discriminator is a compile-time value, we also know
# which brach will be selected:
# which branch will be selected:
let matchedBranch = recNode.pickCaseBranch discriminatorVal
if matchedBranch != nil: checkMissingFields matchedBranch
else:

View File

@@ -575,7 +575,7 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType; caller: PNode)
notNilCheck(tracked, n, paramType)
proc breaksBlock(n: PNode): bool =
# sematic check doesn't allow statements after raise, break, return or
# semantic check doesn't allow statements after raise, break, return or
# call to noreturn proc, so it is safe to check just the last statements
var it = n
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
@@ -751,7 +751,9 @@ proc track(tracked: PEffects, n: PNode) =
discard
else:
message(tracked.config, arg.info, warnProveInit, $arg)
createTypeBoundOps(tracked.graph, tracked.c, n[1].typ.lastSon, n.info)
# check required for 'nim check':
if n[1].typ.len > 0:
createTypeBoundOps(tracked.graph, tracked.c, n[1].typ.lastSon, n.info)
for i in 0 ..< safeLen(n):
track(tracked, n.sons[i])
of nkDotExpr:

View File

@@ -635,6 +635,12 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
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")
elif firstOrd(c.config, typ) != 0:
localError(c.config, n.info, "low(" & $a.sons[0].sym.name.s &
") must be 0 for discriminant")
elif lengthOrd(c.config, typ) > 0x00007FFF:
localError(c.config, n.info, "len($1) must be less than 32768" % a.sons[0].sym.name.s)
for i in 1 ..< len(n):
var b = copyTree(n.sons[i])
addSon(a, b)

View File

@@ -76,13 +76,13 @@ type
c*: PContext
typeMap*: ptr LayeredIdTable # map PType to PType
symMap*: TIdTable # map PSym to PSym
localCache*: TIdTable # local cache for remembering alraedy replaced
localCache*: TIdTable # local cache for remembering already replaced
# types during instantiation of meta types
# (they are not stored in the global cache)
info*: TLineInfo
allowMetaTypes*: bool # allow types such as seq[Number]
# i.e. the result contains unresolved generics
skipTypedesc*: bool # wether we should skip typeDescs
skipTypedesc*: bool # whether we should skip typeDescs
isReturnType*: bool
owner*: PSym # where this instantiation comes from
recursionLimit: int
@@ -249,7 +249,7 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
return s
# XXX: Bound symbols in default parameter expressions may reach here.
# We cannot process them, becase `sym.n` may point to a proc body with
# We cannot process them, because `sym.n` may point to a proc body with
# cyclic references that will lead to an infinite recursion.
# Perhaps we should not use a black-list here, but a whitelist instead
# (e.g. skGenericParam and skType).
@@ -589,7 +589,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
for i in 0 ..< len(result):
if result.sons[i] != nil:
if result.sons[i].kind == tyGenericBody:
localError(cl.c.config, t.sym.info,
localError(cl.c.config, if t.sym != nil: t.sym.info else: cl.info,
"cannot instantiate '" &
typeToString(result.sons[i], preferDesc) &
"' inside of type definition: '" &

View File

@@ -16,11 +16,12 @@ proc align(address, alignment: int): int =
result = (address + (alignment - 1)) and not (alignment - 1)
const
## a size is concidered "unknown" when it is an imported type from C
## a size is considered "unknown" when it is an imported type from C
## or C++.
szUnknownSize* = -3
szIllegalRecursion* = -2
szUncomputedSize* = -1
szTooBigSize* = -4
type IllegalTypeRecursionError = object of Exception
@@ -33,14 +34,14 @@ type
offset: int
proc inc(arg: var OffsetAccum; value: int) =
if unlikely(value == szIllegalRecursion): raiseIllegalTypeRecursion()
if unlikely(value == szIllegalRecursion): raiseIllegalTypeRecursion()
if value == szUnknownSize or arg.offset == szUnknownSize:
arg.offset = szUnknownSize
else:
arg.offset += value
proc alignmentMax(a,b: int): int =
if unlikely(a == szIllegalRecursion or b == szIllegalRecursion): raiseIllegalTypeRecursion()
if unlikely(a == szIllegalRecursion or b == szIllegalRecursion): raiseIllegalTypeRecursion()
if a == szUnknownSize or b == szUnknownSize:
szUnknownSize
else:
@@ -57,7 +58,7 @@ proc align(arg: var OffsetAccum; value: int) =
proc mergeBranch(arg: var OffsetAccum; value: OffsetAccum) =
if value.maxAlign == szUnknownSize or arg.maxAlign == szUnknownSize or
value.offset == szUnknownSize or arg.offset == szUnknownSize:
value.offset == szUnknownSize or arg.offset == szUnknownSize:
arg.maxAlign = szUnknownSize
arg.offset = szUnknownSize
else:
@@ -111,7 +112,7 @@ proc setOffsetsToUnknown(n: PNode) =
for i in 0 ..< safeLen(n):
setOffsetsToUnknown(n[i])
proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, packed: bool, accum: var OffsetAccum): void =
proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, packed: bool, accum: var OffsetAccum) =
## ``offset`` is the offset within the object, after the node has been written, no padding bytes added
## ``align`` maximum alignment from all sub nodes
assert n != nil
@@ -256,7 +257,7 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
typ.size = elemSize
typ.align = int16(elemSize)
else:
typ.size = toInt64(lengthOrd(conf, typ.sons[0]) * int32(elemSize))
typ.size = toInt64Checked(lengthOrd(conf, typ.sons[0]) * int32(elemSize), szTooBigSize)
typ.align = typ.sons[1].align
of tyUncheckedArray:

View File

@@ -877,7 +877,7 @@ proc hoistParamsUsedInDefault(c: PTransf, call, letSection, defExpr: PNode): PNo
# The recursion may confuse you. It performs two duties:
#
# 1) extracting all referenced params from default expressions
# into a let section preceeding the call
# into a let section preceding the call
#
# 2) replacing the "references" within the default expression
# with these extracted skLet symbols.
@@ -1140,7 +1140,7 @@ proc transformBody*(g: ModuleGraph, prc: PSym, cache = true;
let cache = cache or prc.typ.callConv == ccInline
if cache:
# genProc for inline procs will be called multiple times from diffrent modules,
# genProc for inline procs will be called multiple times from different modules,
# it is important to transform exactly once to get sym ids and locations right
prc.transformedBody = result
else:

View File

@@ -303,7 +303,7 @@ proc analyseObjectWithTypeFieldAux(t: PType,
proc analyseObjectWithTypeField*(t: PType): TTypeFieldResult =
# this does a complex analysis whether a call to ``objectInit`` needs to be
# made or intializing of the type field suffices or if there is no type field
# made or initializing of the type field suffices or if there is no type field
# at all in this type.
var marker = initIntSet()
result = analyseObjectWithTypeFieldAux(t, marker)
@@ -814,11 +814,8 @@ proc floatRangeCheck*(x: BiggestFloat, t: PType): bool =
false
proc lengthOrd*(conf: ConfigRef; t: PType): Int128 =
case t.skipTypes(tyUserTypeClasses).kind
of tyInt64, tyInt32, tyInt:
# XXX: this is just wrong
result = lastOrd(conf, t)
of tyDistinct: result = lengthOrd(conf, t.sons[0])
if t.skipTypes(tyUserTypeClasses).kind == tyDistinct:
result = lengthOrd(conf, t.sons[0])
else:
let last = lastOrd(conf, t)
let first = firstOrd(conf, t)

View File

@@ -156,7 +156,7 @@ proc createStrKeepNode(x: var TFullReg; keepNode=true) =
x.node = newNode(nkStrLit)
# It not only hackey, it is also wrong for tgentemplate. The primary
# cause of bugs like these is that the VM does not properly distinguish
# between variable defintions (var foo = e) and variable updates (foo = e).
# between variable definitions (var foo = e) and variable updates (foo = e).
include vmhooks
@@ -357,7 +357,7 @@ proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int =
result = -1
# Traverse the stack starting from the end in order to execute the blocks in
# the inteded order
# the intended order
for i in 1 .. f.safePoints.len:
var pc = f.safePoints[^i]
# Skip the `except` blocks
@@ -436,12 +436,8 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType):
let destDist = (sizeof(dest.intVal) - desttyp.size) * 8
var value = cast[BiggestUInt](src.intVal)
when system.cpuEndian == bigEndian:
value = (value shr srcDist) shl srcDist
value = (value shr destDist) shl destDist
else:
value = (value shl srcDist) shr srcDist
value = (value shl destDist) shr destDist
value = (value shl srcDist) shr srcDist
value = (value shl destDist) shr destDist
dest.intVal = cast[BiggestInt](value)
of tyFloat..tyFloat64:
if dest.kind != rkFloat:
@@ -714,7 +710,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of rkNode:
if regs[ra].node.kind == nkNilLit:
stackTrace(c, tos, pc, errNilAccess)
assert nfIsRef in regs[ra].node.flags
regs[ra].node[] = regs[rc].regToNode[]
regs[ra].node.flags.incl nfIsRef
else: stackTrace(c, tos, pc, errNilAccess)
@@ -1189,7 +1184,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
tos.pushSafePoint(pc + rbx)
assert c.code[pc+rbx].opcode in {opcExcept, opcFinally}
of opcExcept:
# This opcode is never executed, it only holds informations for the
# This opcode is never executed, it only holds information for the
# exception handling routines.
doAssert(false)
of opcFinally:
@@ -1275,7 +1270,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node = getNullValue(typ, c.debug[pc], c.config)
# opcLdNull really is the gist of the VM's problems: should it load
# a fresh null to regs[ra].node or to regs[ra].node[]? This really
# depends on whether regs[ra] represents the variable itself or wether
# depends on whether regs[ra] represents the variable itself or whether
# it holds the indirection! Due to the way registers are re-used we cannot
# say for sure here! --> The codegen has to deal with it
# via 'genAsgnPatch'.
@@ -1567,19 +1562,20 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node.strVal = opSlurp(regs[rb].node.strVal, c.debug[pc],
c.module, c.config)
of opcGorge:
decodeBC(rkNode)
inc pc
let rd = c.code[pc].regA
createStr regs[ra]
if defined(nimsuggest) or c.config.cmd == cmdCheck:
discard "don't run staticExec for 'nim suggest'"
regs[ra].node.strVal = ""
else:
when defined(nimcore):
decodeBC(rkNode)
inc pc
let rd = c.code[pc].regA
createStr regs[ra]
regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
regs[rc].node.strVal, regs[rd].node.strVal,
c.debug[pc], c.config)[0]
else:
regs[ra].node.strVal = ""
globalError(c.config, c.debug[pc], "VM is not built with 'gorge' support")
of opcNError, opcNWarning, opcNHint:
decodeB(rkNode)

View File

@@ -127,7 +127,7 @@ proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
ctx.debug.add(n.info)
proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) =
# Takes the `b` register and the immediate `imm`, appies the operation `opc`,
# Takes the `b` register and the immediate `imm`, applies the operation `opc`,
# and stores the output value into `a`.
# `imm` is signed and must be within [-128, 127]
if imm >= -128 and imm <= 127:
@@ -948,9 +948,13 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
c.genAddSubInt(n, dest, opcAddInt)
of mInc, mDec:
unused(c, n, dest)
let opc = if m == mInc: opcAddInt else: opcSubInt
let isUnsigned = n.sons[1].typ.skipTypes(abstractVarRange).kind in {tyUInt..tyUInt64}
let opc = if not isUnsigned:
if m == mInc: opcAddInt else: opcSubInt
else:
if m == mInc: opcAddu else: opcSubu
let d = c.genx(n.sons[1])
if n.sons[2].isInt8Lit:
if n.sons[2].isInt8Lit and not isUnsigned:
c.gABI(n, succ(opc), d, d, n.sons[2].intVal)
else:
let tmp = c.genx(n.sons[2])
@@ -1316,7 +1320,6 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mMove:
let arg = n[1]
let a = c.genx(arg)
assert dest >= 0
if dest < 0: dest = c.getTemp(arg.typ)
gABC(c, arg, whichAsgnOpc(arg, requiresCopy=false), dest, a)
# XXX use ldNullOpcode() here?

View File

@@ -7,7 +7,7 @@
# distribution, for details about the copyright.
#
# Unforunately this cannot be a module yet:
# Unfortunately this cannot be a module yet:
#import vmdeps, vm
from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc,

View File

@@ -119,9 +119,12 @@ procs ``GC_ref`` and ``GC_unref`` to mark objects as referenced to avoid them
being freed by the GC. Other useful procs from `system <system.html>`_ you can
use to keep track of memory are:
* getTotalMem(): returns the amount of total memory managed by the GC.
* getOccupiedMem(): bytes reserved by the GC and used by objects.
* getFreeMem(): bytes reserved by the GC and not in use.
* ``getTotalMem()`` Returns the amount of total memory managed by the GC.
* ``getOccupiedMem()`` Bytes reserved by the GC and used by objects.
* ``getFreeMem()`` Bytes reserved by the GC and not in use.
These numbers are usually only for the running thread, not for the whole heap,
with the exception of ``--gc:boehm`` and ``--gc:go``.
In addition to ``GC_ref`` and ``GC_unref`` you can avoid the GC by manually
allocating memory with procs like ``alloc``, ``allocShared``, or
@@ -144,3 +147,24 @@ The numbers count the number of objects in all GC heaps, they refer to
all running threads, not only to the current thread. (The current thread
would be the thread that calls ``dumpNumberOfInstances``.) This might
change in later versions.
Garbage collector options
-------------------------
You can choose which garbage collector to use when compiling source code,
you can pass ``--gc:`` on the compile command with the choosed garbage collector.
- ``--gc:refc`` Deferred `reference counting <https://en.wikipedia.org/wiki/Reference_counting>`_ with cycle detection, `thread local heap <https://en.wikipedia.org/wiki/Heap_(programming)>`_, default.
- ``--gc:markAndSweep`` `Mark-And-Sweep <https://en.wikipedia.org/wiki/Tracing_garbage_collection#Copying_vs._mark-and-sweep_vs._mark-and-don't-sweep>`_ based garbage collector, `thread local heap <https://en.wikipedia.org/wiki/Heap_(programming)>`_.
- ``--gc:boehm`` `Boehm <https://en.wikipedia.org/wiki/Boehm_garbage_collector>`_ based garbage collector, `stop-the-world <https://en.wikipedia.org/wiki/Tracing_garbage_collection#Stop-the-world_vs._incremental_vs._concurrent>`_, `shared heap <https://en.wikipedia.org/wiki/Heap_(programming)>`_.
- ``--gc:go`` Go lang like garbage collector, `stop-the-world <https://en.wikipedia.org/wiki/Tracing_garbage_collection#Stop-the-world_vs._incremental_vs._concurrent>`_, `shared heap <https://en.wikipedia.org/wiki/Heap_(programming)>`_.
- ``--gc:regions`` `Stack <https://en.wikipedia.org/wiki/Memory_management#Stack_allocation>`_ based garbage collector.
- ``--gc:none`` No garbage collector.
The same Nim code can compile to use any of the garbage collectors,
the Nim syntax mostly wont change from one garbage collector to another.
No garbage collector is used for `JavaScript and NodeJS <https://nim-lang.github.io/Nim/backends.html#backends-the-javascript-target>`_ compilation targets.
`NimScript <https://nim-lang.github.io/Nim/nims.html>`_ target uses Nim VM garbage collector.
If you are new to Nim and just starting, the default garbage collector is balanced to fit most common use cases.

View File

@@ -450,9 +450,6 @@ Miscellaneous
* `logging <logging.html>`_
This module implements a simple logger.
* `quitprocs <quitprocs>`_
Better implementation of ``system.addQuitProc``.
* `segfaults <segfaults.html>`_
Turns access violations or segfaults into a ``NilAccessError`` exception.

View File

@@ -3508,8 +3508,8 @@ for details on how to change this behavior.
Anonymous Procs
---------------
Procs can also be treated as expressions, in which case it's allowed to omit
the proc's name.
Unnamed procedures can be used as lambda expressions to pass into other
procedures:
.. code-block:: nim
var cities = @["Frankfurt", "Tokyo", "New York", "Kyiv"]
@@ -3519,7 +3519,9 @@ the proc's name.
Procs as expressions can appear both as nested procs and inside top level
executable code.
executable code. The `sugar <sugar.html>`_ module contains the `=>` macro
which enables a more succinct syntax for anonymous procedures resembling
lambdas as they are in languages like JavaScript, C#, etc.
Func
@@ -3691,7 +3693,7 @@ type.
method eval(e: Expression): int {.base.} =
# override this base method
quit "to override!"
raise newException(CatchableError, "Method without implementation override")
method eval(e: Literal): int = return e.x
@@ -6219,6 +6221,25 @@ but are used to override the settings temporarily. Example:
# ... some code ...
{.pop.} # restore old settings
`push/pop`:idx: can switch on/off some standard library pragmas, example:
.. code-block:: nim
{.push inline.}
proc thisIsInlined(): int = 42
func willBeInlined(): float = 42.0
{.pop.}
proc notInlined(): int = 9
{.push discardable, boundChecks: off, compileTime, noSideEffect, experimental.}
template example(): string = "https://nim-lang.org"
{.pop.}
{.push deprecated, hint[LineTooLong]: off, used, stackTrace: off.}
proc sample(): bool = true
{.pop.}
For third party pragmas it depends on its implementation, but uses the same syntax.
register pragma
---------------

View File

@@ -142,15 +142,6 @@ comments can also be nested.
]#
]#
You can also use the `discard statement <#procedures-discard-statement>`_ together with *long string
literals* to create block comments:
.. code-block:: nim
:test: "nim c $1"
discard """ You can have any Nim code text commented
out inside this with no indentation restrictions.
yes("May I ask a pointless question?") """
Numbers
-------

View File

@@ -169,6 +169,10 @@ proc bundleNimsuggest(args: string) =
proc buildVccTool(args: string) =
nimCompileFold("Compile Vcc", "tools/vccexe/vccexe.nim ", options = args)
proc bundleNimpretty(args: string) =
nimCompileFold("Compile nimpretty", "nimpretty/nimpretty.nim",
options = "-d:release " & args)
proc bundleWinTools(args: string) =
nimCompile("tools/finish.nim", outputDir = "", options = args)
@@ -185,6 +189,7 @@ proc bundleWinTools(args: string) =
proc zip(latest: bool; args: string) =
bundleNimbleExe(latest, args)
bundleNimsuggest(args)
bundleNimpretty(args)
bundleWinTools(args)
nimexec("cc -r $2 --var:version=$1 --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" %
[VersionAsString, compileNimInst])
@@ -214,8 +219,7 @@ proc buildTools(args: string = "") =
nimCompileFold("Compile nimgrep", "tools/nimgrep.nim",
options = "-d:release " & args)
when defined(windows): buildVccTool(args)
nimCompileFold("Compile nimpretty", "nimpretty/nimpretty.nim",
options = "-d:release " & args)
bundleNimpretty(args)
nimCompileFold("Compile nimfind", "tools/nimfind.nim",
options = "-d:release " & args)
nimCompileFold("Compile testament", "testament/testament.nim",
@@ -316,8 +320,8 @@ proc boot(args: string) =
# 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, smartNimcache]
exec "$# jsonscript $# --nimcache:$# compiler" / "nim.nim" %
[nimi, args, smartNimcache]
if sameFileContent(output, i.thVersion):
copyExe(output, finalDest)

View File

@@ -121,13 +121,13 @@ type
type
NimIdent* {.deprecated.} = object of RootObj
## represents a Nim identifier in the AST. **Note**: This is only
## Represents a Nim identifier in the AST. **Note**: This is only
## rarely useful, for identifier construction from a string
## use ``ident"abc"``.
NimSymObj = object # hidden
NimSym* {.deprecated.} = ref NimSymObj
## represents a Nim *symbol* in the compiler; a *symbol* is a looked-up
## Represents a Nim *symbol* in the compiler; a *symbol* is a looked-up
## *ident*.
@@ -141,45 +141,46 @@ const
proc `!`*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect, deprecated:
"Deprecated since version 0.18.0: Use 'ident' or 'newIdentNode' instead.".}
## constructs an identifier from the string `s`
## Constructs an identifier from the string `s`.
proc toNimIdent*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect, deprecated:
"Deprecated since version 0.18.0: Use 'ident' or 'newIdentNode' instead.".}
## constructs an identifier from the string `s`
## Constructs an identifier from the string `s`.
proc `==`*(a, b: NimIdent): bool {.magic: "EqIdent", noSideEffect, deprecated:
"Deprecated since version 0.18.1; Use '==' on 'NimNode' instead.".}
## compares two Nim identifiers
## Compares two Nim identifiers.
proc `==`*(a, b: NimNode): bool {.magic: "EqNimrodNode", noSideEffect.}
## compares two Nim nodes
## Compare two Nim nodes. Return true if nodes are structurally
## equivalent. This means two independently created nodes can be equal.
proc `==`*(a, b: NimSym): bool {.magic: "EqNimrodNode", noSideEffect, deprecated:
"Deprecated since version 0.18.1; Use '==(NimNode, NimNode)' instead.".}
## compares two Nim symbols
## Compares two Nim symbols.
{.pop.}
proc sameType*(a, b: NimNode): bool {.magic: "SameNodeType", noSideEffect.} =
## compares two Nim nodes' types. Return true if the types are the same,
## Compares two Nim nodes' types. Return true if the types are the same,
## eg. true when comparing alias with original type.
discard
proc len*(n: NimNode): int {.magic: "NLen", noSideEffect.}
## returns the number of children of `n`.
## Returns the number of children of `n`.
proc `[]`*(n: NimNode, i: int): NimNode {.magic: "NChild", noSideEffect.}
## get `n`'s `i`'th child.
## Get `n`'s `i`'th child.
proc `[]`*(n: NimNode, i: BackwardsIndex): NimNode = n[n.len - i.int]
## get `n`'s `i`'th child.
## Get `n`'s `i`'th child.
template `^^`(n: NimNode, i: untyped): untyped =
(when i is BackwardsIndex: n.len - int(i) else: int(i))
proc `[]`*[T, U](n: NimNode, x: HSlice[T, U]): seq[NimNode] =
## slice operation for NimNode.
## returns a seq of child of `n` who inclusive range [n[x.a], n[x.b]].
## Slice operation for NimNode.
## Returns a seq of child of `n` who inclusive range [n[x.a], n[x.b]].
let xa = n ^^ x.a
let L = (n ^^ x.b) - xa + 1
result = newSeq[NimNode](L)
@@ -188,10 +189,10 @@ proc `[]`*[T, U](n: NimNode, x: HSlice[T, U]): seq[NimNode] =
proc `[]=`*(n: NimNode, i: int, child: NimNode) {.magic: "NSetChild",
noSideEffect.}
## set `n`'s `i`'th child to `child`.
## Set `n`'s `i`'th child to `child`.
proc `[]=`*(n: NimNode, i: BackwardsIndex, child: NimNode) =
## set `n`'s `i`'th child to `child`.
## Set `n`'s `i`'th child to `child`.
n[n.len - i.int] = child
template `or`*(x, y: NimNode): NimNode =
@@ -220,10 +221,10 @@ proc add*(father: NimNode, children: varargs[NimNode]): NimNode {.
## Returns the `father` node so that calls can be nested.
proc del*(father: NimNode, idx = 0, n = 1) {.magic: "NDel", noSideEffect.}
## deletes `n` children of `father` starting at index `idx`.
## Deletes `n` children of `father` starting at index `idx`.
proc kind*(n: NimNode): NimNodeKind {.magic: "NKind", noSideEffect.}
## returns the `kind` of the node `n`.
## Returns the `kind` of the node `n`.
proc intVal*(n: NimNode): BiggestInt {.magic: "NIntVal", noSideEffect.}
## Returns an integer value from any integer literal or enum field symbol.
@@ -244,17 +245,20 @@ proc getImpl*(s: NimSym): NimNode {.magic: "GetImpl", noSideEffect, deprecated:
when defined(nimSymKind):
proc symKind*(symbol: NimNode): NimSymKind {.magic: "NSymKind", noSideEffect.}
proc getImpl*(symbol: NimNode): NimNode {.magic: "GetImpl", noSideEffect.}
## Returns a copy of the declaration of a symbol or `nil`.
proc strVal*(n: NimNode): string {.magic: "NStrVal", noSideEffect.}
## retrieve the implementation of `symbol`. `symbol` can be a
## routine or a const.
## Returns the string value of an identifier, symbol, comment, or string literal.
##
## See also:
## * `strVal= proc<#strVal=,NimNode,string>`_ for setting the string value.
proc `$`*(i: NimIdent): string {.magic: "NStrVal", noSideEffect, deprecated:
"Deprecated since version 0.18.1; Use 'strVal' instead.".}
## converts a Nim identifier to a string
## Converts a Nim identifier to a string.
proc `$`*(s: NimSym): string {.magic: "NStrVal", noSideEffect, deprecated:
"Deprecated since version 0.18.1; Use 'strVal' instead.".}
## converts a Nim symbol to a string
## Converts a Nim symbol to a string.
else: # bootstrapping substitute
proc getImpl*(symbol: NimNode): NimNode =
@@ -278,22 +282,28 @@ else: # bootstrapping substitute
when defined(nimSymImplTransform):
proc getImplTransformed*(symbol: NimNode): NimNode {.magic: "GetImplTransf", noSideEffect.}
## for a typed proc returns the AST after transformation pass
## For a typed proc returns the AST after transformation pass.
when defined(nimHasSymOwnerInMacro):
proc owner*(sym: NimNode): NimNode {.magic: "SymOwner", noSideEffect.}
## accepts node of kind nnkSym and returns its owner's symbol.
## result is also mnde of kind nnkSym if owner exists otherwise
## nnkNilLit is returned
## Accepts a node of kind `nnkSym` and returns its owner's symbol.
## The meaning of 'owner' depends on `sym`'s `NimSymKind` and declaration
## context. For top level declarations this is an `nskModule` symbol,
## for proc local variables an `nskProc` symbol, for enum/object fields an
## `nskType` symbol, etc. For symbols without an owner, `nil` is returned.
##
## See also:
## * `symKind proc<#symKind,NimNode>`_ to get the kind of a symbol
## * `getImpl proc<#getImpl,NimNode>`_ to get the declaration of a symbol
when defined(nimHasInstantiationOfInMacro):
proc isInstantiationOf*(instanceProcSym, genProcSym: NimNode): bool {.magic: "SymIsInstantiationOf", noSideEffect.}
## check if proc symbol is instance of the generic proc symbol
## useful to check proc symbols against generic symbols
## returned by `bindSym`
## Checks if a proc symbol is an instance of the generic proc symbol.
## Useful to check proc symbols against generic symbols
## returned by `bindSym`.
proc getType*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
## with 'getType' you can access the node's `type`:idx:. A Nim type is
## With 'getType' you can access the node's `type`:idx:. A Nim type is
## mapped to a Nim AST too, so it's slightly confusing but it means the same
## API can be used to traverse types. Recursive types are flattened for you
## so there is no danger of infinite recursions during traversal. To
@@ -301,10 +311,7 @@ proc getType*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
## kind of type it is, call `typeKind` on getType's result.
proc getType*(n: typedesc): NimNode {.magic: "NGetType", noSideEffect.}
## Returns the Nim type node for given type. This can be used to turn macro
## typedesc parameter into proper NimNode representing type, since typedesc
## are an exception in macro calls - they are not mapped implicitly to
## NimNode like any other arguments.
## Version of ``getType`` which takes a ``typedesc``.
proc typeKind*(n: NimNode): NimTypeKind {.magic: "NGetType", noSideEffect.}
## Returns the type kind of the node 'n' that should represent a type, that
@@ -333,8 +340,8 @@ proc getTypeInst*(n: typedesc): NimNode {.magic: "NGetType", noSideEffect.}
proc getTypeImpl*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.} =
## Returns the `type`:idx: of a node in a form matching the implementation
## of the type. Any intermediate aliases are expanded to arrive at the final
## type implementation. You can instead use ``getImpl`` on a symbol if you
## of the type. Any intermediate aliases are expanded to arrive at the final
## type implementation. You can instead use ``getImpl`` on a symbol if you
## want to find the intermediate aliases.
runnableExamples:
type
@@ -364,7 +371,7 @@ when defined(nimHasSignatureHashInMacro):
proc symBodyHash*(s: NimNode): string {.noSideEffect.} =
## Returns a stable digest for symbols derived not only from type signature
## and owning module, but also implementation body. All procs/varibles used in
## and owning module, but also implementation body. All procs/variables used in
## the implementation of this symbol are hashed recursively as well, including
## magics from system module.
discard
@@ -393,6 +400,14 @@ proc `ident=`*(n: NimNode, val: NimIdent) {.magic: "NSetIdent", noSideEffect, de
# bracket[0] = fake # constructs a mixed array with ints and floats!
proc `strVal=`*(n: NimNode, val: string) {.magic: "NSetStrVal", noSideEffect.}
## Sets the string value of a string literal or comment.
## Setting `strVal` is disallowed for `nnkIdent` and `nnkSym` nodes; a new node
## must be created using `ident` or `bindSym` instead.
##
## See also:
## * `strVal proc<#strVal,NimNode>`_ for getting the string value.
## * `ident proc<#ident,string>`_ for creating an identifier.
## * `bindSym proc<#bindSym%2C%2CBindSymRule>`_ for binding a symbol.
proc newNimNode*(kind: NimNodeKind,
lineInfoFrom: NimNode = nil): NimNode
@@ -407,47 +422,47 @@ proc copyNimNode*(n: NimNode): NimNode {.magic: "NCopyNimNode", noSideEffect.}
proc copyNimTree*(n: NimNode): NimNode {.magic: "NCopyNimTree", noSideEffect.}
proc error*(msg: string, n: NimNode = nil) {.magic: "NError", benign.}
## writes an error message at compile time. The optional ``n: NimNode``
## Writes an error message at compile time. The optional ``n: NimNode``
## parameter is used as the source for file and line number information in
## the compilation error message.
proc warning*(msg: string, n: NimNode = nil) {.magic: "NWarning", benign.}
## writes a warning message at compile time
## Writes a warning message at compile time.
proc hint*(msg: string, n: NimNode = nil) {.magic: "NHint", benign.}
## writes a hint message at compile time
## Writes a hint message at compile time.
proc newStrLitNode*(s: string): NimNode {.compileTime, noSideEffect.} =
## creates a string literal node from `s`
## Creates a string literal node from `s`.
result = newNimNode(nnkStrLit)
result.strVal = s
proc newCommentStmtNode*(s: string): NimNode {.compileTime, noSideEffect.} =
## creates a comment statement node
## Creates a comment statement node.
result = newNimNode(nnkCommentStmt)
result.strVal = s
proc newIntLitNode*(i: BiggestInt): NimNode {.compileTime.} =
## creates a int literal node from `i`
## Creates an int literal node from `i`.
result = newNimNode(nnkIntLit)
result.intVal = i
proc newFloatLitNode*(f: BiggestFloat): NimNode {.compileTime.} =
## creates a float literal node from `f`
## Creates a float literal node from `f`.
result = newNimNode(nnkFloatLit)
result.floatVal = f
{.push warnings: off.}
proc newIdentNode*(i: NimIdent): NimNode {.compileTime, deprecated.} =
## creates an identifier node from `i`
## Creates an identifier node from `i`.
result = newNimNode(nnkIdent)
result.ident = i
{.pop.}
proc newIdentNode*(i: string): NimNode {.magic: "StrToIdent", noSideEffect, compilerproc.}
## creates an identifier node from `i`. It is simply an alias for
## Creates an identifier node from `i`. It is simply an alias for
## ``ident(string)``. Use that, it's shorter.
@@ -463,35 +478,35 @@ type
proc bindSym*(ident: string | NimNode, rule: BindSymRule = brClosed): NimNode {.
magic: "NBindSym", noSideEffect.}
## creates a node that binds `ident` to a symbol node. The bound symbol
## Ceates a node that binds `ident` to a symbol node. The bound symbol
## may be an overloaded symbol.
## if `ident` is a NimNode, it must have nkIdent kind.
## If ``rule == brClosed`` either an ``nkClosedSymChoice`` tree is
## returned or ``nkSym`` if the symbol is not ambiguous.
## If ``rule == brOpen`` either an ``nkOpenSymChoice`` tree is
## returned or ``nkSym`` if the symbol is not ambiguous.
## If ``rule == brForceOpen`` always an ``nkOpenSymChoice`` tree is
## if `ident` is a NimNode, it must have ``nnkIdent`` kind.
## If ``rule == brClosed`` either an ``nnkClosedSymChoice`` tree is
## returned or ``nnkSym`` if the symbol is not ambiguous.
## If ``rule == brOpen`` either an ``nnkOpenSymChoice`` tree is
## returned or ``nnkSym`` if the symbol is not ambiguous.
## If ``rule == brForceOpen`` always an ``nnkOpenSymChoice`` tree is
## returned even if the symbol is not ambiguous.
##
## experimental feature:
## use {.experimental: "dynamicBindSym".} to activate it
## if called from template / regular code, `ident` and `rule` must be
## Experimental feature:
## use {.experimental: "dynamicBindSym".} to activate it.
## If called from template / regular code, `ident` and `rule` must be
## constant expression / literal value.
## if called from macros / compile time procs / static blocks,
## If called from macros / compile time procs / static blocks,
## `ident` and `rule` can be VM computed value.
proc genSym*(kind: NimSymKind = nskLet; ident = ""): NimNode {.
magic: "NGenSym", noSideEffect.}
## generates a fresh symbol that is guaranteed to be unique. The symbol
## Generates a fresh symbol that is guaranteed to be unique. The symbol
## needs to occur in a declaration context.
proc callsite*(): NimNode {.magic: "NCallSite", benign, deprecated:
"Deprecated since v0.18.1; use varargs[untyped] in the macro prototype instead".}
## returns the AST of the invocation expression that invoked this macro.
## Returns the AST of the invocation expression that invoked this macro.
proc toStrLit*(n: NimNode): NimNode {.compileTime.} =
## converts the AST `n` to the concrete Nim code and wraps that
## in a string literal node
## Converts the AST `n` to the concrete Nim code and wraps that
## in a string literal node.
return newStrLitNode(repr(n))
type
@@ -500,27 +515,29 @@ type
line*,column*: int
proc `$`*(arg: LineInfo): string =
## Return a string representation in the form `filepath(line, column)`.
# BUG: without `result = `, gives compile error
result = arg.filename & "(" & $arg.line & ", " & $arg.column & ")"
#proc lineinfo*(n: NimNode): LineInfo {.magic: "NLineInfo", noSideEffect.}
## returns the position the node appears in the original source file
## in the form filename(line, col)
# ## returns the position the node appears in the original source file
# ## in the form filename(line, col)
proc getLine(arg: NimNode): int {.magic: "NLineInfo", noSideEffect.}
proc getColumn(arg: NimNode): int {.magic: "NLineInfo", noSideEffect.}
proc getFile(arg: NimNode): string {.magic: "NLineInfo", noSideEffect.}
proc copyLineInfo*(arg: NimNode, info: NimNode) {.magic: "NLineInfo", noSideEffect.}
## copy lineinfo from info node
## Copy lineinfo from ``info``.
proc lineInfoObj*(n: NimNode): LineInfo {.compileTime.} =
## returns ``LineInfo`` of ``n``, using absolute path for ``filename``
## Returns ``LineInfo`` of ``n``, using absolute path for ``filename``.
result.filename = n.getFile
result.line = n.getLine
result.column = n.getColumn
proc lineInfo*(arg: NimNode): string {.compileTime.} =
## Return line info in the form `filepath(line, column)`.
$arg.lineInfoObj
proc internalParseExpr(s: string): NimNode {.
@@ -586,25 +603,25 @@ proc quote*(bl: typed, op = "``"): NimNode {.magic: "QuoteAst", noSideEffect.}
## echo `info` & ": Check failed: " & `expString`
proc expectKind*(n: NimNode, k: NimNodeKind) {.compileTime.} =
## checks that `n` is of kind `k`. If this is not the case,
## Checks that `n` is of kind `k`. If this is not the case,
## compilation aborts with an error message. This is useful for writing
## macros that check the AST that is passed to them.
if n.kind != k: error("Expected a node of kind " & $k & ", got " & $n.kind, n)
proc expectMinLen*(n: NimNode, min: int) {.compileTime.} =
## checks that `n` has at least `min` children. If this is not the case,
## Checks that `n` has at least `min` children. If this is not the case,
## compilation aborts with an error message. This is useful for writing
## macros that check its number of arguments.
if n.len < min: error("macro expects a node with " & $min & " children", n)
proc expectLen*(n: NimNode, len: int) {.compileTime.} =
## checks that `n` has exactly `len` children. If this is not the case,
## Checks that `n` has exactly `len` children. If this is not the case,
## compilation aborts with an error message. This is useful for writing
## macros that check its number of arguments.
if n.len != len: error("macro expects a node with " & $len & " children", n)
proc expectLen*(n: NimNode, min, max: int) {.compileTime.} =
## checks that `n` has a number of children in the range ``min..max``.
## Checks that `n` has a number of children in the range ``min..max``.
## If this is not the case, compilation aborts with an error message.
## This is useful for writing macros that check its number of arguments.
if n.len < min or n.len > max:
@@ -612,13 +629,13 @@ proc expectLen*(n: NimNode, min, max: int) {.compileTime.} =
proc newTree*(kind: NimNodeKind,
children: varargs[NimNode]): NimNode {.compileTime.} =
## produces a new node with children.
## Produces a new node with children.
result = newNimNode(kind)
result.add(children)
proc newCall*(theProc: NimNode,
args: varargs[NimNode]): NimNode {.compileTime.} =
## produces a new call node. `theProc` is the proc that is called with
## Produces a new call node. `theProc` is the proc that is called with
## the arguments ``args[0..]``.
result = newNimNode(nnkCall)
result.add(theProc)
@@ -628,7 +645,7 @@ proc newCall*(theProc: NimNode,
proc newCall*(theProc: NimIdent, args: varargs[NimNode]): NimNode {.compileTime, deprecated:
"Deprecated since v0.18.1; use 'newCall(string, ...)' or 'newCall(NimNode, ...)' instead".} =
## produces a new call node. `theProc` is the proc that is called with
## Produces a new call node. `theProc` is the proc that is called with
## the arguments ``args[0..]``.
result = newNimNode(nnkCall)
result.add(newIdentNode(theProc))
@@ -638,91 +655,91 @@ proc newCall*(theProc: NimIdent, args: varargs[NimNode]): NimNode {.compileTime,
proc newCall*(theProc: string,
args: varargs[NimNode]): NimNode {.compileTime.} =
## produces a new call node. `theProc` is the proc that is called with
## Produces a new call node. `theProc` is the proc that is called with
## the arguments ``args[0..]``.
result = newNimNode(nnkCall)
result.add(newIdentNode(theProc))
result.add(args)
proc newLit*(c: char): NimNode {.compileTime.} =
## produces a new character literal node.
## Produces a new character literal node.
result = newNimNode(nnkCharLit)
result.intVal = ord(c)
proc newLit*(i: int): NimNode {.compileTime.} =
## produces a new integer literal node.
## Produces a new integer literal node.
result = newNimNode(nnkIntLit)
result.intVal = i
proc newLit*(i: int8): NimNode {.compileTime.} =
## produces a new integer literal node.
## Produces a new integer literal node.
result = newNimNode(nnkInt8Lit)
result.intVal = i
proc newLit*(i: int16): NimNode {.compileTime.} =
## produces a new integer literal node.
## Produces a new integer literal node.
result = newNimNode(nnkInt16Lit)
result.intVal = i
proc newLit*(i: int32): NimNode {.compileTime.} =
## produces a new integer literal node.
## Produces a new integer literal node.
result = newNimNode(nnkInt32Lit)
result.intVal = i
proc newLit*(i: int64): NimNode {.compileTime.} =
## produces a new integer literal node.
## Produces a new integer literal node.
result = newNimNode(nnkInt64Lit)
result.intVal = i
proc newLit*(i: uint): NimNode {.compileTime.} =
## produces a new unsigned integer literal node.
## Produces a new unsigned integer literal node.
result = newNimNode(nnkUIntLit)
result.intVal = BiggestInt(i)
proc newLit*(i: uint8): NimNode {.compileTime.} =
## produces a new unsigned integer literal node.
## Produces a new unsigned integer literal node.
result = newNimNode(nnkUInt8Lit)
result.intVal = BiggestInt(i)
proc newLit*(i: uint16): NimNode {.compileTime.} =
## produces a new unsigned integer literal node.
## Produces a new unsigned integer literal node.
result = newNimNode(nnkUInt16Lit)
result.intVal = BiggestInt(i)
proc newLit*(i: uint32): NimNode {.compileTime.} =
## produces a new unsigned integer literal node.
## Produces a new unsigned integer literal node.
result = newNimNode(nnkUInt32Lit)
result.intVal = BiggestInt(i)
proc newLit*(i: uint64): NimNode {.compileTime.} =
## produces a new unsigned integer literal node.
## Produces a new unsigned integer literal node.
result = newNimNode(nnkUInt64Lit)
result.intVal = BiggestInt(i)
proc newLit*(b: bool): NimNode {.compileTime.} =
## produces a new boolean literal node.
## Produces a new boolean literal node.
result = if b: bindSym"true" else: bindSym"false"
when false:
# the float type is not really a distinct type as described in https://github.com/nim-lang/Nim/issues/5875
proc newLit*(f: float): NimNode {.compileTime.} =
## produces a new float literal node.
## Produces a new float literal node.
result = newNimNode(nnkFloatLit)
result.floatVal = f
proc newLit*(f: float32): NimNode {.compileTime.} =
## produces a new float literal node.
## Produces a new float literal node.
result = newNimNode(nnkFloat32Lit)
result.floatVal = f
proc newLit*(f: float64): NimNode {.compileTime.} =
## produces a new float literal node.
## Produces a new float literal node.
result = newNimNode(nnkFloat64Lit)
result.floatVal = f
when declared(float128):
proc newLit*(f: float128): NimNode {.compileTime.} =
## produces a new float literal node.
## Produces a new float literal node.
result = newNimNode(nnkFloat128Lit)
result.floatVal = f
@@ -771,12 +788,12 @@ proc newLit*(arg: tuple): NimNode {.compileTime.} =
result.add nnkExprColonExpr.newTree(newIdentNode(a), newLit(b))
proc newLit*(s: string): NimNode {.compileTime.} =
## produces a new string literal node.
## Produces a new string literal node.
result = newNimNode(nnkStrLit)
result.strVal = s
proc nestList*(op: NimNode; pack: NimNode): NimNode {.compileTime.} =
## nests the list `pack` into a tree of call expressions:
## Nests the list `pack` into a tree of call expressions:
## ``[a, b, c]`` is transformed into ``op(a, op(c, d))``.
## This is also known as fold expression.
if pack.len < 1:
@@ -786,7 +803,7 @@ proc nestList*(op: NimNode; pack: NimNode): NimNode {.compileTime.} =
result = newCall(op, pack[i], result)
proc nestList*(op: NimNode; pack: NimNode; init: NimNode): NimNode {.compileTime.} =
## nests the list `pack` into a tree of call expressions:
## Nests the list `pack` into a tree of call expressions:
## ``[a, b, c]`` is transformed into ``op(a, op(c, d))``.
## This is also known as fold expression.
result = init
@@ -973,37 +990,37 @@ macro dumpLispImm*(s: untyped): untyped {.deprecated.} = echo s.lispRepr
## Deprecated. Use `dumpLisp` instead.
proc newEmptyNode*(): NimNode {.compileTime, noSideEffect.} =
## Create a new empty node
## Create a new empty node.
result = newNimNode(nnkEmpty)
proc newStmtList*(stmts: varargs[NimNode]): NimNode {.compileTime.}=
## Create a new statement list
## Create a new statement list.
result = newNimNode(nnkStmtList).add(stmts)
proc newPar*(exprs: varargs[NimNode]): NimNode {.compileTime.}=
## Create a new parentheses-enclosed expression
## Create a new parentheses-enclosed expression.
newNimNode(nnkPar).add(exprs)
proc newBlockStmt*(label, body: NimNode): NimNode {.compileTime.} =
## Create a new block statement with label
## Create a new block statement with label.
return newNimNode(nnkBlockStmt).add(label, body)
proc newBlockStmt*(body: NimNode): NimNode {.compileTime.} =
## Create a new block: stmt
## Create a new block: stmt.
return newNimNode(nnkBlockStmt).add(newEmptyNode(), body)
proc newVarStmt*(name, value: NimNode): NimNode {.compileTime.} =
## Create a new var stmt
## Create a new var stmt.
return newNimNode(nnkVarSection).add(
newNimNode(nnkIdentDefs).add(name, newNimNode(nnkEmpty), value))
proc newLetStmt*(name, value: NimNode): NimNode {.compileTime.} =
## Create a new let stmt
## Create a new let stmt.
return newNimNode(nnkLetSection).add(
newNimNode(nnkIdentDefs).add(name, newNimNode(nnkEmpty), value))
proc newConstStmt*(name, value: NimNode): NimNode {.compileTime.} =
## Create a new const stmt
## Create a new const stmt.
newNimNode(nnkConstSection).add(
newNimNode(nnkConstDef).add(name, newNimNode(nnkEmpty), value))
@@ -1011,13 +1028,13 @@ proc newAssignment*(lhs, rhs: NimNode): NimNode {.compileTime.} =
return newNimNode(nnkAsgn).add(lhs, rhs)
proc newDotExpr*(a, b: NimNode): NimNode {.compileTime.} =
## Create new dot expression
## a.dot(b) -> `a.b`
## Create new dot expression.
## a.dot(b) -> `a.b`
return newNimNode(nnkDotExpr).add(a, b)
proc newColonExpr*(a, b: NimNode): NimNode {.compileTime.} =
## Create new colon expression
## newColonExpr(a, b) -> `a: b`
## Create new colon expression.
## newColonExpr(a, b) -> `a: b`
newNimNode(nnkExprColonExpr).add(a, b)
proc newIdentDefs*(name, kind: NimNode;
@@ -1053,11 +1070,11 @@ proc newIdentDefs*(name, kind: NimNode;
newNimNode(nnkIdentDefs).add(name, kind, default)
proc newNilLit*(): NimNode {.compileTime.} =
## New nil literal shortcut
## New nil literal shortcut.
result = newNimNode(nnkNilLit)
proc last*(node: NimNode): NimNode {.compileTime.} = node[node.len-1]
## Return the last item in nodes children. Same as `node[^1]`
## Return the last item in nodes children. Same as `node[^1]`.
const
@@ -1068,7 +1085,7 @@ const
nnkCallStrLit, nnkHiddenCallConv}
proc expectKind*(n: NimNode; k: set[NimNodeKind]) {.compileTime.} =
## checks that `n` is of kind `k`. If this is not the case,
## Checks that `n` is of kind `k`. If this is not the case,
## compilation aborts with an error message. This is useful for writing
## macros that check the AST that is passed to them.
if n.kind notin k: error("Expected one of " & $k & ", got " & $n.kind, n)
@@ -1078,7 +1095,7 @@ proc newProc*(name = newEmptyNode();
body: NimNode = newStmtList();
procType = nnkProcDef;
pragmas: NimNode = newEmptyNode()): NimNode {.compileTime.} =
## shortcut for creating a new proc
## Shortcut for creating a new proc.
##
## The ``params`` array must start with the return type of the proc,
## followed by a list of IdentDefs which specify the params.
@@ -1156,7 +1173,7 @@ proc newEnum*(name: NimNode, fields: openArray[NimNode],
return typeSect
proc copyChildrenTo*(src, dest: NimNode) {.compileTime.}=
## Copy all children from `src` to `dest`
## Copy all children from `src` to `dest`.
for i in 0 ..< src.len:
dest.add src[i].copyNimTree
@@ -1189,15 +1206,15 @@ proc `params=`* (someProc: NimNode; params: NimNode) {.compileTime.}=
someProc[3] = params
proc pragma*(someProc: NimNode): NimNode {.compileTime.} =
## Get the pragma of a proc type
## These will be expanded
## Get the pragma of a proc type.
## These will be expanded.
if someProc.kind == nnkProcTy:
result = someProc[1]
else:
someProc.expectRoutine
result = someProc[4]
proc `pragma=`*(someProc: NimNode; val: NimNode) {.compileTime.}=
## Set the pragma of a proc type
## Set the pragma of a proc type.
expectKind(val, {nnkEmpty, nnkPragma})
if someProc.kind == nnkProcTy:
someProc[1] = val
@@ -1206,7 +1223,7 @@ proc `pragma=`*(someProc: NimNode; val: NimNode) {.compileTime.}=
someProc[4] = val
proc addPragma*(someProc, pragma: NimNode) {.compileTime.} =
## Adds pragma to routine definition
## Adds pragma to routine definition.
someProc.expectKind(RoutineNodes + {nnkProcTy})
var pragmaNode = someProc.pragma
if pragmaNode.isNil or pragmaNode.kind == nnkEmpty:
@@ -1242,7 +1259,7 @@ proc `body=`*(someProc: NimNode, val: NimNode) {.compileTime.} =
proc basename*(a: NimNode): NimNode {.compileTime, benign.}
proc `$`*(node: NimNode): string {.compileTime.} =
## Get the string of an identifier node
## Get the string of an identifier node.
case node.kind
of nnkPostfix:
result = node.basename.strVal & "*"
@@ -1256,7 +1273,7 @@ proc `$`*(node: NimNode): string {.compileTime.} =
badNodeKind node, "$"
proc ident*(name: string): NimNode {.magic: "StrToIdent", noSideEffect.}
## Create a new ident node from a string
## Create a new ident node from a string.
iterator items*(n: NimNode): NimNode {.inline.} =
## Iterates over the children of the NimNode ``n``.
@@ -1288,22 +1305,22 @@ template findChild*(n: NimNode; cond: untyped): NimNode {.dirty.} =
res
proc insert*(a: NimNode; pos: int; b: NimNode) {.compileTime.} =
## Insert node B into A at pos
## Insert node ``b`` into node ``a`` at ``pos``.
if len(a)-1 < pos:
## add some empty nodes first
# add some empty nodes first
for i in len(a)-1..pos-2:
a.add newEmptyNode()
a.add b
else:
## push the last item onto the list again
## and shift each item down to pos up one
# push the last item onto the list again
# and shift each item down to pos up one
a.add(a[a.len-1])
for i in countdown(len(a) - 3, pos):
a[i + 1] = a[i]
a[pos] = b
proc basename*(a: NimNode): NimNode =
## Pull an identifier from prefix/postfix expressions
## Pull an identifier from prefix/postfix expressions.
case a.kind
of nnkIdent: return a
of nnkPostfix, nnkPrefix: return a[1]
@@ -1347,7 +1364,7 @@ proc unpackInfix*(node: NimNode): tuple[left: NimNode; op: string;
result = (node[1], $node[0], node[2])
proc copy*(node: NimNode): NimNode {.compileTime.} =
## An alias for copyNimTree().
## An alias for `copyNimTree<#copyNimTree,NimNode>`_.
return node.copyNimTree()
when defined(nimVmEqIdent):
@@ -1388,7 +1405,7 @@ else:
proc eqIdent*(a, b: string): bool = cmpIgnoreStyle(a, b) == 0
## Check if two idents are identical.
## Check if two idents are equal.
proc eqIdent*(node: NimNode; s: string): bool {.compileTime.} =
## Check if node is some identifier node (``nnkIdent``, ``nnkSym``, etc.)
@@ -1403,7 +1420,7 @@ else:
result = false
proc hasArgOfName*(params: NimNode; name: string): bool {.compileTime.}=
## Search nnkFormalParams for an argument.
## Search ``nnkFormalParams`` for an argument.
expectKind(params, nnkFormalParams)
for i in 1 ..< params.len:
template node: untyped = params[i]
@@ -1411,7 +1428,7 @@ proc hasArgOfName*(params: NimNode; name: string): bool {.compileTime.}=
return true
proc addIdentIfAbsent*(dest: NimNode, ident: string) {.compileTime.} =
## Add ident to dest if it is not present. This is intended for use
## Add ``ident`` to ``dest`` if it is not present. This is intended for use
## with pragmas.
for node in dest.children:
case node.kind
@@ -1585,7 +1602,7 @@ macro getCustomPragmaVal*(n: typed, cp: typed{nkSym}): untyped =
when not defined(booting):
template emit*(e: static[string]): untyped {.deprecated.} =
## accepts a single string argument and treats it as nim code
## Accepts a single string argument and treats it as nim code
## that should be inserted verbatim in the program
## Example:
##

View File

@@ -391,7 +391,7 @@ proc setVal[K, V](table: var PConcTable[K, V], key: int, val: int,
# Done spinning for a new slot
var oldVal = atomic_load_n(table[idx].value.addr, ATOMIC_RELAXED)
if val == oldVal:
#echo("this val is alredy in the slot")
#echo("this val is already in the slot")
return oldVal
nextTable = atomic_load_n(table.next.addr, ATOMIC_SEQ_CST)
if nextTable == nil and

View File

@@ -42,7 +42,7 @@ type
## the option was given a value
proc initOptParser*(cmdline: seq[string]): OptParser {.rtl.} =
## Initalizes option parses with cmdline. cmdline should not contain
## Initializes option parses with cmdline. cmdline should not contain
## argument 0 - program name.
## If cmdline.len == 0 default to current command line arguments.
result.remainingShortOptions = ""

View File

@@ -275,9 +275,9 @@ proc createDiffs(dataA, dataB: DiffData): seq[Item] =
proc diffInt*(arrayA, arrayB: openArray[int]): seq[Item] =
## Find the difference in 2 arrays of integers.
##
## ``arrayA`` A-version of the numbers (usualy the old one)
## ``arrayA`` A-version of the numbers (usually the old one)
##
## ``arrayB`` B-version of the numbers (usualy the new one)
## ``arrayB`` B-version of the numbers (usually the new one)
##
## Returns a sequence of Items that describe the differences.
@@ -301,7 +301,7 @@ proc diffText*(textA, textB: string): seq[Item] =
##
## The algorithm itself is comparing 2 arrays of numbers so when comparing 2 text documents
## each line is converted into a (hash) number. This hash-value is computed by storing all
## textlines into a common hashtable so i can find dublicates in there, and generating a
## textlines into a common hashtable so i can find duplicates in there, and generating a
## new number each time a new textline is inserted.
##
## ``textA`` A-version of the text (usually the old one)

View File

@@ -272,7 +272,7 @@ iterator fastRows*(db: var DbConn, query: SqlQuery,
## if you require **ALL** the rows.
##
## Breaking the fastRows() iterator during a loop may cause a driver error
## for subsequenct queries
## for subsequent queries
##
## Rows are retrieved from the server at each iteration.
var
@@ -303,7 +303,7 @@ iterator instantRows*(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): InstantRow
{.tags: [ReadDbEffect, WriteDbEffect].} =
## Same as fastRows but returns a handle that can be used to get column text
## on demand using []. Returned handle is valid only within the interator body.
## on demand using []. Returned handle is valid only within the iterator body.
var
rowRes: Row = @[]
sz: TSqlInteger = 0

View File

@@ -182,7 +182,7 @@ proc setRow(res: PPGresult, r: var Row, line, cols: int32) =
iterator fastRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## executes the query and iterates over the result dataset. This is very
## fast, but potenially dangerous: If the for-loop-body executes another
## fast, but potentially dangerous: If the for-loop-body executes another
## query, the results can be undefined. For Postgres it is safe though.
var res = setupQuery(db, query, args)
var L = pqnfields(res)

View File

@@ -94,6 +94,18 @@
##
## db.close()
##
##
## Note
## ====
## This module does not implement any ORM features such as mapping the types from the schema.
## Instead, a ``seq[string]`` is returned for each row.
##
## The reasoning is as follows:
## 1. it's close to what many DBs offer natively (char**)
## 2. it hides the number of types that the DB supports
## (int? int64? decimal up to 10 places? geo coords?)
## 3. it's convenient when all you do is to forward the data to somewhere else (echo, log, put the data into a new query)
##
## See also
## ========
##

View File

@@ -137,7 +137,7 @@ type
## into PCRE flags. These include ``NEVER_UTF``, ``ANCHORED``,
## ``DOLLAR_ENDONLY``, ``FIRSTLINE``, ``NO_AUTO_CAPTURE``,
## ``JAVASCRIPT_COMPAT``, ``U``, ``NO_STUDY``. In other PCRE wrappers, you
## will need to pass these as seperate flags to PCRE.
## will need to pass these as separate flags to PCRE.
pattern*: string ## not nil
pcreObj: ptr pcre.Pcre ## not nil
pcreExtra: ptr pcre.ExtraData ## nil

View File

@@ -498,7 +498,7 @@ macro bindMethod*(procedure: typed): auto =
this = newIdentNode("this")
# construct the `this` parameter:
thisQuote = quote do:
var `this` {.nodecl, importc.} : `thisType`
var `this` {.nodecl, importc: "this".}: `thisType`
call = newNimNode(nnkCall).add(rawProc[0], thisQuote[0][0][0])
# construct the procedure call inside the method
if args.len > 2:

View File

@@ -101,7 +101,7 @@ proc initRstGenerator*(g: var RstGenerator, target: OutputTarget,
## index hyperlinks to the file, but you can pass an empty string here if you
## are parsing a stream in memory. If `filename` ends with the ``.nim``
## extension, the title for the document will be set by default to ``Module
## filename``. This default title can be overriden by the embedded rst, but
## filename``. This default title can be overridden by the embedded rst, but
## it helps to prettify the generated index if no title is found.
##
## The ``RstParseOptions``, ``FindFileHandler`` and ``MsgHandler`` types
@@ -350,7 +350,7 @@ proc hash(n: PRstNode): int =
proc renderIndexTerm*(d: PDoc, n: PRstNode, result: var string) =
## Renders the string decorated within \`foobar\`\:idx\: markers.
##
## Additionally adds the encosed text to the index as a term. Since we are
## Additionally adds the enclosed text to the index as a term. Since we are
## interested in different instances of the same term to have different
## entries, a table is used to keep track of the amount of times a term has
## previously appeared to give a different identifier value for each.

View File

@@ -29,7 +29,7 @@
# Dead code elimination ensures that we don't accidentally generate #includes
# for files that might not exist on a specific platform! The user will get an
# error only if they actualy try to use the missing declaration
# error only if they actually try to use the missing declaration
{.deadCodeElim: on.} # dce option deprecated
when defined(nimHasStyleChecks):

View File

@@ -83,7 +83,7 @@ proc sendSignal*(pid: Pid, signal: int) =
proc mkstemp*(prefix: string): (string, File) =
## Creates a unique temporary file from a prefix string. Adds a six chars suffix.
## The file is created with perms 0600.
## Returs the filename and a file opened in r/w mode.
## Returns the filename and a file opened in r/w mode.
var tmpl = cstring(prefix & "XXXXXX")
let fd = mkstemp(tmpl)
var f: File

View File

@@ -172,8 +172,8 @@ proc binarySearch*[T, K](a: openArray[T], key: K,
## ``cmp`` is the comparator function to use, the expected return values are
## the same as that of system.cmp.
runnableExamples:
assert binarySearch(["a","b","c","d"], "d", system.cmp[string]) == 3
assert binarySearch(["a","b","d","c"], "d", system.cmp[string]) == 2
assert binarySearch(["a", "b", "c", "d"], "d", system.cmp[string]) == 3
assert binarySearch(["a", "b", "d", "c"], "d", system.cmp[string]) == 2
if a.len == 0:
return -1
@@ -228,7 +228,8 @@ proc smartBinarySearch*[T](a: openArray[T], key: T): int {.deprecated:
const
onlySafeCode = true
proc lowerBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.closure.}): int =
proc lowerBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.
closure.}): int =
## Returns a position to the first element in the ``a`` that is greater than
## ``key``, or last if no such element is found.
## In other words if you have a sorted sequence and you call
@@ -244,12 +245,12 @@ proc lowerBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.clo
## * `upperBound proc<#upperBound,openArray[T],K,proc(T,K)>`_ sorted by ``cmp`` in the specified order
## * `upperBound proc<#upperBound,openArray[T],T>`_
runnableExamples:
var arr = @[1,2,3,5,6,7,8,9]
var arr = @[1, 2, 3, 5, 6, 7, 8, 9]
assert arr.lowerBound(3, system.cmp[int]) == 2
assert arr.lowerBound(4, system.cmp[int]) == 3
assert arr.lowerBound(5, system.cmp[int]) == 3
arr.insert(4, arr.lowerBound(4, system.cmp[int]))
assert arr == [1,2,3,4,5,6,7,8,9]
assert arr == [1, 2, 3, 4, 5, 6, 7, 8, 9]
result = a.low
var count = a.high - a.low + 1
var step, pos: int
@@ -275,7 +276,8 @@ proc lowerBound*[T](a: openArray[T], key: T): int = lowerBound(a, key, cmp[T])
## * `upperBound proc<#upperBound,openArray[T],K,proc(T,K)>`_ sorted by ``cmp`` in the specified order
## * `upperBound proc<#upperBound,openArray[T],T>`_
proc upperBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.closure.}): int =
proc upperBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.
closure.}): int =
## Returns a position to the first element in the ``a`` that is not less
## (i.e. greater or equal to) than ``key``, or last if no such element is found.
## In other words if you have a sorted sequence and you call
@@ -291,12 +293,12 @@ proc upperBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.clo
## * `lowerBound proc<#lowerBound,openArray[T],K,proc(T,K)>`_ sorted by ``cmp`` in the specified order
## * `lowerBound proc<#lowerBound,openArray[T],T>`_
runnableExamples:
var arr = @[1,2,3,5,6,7,8,9]
var arr = @[1, 2, 3, 5, 6, 7, 8, 9]
assert arr.upperBound(2, system.cmp[int]) == 2
assert arr.upperBound(3, system.cmp[int]) == 3
assert arr.upperBound(4, system.cmp[int]) == 3
arr.insert(4, arr.upperBound(3, system.cmp[int]))
assert arr == [1,2,3,4,5,6,7,8,9]
assert arr == [1, 2, 3, 4, 5, 6, 7, 8, 9]
result = a.low
var count = a.high - a.low + 1
var step, pos: int
@@ -422,7 +424,8 @@ func sort*[T](a: var openArray[T],
dec(m, s*2)
s = s*2
proc sort*[T](a: var openArray[T], order = SortOrder.Ascending) = sort[T](a, system.cmp[T], order)
proc sort*[T](a: var openArray[T], order = SortOrder.Ascending) = sort[T](a,
system.cmp[T], order)
## Shortcut version of ``sort`` that uses ``system.cmp[T]`` as the comparison function.
##
## **See also:**
@@ -492,11 +495,13 @@ template sortedByIt*(seq1, op: untyped): untyped =
p2: Person = (name: "p2", age: 20)
p3: Person = (name: "p3", age: 30)
p4: Person = (name: "p4", age: 30)
people = @[p1,p2,p4,p3]
people = @[p1, p2, p4, p3]
assert people.sortedByIt(it.name) == @[(name: "p1", age: 60), (name: "p2", age: 20), (name: "p3", age: 30), (name: "p4", age: 30)]
assert people.sortedByIt(it.name) == @[(name: "p1", age: 60), (name: "p2",
age: 20), (name: "p3", age: 30), (name: "p4", age: 30)]
# Nested sort
assert people.sortedByIt((it.age, it.name)) == @[(name: "p2", age: 20), (name: "p3", age: 30), (name: "p4", age: 30), (name: "p1", age: 60)]
assert people.sortedByIt((it.age, it.name)) == @[(name: "p2", age: 20),
(name: "p3", age: 30), (name: "p4", age: 30), (name: "p1", age: 60)]
var result = sorted(seq1, proc(x, y: type(seq1[0])): int =
var it {.inject.} = x
let a = op
@@ -529,7 +534,7 @@ func isSorted*[T](a: openArray[T],
assert isSorted(e) == false
result = true
for i in 0..<len(a)-1:
if cmp(a[i],a[i+1]) * order > 0:
if cmp(a[i], a[i+1]) * order > 0:
return false
proc isSorted*[T](a: openArray[T], order = SortOrder.Ascending): bool =
@@ -665,19 +670,19 @@ proc prevPermutation*[T](x: var openArray[T]): bool {.discardable.} =
when isMainModule:
# Tests for lowerBound
var arr = @[1,2,3,5,6,7,8,9]
var arr = @[1, 2, 3, 5, 6, 7, 8, 9]
assert arr.lowerBound(0) == 0
assert arr.lowerBound(4) == 3
assert arr.lowerBound(5) == 3
assert arr.lowerBound(10) == 8
arr = @[1,5,10]
arr = @[1, 5, 10]
assert arr.lowerBound(4) == 1
assert arr.lowerBound(5) == 1
assert arr.lowerBound(6) == 2
# Tests for isSorted
var srt1 = [1,2,3,4,4,4,4,5]
var srt2 = ["iello","hello"]
var srt3 = [1.0,1.0,1.0]
var srt1 = [1, 2, 3, 4, 4, 4, 4, 5]
var srt2 = ["iello", "hello"]
var srt3 = [1.0, 1.0, 1.0]
var srt4: seq[int]
assert srt1.isSorted(cmp) == true
assert srt2.isSorted(cmp) == false
@@ -686,8 +691,8 @@ when isMainModule:
var srtseq = newSeq[int]()
assert srtseq.isSorted(cmp) == true
# Tests for reversed
var arr1 = @[0,1,2,3,4]
assert arr1.reversed() == @[4,3,2,1,0]
var arr1 = @[0, 1, 2, 3, 4]
assert arr1.reversed() == @[4, 3, 2, 1, 0]
for i in 0 .. high(arr1):
assert arr1.reversed(0, i) == arr1.reversed()[high(arr1) - i .. high(arr1)]
assert arr1.reversed(i, high(arr1)) == arr1.reversed()[0 .. high(arr1) - i]
@@ -745,7 +750,8 @@ proc rotatedInternal[T](arg: openArray[T]; first, middle, last: int): seq[T] =
for i in last ..< arg.len:
result[i] = arg[i]
proc rotateLeft*[T](arg: var openArray[T]; slice: HSlice[int, int]; dist: int): int {.discardable.} =
proc rotateLeft*[T](arg: var openArray[T]; slice: HSlice[int, int];
dist: int): int {.discardable.} =
## Performs a left rotation on a range of elements. If you want to rotate
## right, use a negative ``dist``. Specifically, ``rotateLeft`` rotates
## the elements at ``slice`` by ``dist`` positions.
@@ -801,7 +807,8 @@ proc rotateLeft*[T](arg: var openArray[T]; dist: int): int {.discardable.} =
let distLeft = ((dist mod arglen) + arglen) mod arglen
arg.rotateInternal(0, distLeft, arglen)
proc rotatedLeft*[T](arg: openArray[T]; slice: HSlice[int, int], dist: int): seq[T] =
proc rotatedLeft*[T](arg: openArray[T]; slice: HSlice[int, int],
dist: int): seq[T] =
## Same as ``rotateLeft``, just with the difference that it does
## not modify the argument. It creates a new ``seq`` instead.
##
@@ -858,7 +865,7 @@ when isMainModule:
doAssert list == expected
doAssert list2 == @expected
var s0,s1,s2,s3,s4,s5 = "xxxabcdefgxxx"
var s0, s1, s2, s3, s4, s5 = "xxxabcdefgxxx"
doAssert s0.rotateLeft(3 ..< 10, 3) == 7
doAssert s0 == "xxxdefgabcxxx"
@@ -876,20 +883,22 @@ when isMainModule:
block product:
doAssert product(newSeq[seq[int]]()) == newSeq[seq[int]](), "empty input"
doAssert product(@[newSeq[int](), @[], @[]]) == newSeq[seq[int]](), "bit more empty input"
doAssert product(@[@[1,2]]) == @[@[1,2]], "a simple case of one element"
doAssert product(@[@[1,2], @[3,4]]) == @[@[2,4],@[1,4],@[2,3],@[1,3]], "two elements"
doAssert product(@[@[1,2], @[3,4], @[5,6]]) == @[@[2,4,6],@[1,4,6],@[2,3,6],@[1,3,6], @[2,4,5],@[1,4,5],@[2,3,5],@[1,3,5]], "three elements"
doAssert product(@[@[1,2], @[]]) == newSeq[seq[int]](), "two elements, but one empty"
doAssert product(@[@[1, 2]]) == @[@[1, 2]], "a simple case of one element"
doAssert product(@[@[1, 2], @[3, 4]]) == @[@[2, 4], @[1, 4], @[2, 3], @[1,
3]], "two elements"
doAssert product(@[@[1, 2], @[3, 4], @[5, 6]]) == @[@[2, 4, 6], @[1, 4, 6],
@[2, 3, 6], @[1, 3, 6], @[2, 4, 5], @[1, 4, 5], @[2, 3, 5], @[1, 3, 5]], "three elements"
doAssert product(@[@[1, 2], @[]]) == newSeq[seq[int]](), "two elements, but one empty"
block lowerBound:
doAssert lowerBound([1,2,4], 3, system.cmp[int]) == 2
doAssert lowerBound([1,2,2,3], 4, system.cmp[int]) == 4
doAssert lowerBound([1,2,3,10], 11) == 4
doAssert lowerBound([1, 2, 4], 3, system.cmp[int]) == 2
doAssert lowerBound([1, 2, 2, 3], 4, system.cmp[int]) == 4
doAssert lowerBound([1, 2, 3, 10], 11) == 4
block upperBound:
doAssert upperBound([1,2,4], 3, system.cmp[int]) == 2
doAssert upperBound([1,2,2,3], 3, system.cmp[int]) == 4
doAssert upperBound([1,2,3,5], 3) == 3
doAssert upperBound([1, 2, 4], 3, system.cmp[int]) == 2
doAssert upperBound([1, 2, 2, 3], 3, system.cmp[int]) == 4
doAssert upperBound([1, 2, 3, 5], 3) == 3
block fillEmptySeq:
var s = newSeq[int]()
@@ -901,16 +910,16 @@ when isMainModule:
let oneData = @[1]
doAssert binarySearch(oneData, 1) == 0
doAssert binarySearch(onedata, 7) == -1
let someData = @[1,3,4,7]
let someData = @[1, 3, 4, 7]
doAssert binarySearch(someData, 1) == 0
doAssert binarySearch(somedata, 7) == 3
doAssert binarySearch(someData, -1) == -1
doAssert binarySearch(someData, 5) == -1
doAssert binarySearch(someData, 13) == -1
let moreData = @[1,3,5,7,4711]
let moreData = @[1, 3, 5, 7, 4711]
doAssert binarySearch(moreData, -1) == -1
doAssert binarySearch(moreData, 1) == 0
doAssert binarySearch(moreData, 5) == 2
doAssert binarySearch(moreData, 6) == -1
doAssert binarySearch(moreData, 4711) == 4
doAssert binarySearch(moreData, 4712) == -1
doAssert binarySearch(moreData, 1) == 0
doAssert binarySearch(moreData, 5) == 2
doAssert binarySearch(moreData, 6) == -1
doAssert binarySearch(moreData, 4711) == 4
doAssert binarySearch(moreData, 4712) == -1

View File

@@ -198,7 +198,7 @@ proc processTimers(
dec count
didSomeWork = true
# Return the number of miliseconds in which the next timer will expire.
# Return the number of milliseconds in which the next timer will expire.
if p.timers.len == 0: return
let millisecs = (p.timers[0].finishAt - getMonoTime()).inMilliseconds
@@ -236,7 +236,7 @@ when defined(windows) or defined(nimdoc):
CompletionKey = ULONG_PTR
CompletionData* = object
fd*: AsyncFD # TODO: Rename this.
fd*: AsyncFD # TODO: Rename this.
cb*: owned(proc (fd: AsyncFD, bytesTransferred: DWORD,
errcode: OSErrorCode) {.closure, gcsafe.})
cell*: ForeignCell # we need this `cell` to protect our `cb` environment,
@@ -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.}
@@ -795,7 +795,7 @@ when defined(windows) or defined(nimdoc):
proc contains*(disp: PDispatcher, fd: AsyncFD): bool =
return fd in disp.handles
{.push stackTrace:off.}
{.push stackTrace: off.}
proc waitableCallback(param: pointer,
timerOrWaitFired: WINBOOL): void {.stdcall.} =
var p = cast[PostCallbackDataPtr](param)
@@ -953,10 +953,10 @@ when defined(windows) or defined(nimdoc):
deallocShared(cast[pointer](pcd))
p.handles.excl(fd)
if unregisterWait(waitFd) == 0:
let err = osLastError()
if err.int32 != ERROR_IO_PENDING:
discard closeHandle(handle)
raiseOSError(err)
let err = osLastError()
if err.int32 != ERROR_IO_PENDING:
discard closeHandle(handle)
raiseOSError(err)
if closeHandle(handle) == 0:
raiseOSError(osLastError())
@@ -1093,7 +1093,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]
@@ -1588,7 +1588,7 @@ proc createAsyncNativeSocket*(domain: Domain = Domain.AF_INET,
createAsyncNativeSocketImpl(domain, sockType, protocol)
proc newAsyncNativeSocket*(domain: cint, sockType: cint,
protocol: cint): AsyncFD {.deprecated: "use createAsyncNativeSocket instead".} =
protocol: cint): AsyncFD {.deprecated: "use createAsyncNativeSocket instead".} =
createAsyncNativeSocketImpl(domain, sockType, protocol)
proc newAsyncNativeSocket*(domain: Domain = Domain.AF_INET,

View File

@@ -488,7 +488,7 @@ proc setFileSize*(f: AsyncFile, length: int64) =
status = setFilePointer(f.fd.Handle, low, addr high, 0)
lastErr = osLastError()
if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or
(setEndOfFile(f.fd.Handle) == 0):
(setEndOfFile(f.fd.Handle) == 0):
raiseOSError(osLastError())
else:
# will truncate if Off is a 32-bit type!

View File

@@ -100,27 +100,27 @@ type
of JRetr, JStore:
file: File
filename: string
total: BiggestInt # In bytes.
progress: BiggestInt # In bytes.
oneSecond: BiggestInt # Bytes transferred in one second.
total: BiggestInt # In bytes.
progress: BiggestInt # In bytes.
oneSecond: BiggestInt # Bytes transferred in one second.
lastProgressReport: float # Time
toStore: string # Data left to upload (Only used with async)
toStore: string # Data left to upload (Only used with async)
FtpEventType* = enum
EvTransferProgress, EvLines, EvRetr, EvStore
FtpEvent* = object ## Event
FtpEvent* = object ## Event
filename*: string
case typ*: FtpEventType
of EvLines:
lines*: string ## Lines that have been transferred.
of EvRetr, EvStore: ## Retr/Store operation finished.
lines*: string ## Lines that have been transferred.
of EvRetr, EvStore: ## Retr/Store operation finished.
nil
of EvTransferProgress:
bytesTotal*: BiggestInt ## Bytes total.
bytesFinished*: BiggestInt ## Bytes transferred.
speed*: BiggestInt ## Speed in bytes/s
currentJob*: FtpJobType ## The current job being performed.
bytesTotal*: BiggestInt ## Bytes total.
bytesFinished*: BiggestInt ## Bytes transferred.
speed*: BiggestInt ## Speed in bytes/s
currentJob*: FtpJobType ## The current job being performed.
ReplyError* = object of IOError
@@ -154,7 +154,7 @@ proc assertReply(received: TaintedString, expected: varargs[string]) =
if received.string.startsWith(i): return
raise newException(ReplyError,
"Expected reply '$1' got: $2" %
[expected.join("' or '"), received.string])
[expected.join("' or '"), received.string])
proc pasv(ftp: AsyncFtpClient) {.async.} =
## Negotiate a data connection.
@@ -164,8 +164,8 @@ proc pasv(ftp: AsyncFtpClient) {.async.} =
assertReply(pasvMsg, "227")
var betweenParens = captureBetween(pasvMsg.string, '(', ')')
var nums = betweenParens.split(',')
var ip = nums[0.. ^3]
var port = nums[^2.. ^1]
var ip = nums[0 .. ^3]
var port = nums[^2 .. ^1]
var properPort = port[0].parseInt()*256+port[1].parseInt()
await ftp.dsock.connect(ip.join("."), Port(properPort.toU16))
ftp.dsockConnected = true

View File

@@ -17,11 +17,11 @@ type
function: CallbackFunc
next: owned(ref CallbackList)
FutureBase* = ref object of RootObj ## Untyped future.
FutureBase* = ref object of RootObj ## Untyped future.
callbacks: CallbackList
finished: bool
error*: ref Exception ## Stored exception
error*: ref Exception ## Stored exception
errorStackTrace*: string
when not defined(release):
stackTrace: seq[StackTraceEntry] ## For debugging purposes only.
@@ -29,7 +29,7 @@ type
fromProc: string
Future*[T] = ref object of FutureBase ## Typed future.
value: T ## Stored value
value: T ## Stored value
FutureVar*[T] = distinct Future[T]
@@ -260,7 +260,7 @@ proc clearCallbacks*(future: FutureBase) =
future.callbacks.function = nil
future.callbacks.next = nil
proc addCallback*(future: FutureBase, cb: proc() {.closure,gcsafe.}) =
proc addCallback*(future: FutureBase, cb: proc() {.closure, gcsafe.}) =
## Adds the callbacks proc to be called when the future completes.
##
## If future has already completed then ``cb`` will be called immediately.
@@ -271,16 +271,16 @@ proc addCallback*(future: FutureBase, cb: proc() {.closure,gcsafe.}) =
future.callbacks.add cb
proc addCallback*[T](future: Future[T],
cb: proc (future: Future[T]) {.closure,gcsafe.}) =
cb: proc (future: Future[T]) {.closure, gcsafe.}) =
## Adds the callbacks proc to be called when the future completes.
##
## If future has already completed then ``cb`` will be called immediately.
future.addCallback(
proc() =
cb(future)
cb(future)
)
proc `callback=`*(future: FutureBase, cb: proc () {.closure,gcsafe.}) =
proc `callback=`*(future: FutureBase, cb: proc () {.closure, gcsafe.}) =
## Clears the list of callbacks and sets the callback proc to be called when the future completes.
##
## If future has already completed then ``cb`` will be called immediately.
@@ -290,7 +290,7 @@ proc `callback=`*(future: FutureBase, cb: proc () {.closure,gcsafe.}) =
future.addCallback cb
proc `callback=`*[T](future: Future[T],
cb: proc (future: Future[T]) {.closure,gcsafe.}) =
cb: proc (future: Future[T]) {.closure, gcsafe.}) =
## Sets the callback proc to be called when the future completes.
##
## If future has already completed then ``cb`` will be called immediately.

View File

@@ -50,7 +50,7 @@ type
headers*: HttpHeaders
protocol*: tuple[orig: string, major, minor: int]
url*: Uri
hostname*: string ## The hostname of the client that made the request.
hostname*: string ## The hostname of the client that made the request.
body*: string
AsyncHttpServer* = ref object
@@ -169,7 +169,7 @@ proc processRequest(
for i in 0..1:
lineFut.mget().setLen(0)
lineFut.clean()
await client.recvLineInto(lineFut, maxLength=maxLine) # TODO: Timeouts.
await client.recvLineInto(lineFut, maxLength = maxLine) # TODO: Timeouts.
if lineFut.mget == "":
client.close()
@@ -214,7 +214,7 @@ proc processRequest(
i = 0
lineFut.mget.setLen(0)
lineFut.clean()
await client.recvLineInto(lineFut, maxLength=maxLine)
await client.recvLineInto(lineFut, maxLength = maxLine)
if lineFut.mget == "":
client.close(); return false
@@ -242,7 +242,8 @@ proc processRequest(
# - Check for Content-length header
if request.headers.hasKey("Content-Length"):
var contentLength = 0
if parseSaturatedNatural(request.headers["Content-Length"], contentLength) == 0:
if parseSaturatedNatural(request.headers["Content-Length"],
contentLength) == 0:
await request.respond(Http400, "Bad Request. Invalid Content-Length.")
return true
else:

View File

@@ -163,7 +163,8 @@ proc processBody(node, retFutureSym: NimNode,
if node[1][0].eqIdent("await"):
# x = await y
var newAsgn = node
result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn, node)
result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1],
newAsgn, node)
else: discard
of nnkDiscardStmt:
# discard await x
@@ -212,8 +213,8 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
## This macro transforms a single procedure into a closure iterator.
## The ``async`` macro supports a stmtList holding multiple async procedures.
if prc.kind notin {nnkProcDef, nnkLambda, nnkMethodDef, nnkDo}:
error("Cannot transform this node kind into an async proc." &
" proc/method definition or lambda node expected.")
error("Cannot transform this node kind into an async proc." &
" proc/method definition or lambda node expected.")
let prcName = prc.name.getName
@@ -296,11 +297,12 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
var closureIterator = newProc(iteratorNameSym, [parseExpr("owned(FutureBase)")],
procBody, nnkIteratorDef)
closureIterator.pragma = newNimNode(nnkPragma, lineInfoFrom=prc.body)
closureIterator.pragma = newNimNode(nnkPragma, lineInfoFrom = prc.body)
closureIterator.addPragma(newIdentNode("closure"))
# If proc has an explicit gcsafe pragma, we add it to iterator as well.
if prc.pragma.findChild(it.kind in {nnkSym, nnkIdent} and $it == "gcsafe") != nil:
if prc.pragma.findChild(it.kind in {nnkSym, nnkIdent} and $it ==
"gcsafe") != nil:
closureIterator.addPragma(newIdentNode("gcsafe"))
outerProcBody.add(closureIterator)
@@ -414,20 +416,20 @@ proc splitProc(prc: NimNode): (NimNode, NimNode) =
result[0] = prc.copyNimTree()
# Retrieve the `T` inside `Future[T]`.
let returnType = stripReturnType(result[0][3][0])
result[0][3][0] = splitParamType(returnType, async=false)
result[0][3][0] = splitParamType(returnType, async = false)
for i in 1 ..< result[0][3].len:
# Sync proc (0) -> FormalParams (3) -> IdentDefs, the parameter (i) ->
# parameter type (1).
result[0][3][i][1] = splitParamType(result[0][3][i][1], async=false)
result[0][3][i][1] = splitParamType(result[0][3][i][1], async = false)
result[0][6] = stripAwait(result[0][6])
result[1] = prc.copyNimTree()
if result[1][3][0].kind == nnkBracketExpr:
result[1][3][0][1] = splitParamType(result[1][3][0][1], async=true)
result[1][3][0][1] = splitParamType(result[1][3][0][1], async = true)
for i in 1 ..< result[1][3].len:
# Async proc (1) -> FormalParams (3) -> IdentDefs, the parameter (i) ->
# parameter type (1).
result[1][3][i][1] = splitParamType(result[1][3][i][1], async=true)
result[1][3][i][1] = splitParamType(result[1][3][i][1], async = true)
macro multisync*(prc: untyped): untyped =
## Macro which processes async procedures into both asynchronous and

View File

@@ -114,11 +114,11 @@ type
# AsyncSocket* {.borrow: `.`.} = distinct Socket. But that doesn't work.
AsyncSocketDesc = object
fd: SocketHandle
closed: bool ## determines whether this socket has been closed
closed: bool ## determines whether this socket has been closed
isBuffered: bool ## determines whether this socket is buffered.
buffer: array[0..BufferSize, char]
currPos: int # current index in buffer
bufLen: int # current length of buffer
currPos: int # current index in buffer
bufLen: int # current length of buffer
isSsl: bool
when defineSsl:
sslHandle: SslPtr
@@ -603,7 +603,8 @@ proc recvLine*(socket: AsyncSocket,
await socket.recvLineInto(resString, flags, maxLength)
result = resString.mget()
proc listen*(socket: AsyncSocket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} =
proc listen*(socket: AsyncSocket, backlog = SOMAXCONN) {.tags: [
ReadIOEffect].} =
## Marks ``socket`` as accepting connections.
## ``Backlog`` specifies the maximum length of the
## queue of pending connections.
@@ -620,7 +621,7 @@ proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {.
if realaddr == "":
case socket.domain
of AF_INET6: realaddr = "::"
of AF_INET: realaddr = "0.0.0.0"
of AF_INET: realaddr = "0.0.0.0"
else:
raise newException(ValueError,
"Unknown socket address family and no address specified to bindAddr")
@@ -653,7 +654,7 @@ when defined(posix):
var socketAddr = makeUnixAddr(path)
let ret = socket.fd.connect(cast[ptr SockAddr](addr socketAddr),
(sizeof(socketAddr.sun_family) + path.len).SockLen)
(sizeof(socketAddr.sun_family) + path.len).SockLen)
if ret == 0:
# Request to connect completed immediately.
retFuture.complete()
@@ -671,7 +672,7 @@ when defined(posix):
when not defined(nimdoc):
var socketAddr = makeUnixAddr(path)
if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr),
(sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32:
(sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32:
raiseOSError(osLastError())
elif defined(nimdoc):

View File

@@ -14,10 +14,10 @@ import asyncfutures
import deques
type
FutureStream*[T] = ref object ## Special future that acts as
## a queue. Its API is still
## experimental and so is
## subject to change.
FutureStream*[T] = ref object ## Special future that acts as
## a queue. Its API is still
## experimental and so is
## subject to change.
queue: Deque[T]
finished: bool
cb: proc () {.closure, gcsafe.}
@@ -45,7 +45,7 @@ proc complete*[T](future: FutureStream[T]) =
future.cb()
proc `callback=`*[T](future: FutureStream[T],
cb: proc (future: FutureStream[T]) {.closure,gcsafe.}) =
cb: proc (future: FutureStream[T]) {.closure, gcsafe.}) =
## Sets the callback proc to be called when data was placed inside the
## future stream.
##
@@ -74,7 +74,7 @@ proc write*[T](future: FutureStream[T], value: T): Future[void] =
result.fail(newException(ValueError, msg))
return
# TODO: Implement limiting of the streams storage to prevent it growing
# infinitely when no reads are occuring.
# infinitely when no reads are occurring.
future.queue.addLast(value)
if not future.cb.isNil: future.cb()
result.complete()

View File

@@ -112,7 +112,8 @@ template encodeInternal(s: typed, lineLen: int, newLine: string): untyped =
#assert(r == result.len)
discard
proc encode*[T: SomeInteger|char](s: openArray[T], lineLen = 75, newLine=""): string =
proc encode*[T: SomeInteger|char](s: openArray[T], lineLen = 75,
newLine = ""): string =
## Encodes ``s`` into base64 representation. After ``lineLen`` characters, a
## ``newline`` is added.
##
@@ -128,7 +129,7 @@ proc encode*[T: SomeInteger|char](s: openArray[T], lineLen = 75, newLine=""): st
assert encode([1, 2, 3, 4, 5]) == "AQIDBAU="
encodeInternal(s, lineLen, newLine)
proc encode*(s: string, lineLen = 75, newLine=""): string =
proc encode*(s: string, lineLen = 75, newLine = ""): string =
## Encodes ``s`` into base64 representation. After ``lineLen`` characters, a
## ``newline`` is added.
##
@@ -208,5 +209,5 @@ when isMainModule:
for t in items(tests):
assert decode(encode(t)) == t
assert decode(encode(t, lineLen=40)) == t
assert decode(encode(t, lineLen=76)) == t
assert decode(encode(t, lineLen = 40)) == t
assert decode(encode(t, lineLen = 76)) == t

View File

@@ -23,7 +23,7 @@
## to force predictable behaviour for all input, causing a small performance hit.
##
## At this time only `fastLog2`, `firstSetBit, `countLeadingZeroBits`, `countTrailingZeroBits`
## may return undefined and/or platform dependant value if given invalid input.
## may return undefined and/or platform dependent value if given invalid input.
proc bitnot*[T: SomeInteger](x: T): T {.magic: "BitnotI", noSideEffect.}
## Computes the `bitwise complement` of the integer `x`.
@@ -39,7 +39,8 @@ proc bitxor*[T: SomeInteger](x, y: T): T {.magic: "BitxorI", noSideEffect.}
const useBuiltins = not defined(noIntrinsicsBitOpts)
const noUndefined = defined(noUndefinedBitOpts)
const useGCC_builtins = (defined(gcc) or defined(llvm_gcc) or defined(clang)) and useBuiltins
const useGCC_builtins = (defined(gcc) or defined(llvm_gcc) or
defined(clang)) and useBuiltins
const useICC_builtins = defined(icc) and useBuiltins
const useVCC_builtins = defined(vcc) and useBuiltins
const arch64 = sizeof(int) == 8
@@ -196,7 +197,8 @@ template parityImpl[T](value: T): int =
when useGCC_builtins:
# Returns the number of set 1-bits in value.
proc builtin_popcount(x: cuint): cint {.importc: "__builtin_popcount", cdecl.}
proc builtin_popcountll(x: culonglong): cint {.importc: "__builtin_popcountll", cdecl.}
proc builtin_popcountll(x: culonglong): cint {.
importc: "__builtin_popcountll", cdecl.}
# Returns the bit parity in value
proc builtin_parity(x: cuint): cint {.importc: "__builtin_parity", cdecl.}
@@ -216,17 +218,24 @@ when useGCC_builtins:
elif useVCC_builtins:
# Counts the number of one bits (population count) in a 16-, 32-, or 64-byte unsigned integer.
proc builtin_popcnt16(a2: uint16): uint16 {.importc: "__popcnt16" header: "<intrin.h>", noSideEffect.}
proc builtin_popcnt32(a2: uint32): uint32 {.importc: "__popcnt" header: "<intrin.h>", noSideEffect.}
proc builtin_popcnt64(a2: uint64): uint64 {.importc: "__popcnt64" header: "<intrin.h>", noSideEffect.}
proc builtin_popcnt16(a2: uint16): uint16 {.
importc: "__popcnt16"header: "<intrin.h>", noSideEffect.}
proc builtin_popcnt32(a2: uint32): uint32 {.
importc: "__popcnt"header: "<intrin.h>", noSideEffect.}
proc builtin_popcnt64(a2: uint64): uint64 {.
importc: "__popcnt64"header: "<intrin.h>", noSideEffect.}
# Search the mask data from most significant bit (MSB) to least significant bit (LSB) for a set bit (1).
proc bitScanReverse(index: ptr culong, mask: culong): cuchar {.importc: "_BitScanReverse", header: "<intrin.h>", noSideEffect.}
proc bitScanReverse64(index: ptr culong, mask: uint64): cuchar {.importc: "_BitScanReverse64", header: "<intrin.h>", noSideEffect.}
proc bitScanReverse(index: ptr culong, mask: culong): cuchar {.
importc: "_BitScanReverse", header: "<intrin.h>", noSideEffect.}
proc bitScanReverse64(index: ptr culong, mask: uint64): cuchar {.
importc: "_BitScanReverse64", header: "<intrin.h>", noSideEffect.}
# Search the mask data from least significant bit (LSB) to the most significant bit (MSB) for a set bit (1).
proc bitScanForward(index: ptr culong, mask: culong): cuchar {.importc: "_BitScanForward", header: "<intrin.h>", noSideEffect.}
proc bitScanForward64(index: ptr culong, mask: uint64): cuchar {.importc: "_BitScanForward64", header: "<intrin.h>", noSideEffect.}
proc bitScanForward(index: ptr culong, mask: culong): cuchar {.
importc: "_BitScanForward", header: "<intrin.h>", noSideEffect.}
proc bitScanForward64(index: ptr culong, mask: uint64): cuchar {.
importc: "_BitScanForward64", header: "<intrin.h>", noSideEffect.}
template vcc_scan_impl(fnc: untyped; v: untyped): int =
var index: culong
@@ -238,16 +247,22 @@ elif useICC_builtins:
# Intel compiler intrinsics: http://fulla.fnal.gov/intel/compiler_c/main_cls/intref_cls/common/intref_allia_misc.htm
# see also: https://software.intel.com/en-us/node/523362
# Count the number of bits set to 1 in an integer a, and return that count in dst.
proc builtin_popcnt32(a: cint): cint {.importc: "_popcnt" header: "<immintrin.h>", noSideEffect.}
proc builtin_popcnt64(a: uint64): cint {.importc: "_popcnt64" header: "<immintrin.h>", noSideEffect.}
proc builtin_popcnt32(a: cint): cint {.
importc: "_popcnt"header: "<immintrin.h>", noSideEffect.}
proc builtin_popcnt64(a: uint64): cint {.
importc: "_popcnt64"header: "<immintrin.h>", noSideEffect.}
# Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.
proc bitScanForward(p: ptr uint32, b: uint32): cuchar {.importc: "_BitScanForward", header: "<immintrin.h>", noSideEffect.}
proc bitScanForward64(p: ptr uint32, b: uint64): cuchar {.importc: "_BitScanForward64", header: "<immintrin.h>", noSideEffect.}
proc bitScanForward(p: ptr uint32, b: uint32): cuchar {.
importc: "_BitScanForward", header: "<immintrin.h>", noSideEffect.}
proc bitScanForward64(p: ptr uint32, b: uint64): cuchar {.
importc: "_BitScanForward64", header: "<immintrin.h>", noSideEffect.}
# Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
proc bitScanReverse(p: ptr uint32, b: uint32): cuchar {.importc: "_BitScanReverse", header: "<immintrin.h>", noSideEffect.}
proc bitScanReverse64(p: ptr uint32, b: uint64): cuchar {.importc: "_BitScanReverse64", header: "<immintrin.h>", noSideEffect.}
proc bitScanReverse(p: ptr uint32, b: uint32): cuchar {.
importc: "_BitScanReverse", header: "<immintrin.h>", noSideEffect.}
proc bitScanReverse64(p: ptr uint32, b: uint64): cuchar {.
importc: "_BitScanReverse64", header: "<immintrin.h>", noSideEffect.}
template icc_scan_impl(fnc: untyped; v: untyped): int =
var index: uint32
@@ -266,21 +281,21 @@ proc countSetBits*(x: SomeInteger): int {.inline, noSideEffect.} =
else:
when useGCC_builtins:
when sizeof(x) <= 4: result = builtin_popcount(x.cuint).int
else: result = builtin_popcountll(x.culonglong).int
else: result = builtin_popcountll(x.culonglong).int
elif useVCC_builtins:
when sizeof(x) <= 2: result = builtin_popcnt16(x.uint16).int
elif sizeof(x) <= 4: result = builtin_popcnt32(x.uint32).int
elif arch64: result = builtin_popcnt64(x.uint64).int
else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).uint32 ).int +
builtin_popcnt32((x.uint64 shr 32'u64).uint32 ).int
elif arch64: result = builtin_popcnt64(x.uint64).int
else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).uint32).int +
builtin_popcnt32((x.uint64 shr 32'u64).uint32).int
elif useICC_builtins:
when sizeof(x) <= 4: result = builtin_popcnt32(x.cint).int
elif arch64: result = builtin_popcnt64(x.uint64).int
else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).cint ).int +
builtin_popcnt32((x.uint64 shr 32'u64).cint ).int
elif arch64: result = builtin_popcnt64(x.uint64).int
else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).cint).int +
builtin_popcnt32((x.uint64 shr 32'u64).cint).int
else:
when sizeof(x) <= 4: result = countSetBitsNim(x.uint32)
else: result = countSetBitsNim(x.uint64)
else: result = countSetBitsNim(x.uint64)
proc popcount*(x: SomeInteger): int {.inline, noSideEffect.} =
## Alias for for countSetBits (Hamming weight.)
@@ -298,10 +313,10 @@ proc parityBits*(x: SomeInteger): int {.inline, noSideEffect.} =
else:
when useGCC_builtins:
when sizeof(x) <= 4: result = builtin_parity(x.uint32).int
else: result = builtin_parityll(x.uint64).int
else: result = builtin_parityll(x.uint64).int
else:
when sizeof(x) <= 4: result = parityImpl(x.uint32)
else: result = parityImpl(x.uint64)
else: result = parityImpl(x.uint64)
proc firstSetBit*(x: SomeInteger): int {.inline, noSideEffect.} =
## Returns the 1-based index of the least significant set bit of x.
@@ -321,7 +336,7 @@ proc firstSetBit*(x: SomeInteger): int {.inline, noSideEffect.} =
return 0
when useGCC_builtins:
when sizeof(x) <= 4: result = builtin_ffs(cast[cint](x.cuint)).int
else: result = builtin_ffsll(cast[clonglong](x.culonglong)).int
else: result = builtin_ffsll(cast[clonglong](x.culonglong)).int
elif useVCC_builtins:
when sizeof(x) <= 4:
result = 1 + vcc_scan_impl(bitScanForward, x.culong)
@@ -338,7 +353,7 @@ proc firstSetBit*(x: SomeInteger): int {.inline, noSideEffect.} =
result = firstSetBitNim(x.uint64)
else:
when sizeof(x) <= 4: result = firstSetBitNim(x.uint32)
else: result = firstSetBitNim(x.uint64)
else: result = firstSetBitNim(x.uint64)
proc fastLog2*(x: SomeInteger): int {.inline, noSideEffect.} =
## Quickly find the log base 2 of an integer.
@@ -354,7 +369,7 @@ proc fastLog2*(x: SomeInteger): int {.inline, noSideEffect.} =
else:
when useGCC_builtins:
when sizeof(x) <= 4: result = 31 - builtin_clz(x.uint32).int
else: result = 63 - builtin_clzll(x.uint64).int
else: result = 63 - builtin_clzll(x.uint64).int
elif useVCC_builtins:
when sizeof(x) <= 4:
result = vcc_scan_impl(bitScanReverse, x.culong)
@@ -371,7 +386,7 @@ proc fastLog2*(x: SomeInteger): int {.inline, noSideEffect.} =
result = fastlog2Nim(x.uint64)
else:
when sizeof(x) <= 4: result = fastlog2Nim(x.uint32)
else: result = fastlog2Nim(x.uint64)
else: result = fastlog2Nim(x.uint64)
proc countLeadingZeroBits*(x: SomeInteger): int {.inline, noSideEffect.} =
## Returns the number of leading zero bits in integer.
@@ -387,10 +402,10 @@ proc countLeadingZeroBits*(x: SomeInteger): int {.inline, noSideEffect.} =
else:
when useGCC_builtins:
when sizeof(x) <= 4: result = builtin_clz(x.uint32).int - (32 - sizeof(x)*8)
else: result = builtin_clzll(x.uint64).int
else: result = builtin_clzll(x.uint64).int
else:
when sizeof(x) <= 4: result = sizeof(x)*8 - 1 - fastlog2Nim(x.uint32)
else: result = sizeof(x)*8 - 1 - fastlog2Nim(x.uint64)
else: result = sizeof(x)*8 - 1 - fastlog2Nim(x.uint64)
proc countTrailingZeroBits*(x: SomeInteger): int {.inline, noSideEffect.} =
## Returns the number of trailing zeros in integer.
@@ -406,7 +421,7 @@ proc countTrailingZeroBits*(x: SomeInteger): int {.inline, noSideEffect.} =
else:
when useGCC_builtins:
when sizeof(x) <= 4: result = builtin_ctz(x.uint32).int
else: result = builtin_ctzll(x.uint64).int
else: result = builtin_ctzll(x.uint64).int
else:
result = firstSetBit(x) - 1

View File

@@ -40,7 +40,7 @@ proc openDefaultBrowser*(url: string) =
for b in getEnv("BROWSER").string.split(PathSep):
try:
# we use ``startProcess`` here because we don't want to block!
discard startProcess(command=b, args=[url], options={poUsePath})
discard startProcess(command = b, args = [url], options = {poUsePath})
return
except OSError:
discard

View File

@@ -58,11 +58,11 @@ proc xmlEncode*(s: string): string =
for i in 0..len(s)-1: addXmlChar(result, s[i])
type
CgiError* = object of IOError ## exception that is raised if a CGI error occurs
RequestMethod* = enum ## the used request method
methodNone, ## no REQUEST_METHOD environment variable
methodPost, ## query uses the POST method
methodGet ## query uses the GET method
CgiError* = object of IOError ## exception that is raised if a CGI error occurs
RequestMethod* = enum ## the used request method
methodNone, ## no REQUEST_METHOD environment variable
methodPost, ## query uses the POST method
methodGet ## query uses the GET method
proc cgiError*(msg: string) {.noreturn.} =
## raises an ECgi exception with message `msg`.

View File

@@ -387,6 +387,7 @@ proc assign*(dest: var IntSet, src: IntSet) =
else:
dest.counter = src.counter
dest.max = src.max
dest.elems = src.elems
newSeq(dest.data, src.data.len)
var it = src.head
@@ -653,3 +654,19 @@ when isMainModule:
xs = toSeq(items(x))
xs.sort(cmp[int])
assert xs == @[1, 4, 7, 1001, 1056]
proc bug12366 =
var
x = initIntSet()
y = initIntSet()
n = 3584
for i in 0..n:
x.incl(i)
y.incl(i)
let z = symmetricDifference(x, y)
doAssert z.len == 0
doAssert $z == "{}"
bug12366()

View File

@@ -848,7 +848,7 @@ template mapIt*(s: typed, op: untyped): untyped =
result
template mapIt*(s, typ, op: untyped): untyped {.error:
"Deprecated since v0.12; Use 'mapIt(seq1, op)' - without specifying the type of the returned seqence".} =
"Deprecated since v0.12; Use 'mapIt(seq1, op)' - without specifying the type of the returned sequence".} =
var result: seq[typ] = @[]
for it {.inject.} in items(s):
result.add(op)
@@ -883,7 +883,7 @@ template newSeqWith*(len: int, init: untyped): untyped =
## or to populate fields of the created sequence.
##
runnableExamples:
## Creates a seqence containing 5 bool sequences, each of length of 3.
## Creates a sequence containing 5 bool sequences, each of length of 3.
var seq2D = newSeqWith(5, newSeq[bool](3))
assert seq2D.len == 5
assert seq2D[0].len == 3

View File

@@ -62,12 +62,12 @@ proc `==` *[T](x, y: Complex[T]): bool =
## Compare two complex numbers ``x`` and ``y`` for equality.
result = x.re == y.re and x.im == y.im
proc `+` *[T](x: T, y: Complex[T]): Complex[T] =
proc `+` *[T](x: T; y: Complex[T]): Complex[T] =
## Add a real number to a complex number.
result.re = x + y.re
result.im = y.im
proc `+` *[T](x: Complex[T], y: T): Complex[T] =
proc `+` *[T](x: Complex[T]; y: T): Complex[T] =
## Add a complex number to a real number.
result.re = x.re + y
result.im = x.im
@@ -82,11 +82,11 @@ proc `-` *[T](z: Complex[T]): Complex[T] =
result.re = -z.re
result.im = -z.im
proc `-` *[T](x: T, y: Complex[T]): Complex[T] =
proc `-` *[T](x: T; y: Complex[T]): Complex[T] =
## Subtract a complex number from a real number.
x + (-y)
proc `-` *[T](x: Complex[T], y: T): Complex[T] =
proc `-` *[T](x: Complex[T]; y: T): Complex[T] =
## Subtract a real number from a complex number.
result.re = x.re - y
result.im = x.im
@@ -96,12 +96,12 @@ proc `-` *[T](x, y: Complex[T]): Complex[T] =
result.re = x.re - y.re
result.im = x.im - y.im
proc `/` *[T](x: Complex[T], y: T): Complex[T] =
proc `/` *[T](x: Complex[T]; y: T): Complex[T] =
## Divide complex number ``x`` by real number ``y``.
result.re = x.re / y
result.im = x.im / y
proc `/` *[T](x: T, y: Complex[T]): Complex[T] =
proc `/` *[T](x: T; y: Complex[T]): Complex[T] =
## Divide real number ``x`` by complex number ``y``.
result = x * inv(y)
@@ -119,12 +119,12 @@ proc `/` *[T](x, y: Complex[T]): Complex[T] =
result.re = (x.re + r * x.im) / den
result.im = (x.im - r * x.re) / den
proc `*` *[T](x: T, y: Complex[T]): Complex[T] =
proc `*` *[T](x: T; y: Complex[T]): Complex[T] =
## Multiply a real number and a complex number.
result.re = x * y.re
result.im = x * y.im
proc `*` *[T](x: Complex[T], y: T): Complex[T] =
proc `*` *[T](x: Complex[T]; y: T): Complex[T] =
## Multiply a complex number with a real number.
result.re = x.re * y
result.im = x.im * y
@@ -135,23 +135,23 @@ proc `*` *[T](x, y: Complex[T]): Complex[T] =
result.im = x.im * y.re + x.re * y.im
proc `+=` *[T](x: var Complex[T], y: Complex[T]) =
proc `+=` *[T](x: var Complex[T]; y: Complex[T]) =
## Add ``y`` to ``x``.
x.re += y.re
x.im += y.im
proc `-=` *[T](x: var Complex[T], y: Complex[T]) =
proc `-=` *[T](x: var Complex[T]; y: Complex[T]) =
## Subtract ``y`` from ``x``.
x.re -= y.re
x.im -= y.im
proc `*=` *[T](x: var Complex[T], y: Complex[T]) =
proc `*=` *[T](x: var Complex[T]; y: Complex[T]) =
## Multiply ``y`` to ``x``.
let im = x.im * y.re + x.re * y.im
x.re = x.re * y.re - x.im * y.im
x.im = im
proc `/=` *[T](x: var Complex[T], y: Complex[T]) =
proc `/=` *[T](x: var Complex[T]; y: Complex[T]) =
## Divide ``x`` by ``y`` in place.
x = x / y
@@ -222,7 +222,7 @@ proc pow*[T](x, y: Complex[T]): Complex[T] =
result.re = s * cos(r)
result.im = s * sin(r)
proc pow*[T](x: Complex[T], y: T): Complex[T] =
proc pow*[T](x: Complex[T]; y: T): Complex[T] =
## Complex number ``x`` raised to the power ``y``.
pow(x, complex[T](y))
@@ -352,18 +352,18 @@ when isMainModule:
proc `=~`[T](x, y: Complex[T]): bool =
result = abs(x.re-y.re) < 1e-6 and abs(x.im-y.im) < 1e-6
proc `=~`[T](x: Complex[T], y: T): bool =
proc `=~`[T](x: Complex[T]; y: T): bool =
result = abs(x.re-y) < 1e-6 and abs(x.im) < 1e-6
var
z: Complex64 = complex(0.0, 0.0)
oo: Complex64 = complex(1.0, 1.0)
a: Complex64 = complex(1.0, 2.0)
b: Complex64 = complex(-1.0, -2.0)
m1: Complex64 = complex(-1.0, 0.0)
i: Complex64 = complex(0.0, 1.0)
z: Complex64 = complex(0.0, 0.0)
oo: Complex64 = complex(1.0, 1.0)
a: Complex64 = complex(1.0, 2.0)
b: Complex64 = complex(-1.0, -2.0)
m1: Complex64 = complex(-1.0, 0.0)
i: Complex64 = complex(0.0, 1.0)
one: Complex64 = complex(1.0, 0.0)
tt: Complex64 = complex(10.0, 20.0)
tt: Complex64 = complex(10.0, 20.0)
ipi: Complex64 = complex(0.0, -PI)
doAssert(a/2.0 =~ complex(0.5, 1.0))

View File

@@ -47,7 +47,7 @@ when defined(cpp) or defined(nimdoc):
## Behaves like Acquire when applied to load, like Release when
## applied to a store and like AcquireRelease when applied to a
## read-modify-write operation.
## Also garantees that all threads observe the same total ordering
## Also guarantees that all threads observe the same total ordering
## with other moSequentiallyConsistent operations.
type

View File

@@ -50,7 +50,7 @@ when defined(haiku):
header: "<OS.h>".}
proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
## returns the numer of the processors/cores the machine has.
## returns the number of the processors/cores the machine has.
## Returns 0 if it cannot be detected.
when defined(windows):
type

View File

@@ -7,7 +7,7 @@
# distribution, for details about the copyright.
#
## Implements Nim's `spawn <manual.html#parallel-amp-spawn>`_.
## Implements Nim's `spawn <manual_experimental.html#parallel-amp-spawn>`_.
##
## **See also:**
## * `threads module <threads.html>`_

View File

@@ -23,7 +23,7 @@
when not nimCoroutines and not defined(nimdoc):
when defined(noNimCoroutines):
{.error: "Coroutines can not be used with -d:noNimCoroutines"}
{.error: "Coroutines can not be used with -d:noNimCoroutines".}
else:
{.error: "Coroutines require -d:nimCoroutines".}
@@ -75,13 +75,18 @@ elif coroBackend == CORO_BACKEND_UCONTEXT:
Context = ucontext_t
proc getcontext(context: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
proc setcontext(context: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
proc swapcontext(fromCtx, toCtx: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
proc makecontext(context: var ucontext_t, fn: pointer, argc: int32) {.importc, header: "<ucontext.h>", varargs.}
proc getcontext(context: var ucontext_t): int32 {.importc,
header: "<ucontext.h>".}
proc setcontext(context: var ucontext_t): int32 {.importc,
header: "<ucontext.h>".}
proc swapcontext(fromCtx, toCtx: var ucontext_t): int32 {.importc,
header: "<ucontext.h>".}
proc makecontext(context: var ucontext_t, fn: pointer, argc: int32) {.importc,
header: "<ucontext.h>", varargs.}
elif coroBackend == CORO_BACKEND_SETJMP:
proc coroExecWithStack*(fn: pointer, stack: pointer) {.noreturn, importc: "narch_$1", fastcall.}
proc coroExecWithStack*(fn: pointer, stack: pointer) {.noreturn,
importc: "narch_$1", fastcall.}
when defined(amd64):
{.compile: "../arch/x86/amd64.S".}
elif defined(i386):
@@ -105,14 +110,14 @@ elif coroBackend == CORO_BACKEND_SETJMP:
{.error: "Unsupported architecture.".}
proc setjmp(ctx: var JmpBuf): int {.importc: "narch_$1".}
proc longjmp(ctx: JmpBuf, ret=1) {.importc: "narch_$1".}
proc longjmp(ctx: JmpBuf, ret = 1) {.importc: "narch_$1".}
else:
# Use setjmp/longjmp implementation provided by the system.
type
JmpBuf {.importc: "jmp_buf", header: "<setjmp.h>".} = object
proc setjmp(ctx: var JmpBuf): int {.importc, header: "<setjmp.h>".}
proc longjmp(ctx: JmpBuf, ret=1) {.importc, header: "<setjmp.h>".}
proc longjmp(ctx: JmpBuf, ret = 1) {.importc, header: "<setjmp.h>".}
type
Context = JmpBuf
@@ -134,8 +139,8 @@ const
type
Stack {.pure.} = object
top: pointer # Top of the stack. Pointer used for deallocating stack if we own it.
bottom: pointer # Very bottom of the stack, acts as unique stack identifier.
top: pointer # Top of the stack. Pointer used for deallocating stack if we own it.
bottom: pointer # Very bottom of the stack, acts as unique stack identifier.
size: int
Coroutine {.pure.} = object
@@ -211,7 +216,7 @@ proc switchTo(current, to: CoroutinePtr) =
setFrameState(frame)
GC_setActiveStack(current.stack.bottom)
proc suspend*(sleepTime: float=0) =
proc suspend*(sleepTime: float = 0) =
## Stops coroutine execution and resumes no sooner than after ``sleeptime`` seconds.
## Until then other coroutines are executed.
var current = getCurrent()
@@ -234,15 +239,15 @@ proc runCurrentTask() =
GC_setActiveStack(sp)
current.state = CORO_EXECUTING
try:
current.fn() # Start coroutine execution
current.fn() # Start coroutine execution
except:
echo "Unhandled exception in coroutine."
writeStackTrace()
current.state = CORO_FINISHED
suspend(0) # Exit coroutine without returning from coroExecWithStack()
suspend(0) # Exit coroutine without returning from coroExecWithStack()
doAssert false
proc start*(c: proc(), stacksize: int=defaultStackSize): CoroutineRef {.discardable.} =
proc start*(c: proc(), stacksize: int = defaultStackSize): CoroutineRef {.discardable.} =
## Schedule coroutine for execution. It does not run immediately.
if ctx == nil:
initialize()
@@ -251,7 +256,9 @@ proc start*(c: proc(), stacksize: int=defaultStackSize): CoroutineRef {.discarda
when coroBackend == CORO_BACKEND_FIBERS:
coro = cast[CoroutinePtr](alloc0(sizeof(Coroutine)))
coro.execContext = CreateFiberEx(stacksize, stacksize,
FIBER_FLAG_FLOAT_SWITCH, (proc(p: pointer): void {.stdcall.} = runCurrentTask()), nil)
FIBER_FLAG_FLOAT_SWITCH,
(proc(p: pointer): void {.stdcall.} = runCurrentTask()),
nil)
coro.stack.size = stacksize
else:
coro = cast[CoroutinePtr](alloc0(sizeof(Coroutine) + stacksize))
@@ -313,7 +320,7 @@ proc run*() =
proc alive*(c: CoroutineRef): bool = c.coro != nil and c.coro.state != CORO_FINISHED
## Returns ``true`` if coroutine has not returned, ``false`` otherwise.
proc wait*(c: CoroutineRef, interval=0.01) =
proc wait*(c: CoroutineRef, interval = 0.01) =
## Returns only after coroutine ``c`` has returned. ``interval`` is time in seconds how often.
while alive(c):
suspend(interval)

View File

@@ -18,62 +18,62 @@ type
DbEffect* = object of IOEffect ## effect that denotes a database operation
ReadDbEffect* = object of DbEffect ## effect that denotes a read operation
WriteDbEffect* = object of DbEffect ## effect that denotes a write operation
ReadDbEffect* = object of DbEffect ## effect that denotes a read operation
WriteDbEffect* = object of DbEffect ## effect that denotes a write operation
DbTypeKind* = enum ## a superset of datatypes that might be supported.
dbUnknown, ## unknown datatype
dbSerial, ## datatype used for primary auto-increment keys
dbNull, ## datatype used for the NULL value
dbBit, ## bit datatype
dbBool, ## boolean datatype
dbBlob, ## blob datatype
dbFixedChar, ## string of fixed length
dbVarchar, ## string datatype
dbJson, ## JSON datatype
dbXml, ## XML datatype
dbInt, ## some integer type
dbUInt, ## some unsigned integer type
dbDecimal, ## decimal numbers (fixed-point number)
dbFloat, ## some floating point type
dbDate, ## a year-month-day description
dbTime, ## HH:MM:SS information
dbDatetime, ## year-month-day and HH:MM:SS information,
## plus optional time or timezone information
dbTimestamp, ## Timestamp values are stored as the number of seconds
## since the epoch ('1970-01-01 00:00:00' UTC).
dbTimeInterval, ## an interval [a,b] of times
dbEnum, ## some enum
dbSet, ## set of enum values
dbArray, ## an array of values
dbComposite, ## composite type (record, struct, etc)
dbUrl, ## a URL
dbUuid, ## a UUID
dbInet, ## an IP address
dbMacAddress, ## a MAC address
dbGeometry, ## some geometric type
dbPoint, ## Point on a plane (x,y)
dbLine, ## Infinite line ((x1,y1),(x2,y2))
dbLseg, ## Finite line segment ((x1,y1),(x2,y2))
dbBox, ## Rectangular box ((x1,y1),(x2,y2))
dbPath, ## Closed or open path (similar to polygon) ((x1,y1),...)
dbPolygon, ## Polygon (similar to closed path) ((x1,y1),...)
dbCircle, ## Circle <(x,y),r> (center point and radius)
dbUser1, ## user definable datatype 1 (for unknown extensions)
dbUser2, ## user definable datatype 2 (for unknown extensions)
dbUser3, ## user definable datatype 3 (for unknown extensions)
dbUser4, ## user definable datatype 4 (for unknown extensions)
dbUser5 ## user definable datatype 5 (for unknown extensions)
DbTypeKind* = enum ## a superset of datatypes that might be supported.
dbUnknown, ## unknown datatype
dbSerial, ## datatype used for primary auto-increment keys
dbNull, ## datatype used for the NULL value
dbBit, ## bit datatype
dbBool, ## boolean datatype
dbBlob, ## blob datatype
dbFixedChar, ## string of fixed length
dbVarchar, ## string datatype
dbJson, ## JSON datatype
dbXml, ## XML datatype
dbInt, ## some integer type
dbUInt, ## some unsigned integer type
dbDecimal, ## decimal numbers (fixed-point number)
dbFloat, ## some floating point type
dbDate, ## a year-month-day description
dbTime, ## HH:MM:SS information
dbDatetime, ## year-month-day and HH:MM:SS information,
## plus optional time or timezone information
dbTimestamp, ## Timestamp values are stored as the number of seconds
## since the epoch ('1970-01-01 00:00:00' UTC).
dbTimeInterval, ## an interval [a,b] of times
dbEnum, ## some enum
dbSet, ## set of enum values
dbArray, ## an array of values
dbComposite, ## composite type (record, struct, etc)
dbUrl, ## a URL
dbUuid, ## a UUID
dbInet, ## an IP address
dbMacAddress, ## a MAC address
dbGeometry, ## some geometric type
dbPoint, ## Point on a plane (x,y)
dbLine, ## Infinite line ((x1,y1),(x2,y2))
dbLseg, ## Finite line segment ((x1,y1),(x2,y2))
dbBox, ## Rectangular box ((x1,y1),(x2,y2))
dbPath, ## Closed or open path (similar to polygon) ((x1,y1),...)
dbPolygon, ## Polygon (similar to closed path) ((x1,y1),...)
dbCircle, ## Circle <(x,y),r> (center point and radius)
dbUser1, ## user definable datatype 1 (for unknown extensions)
dbUser2, ## user definable datatype 2 (for unknown extensions)
dbUser3, ## user definable datatype 3 (for unknown extensions)
dbUser4, ## user definable datatype 4 (for unknown extensions)
dbUser5 ## user definable datatype 5 (for unknown extensions)
DbType* = object ## describes a database type
kind*: DbTypeKind ## the kind of the described type
notNull*: bool ## does the type contain NULL?
name*: string ## the name of the type
size*: Natural ## the size of the datatype; 0 if of variable size
maxReprLen*: Natural ## maximal length required for the representation
DbType* = object ## describes a database type
kind*: DbTypeKind ## the kind of the described type
notNull*: bool ## does the type contain NULL?
name*: string ## the name of the type
size*: Natural ## the size of the datatype; 0 if of variable size
maxReprLen*: Natural ## maximal length required for the representation
precision*, scale*: Natural ## precision and scale of the number
min*, max*: BiggestInt ## the minimum and maximum of allowed values
validValues*: seq[string] ## valid values of an enum or a set
min*, max*: BiggestInt ## the minimum and maximum of allowed values
validValues*: seq[string] ## valid values of an enum or a set
DbColumn* = object ## information about a database column
name*: string ## name of the column

View File

@@ -32,10 +32,10 @@ when not defined(nimscript):
type
Distribution* {.pure.} = enum ## the list of known distributions
Windows ## some version of Windows
Posix ## some Posix system
MacOSX ## some version of OSX
Linux ## some version of Linux
Windows ## some version of Windows
Posix ## some Posix system
MacOSX ## some version of OSX
Linux ## some version of Linux
Ubuntu
Debian
Gentoo
@@ -133,8 +133,9 @@ const
LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware,
Distribution.ArchLinux}
var unameRes, releaseRes, hostnamectlRes: string ## we cache the result of the 'uname -a'
## execution for faster platform detections.
# we cache the result of the 'uname -a'
# execution for faster platform detections.
var unameRes, releaseRes, hostnamectlRes: string
template unameRelease(cmd, cache): untyped =
if cache.len == 0:
@@ -173,7 +174,8 @@ proc detectOsImpl(d: Distribution): bool =
result = defined(haiku)
else:
let dd = toLowerAscii($d)
result = dd in toLowerAscii(uname()) or dd in toLowerAscii(release()) or ("operating system: " & dd) in toLowerAscii(hostnamectl())
result = dd in toLowerAscii(uname()) or dd in toLowerAscii(release()) or
("operating system: " & dd) in toLowerAscii(hostnamectl())
template detectOs*(d: untyped): bool =
## Distro/OS detection. For convenience the
@@ -184,7 +186,7 @@ template detectOs*(d: untyped): bool =
when not defined(nimble):
var foreignDeps: seq[string] = @[]
proc foreignCmd*(cmd: string; requiresSudo=false) =
proc foreignCmd*(cmd: string; requiresSudo = false) =
## Registers a foreign command to the intern list of commands
## that can be queried later.
let c = (if requiresSudo: "sudo " else: "") & cmd

View File

@@ -59,7 +59,7 @@ import strutils
type
LibHandle* = pointer ## a handle to a dynamically loaded library
proc loadLib*(path: string, globalSymbols=false): LibHandle {.gcsafe.}
proc loadLib*(path: string, globalSymbols = false): LibHandle {.gcsafe.}
## loads a library from `path`. Returns nil if the library could not
## be loaded.
@@ -96,7 +96,7 @@ proc libCandidates*(s: string, dest: var seq[string]) =
else:
add(dest, s)
proc loadLibPattern*(pattern: string, globalSymbols=false): LibHandle =
proc loadLibPattern*(pattern: string, globalSymbols = false): LibHandle =
## loads a library with name matching `pattern`, similar to what `dlimport`
## pragma does. Returns nil if the library could not be loaded.
## Warning: this proc uses the GC and so cannot be used to load the GC.
@@ -117,7 +117,7 @@ when defined(posix) and not defined(nintendoswitch):
#
import posix
proc loadLib(path: string, globalSymbols=false): LibHandle =
proc loadLib(path: string, globalSymbols = false): LibHandle =
let flags =
if globalSymbols: RTLD_NOW or RTLD_GLOBAL
else: RTLD_NOW
@@ -141,7 +141,7 @@ elif defined(nintendoswitch):
raise newException(OSError, "dlopen not implemented on Nintendo Switch!")
proc dlsym(lib: LibHandle, name: cstring): pointer =
raise newException(OSError, "dlsym not implemented on Nintendo Switch!")
proc loadLib(path: string, global_symbols=false): LibHandle =
proc loadLib(path: string, global_symbols = false): LibHandle =
raise newException(OSError, "loadLib not implemented on Nintendo Switch!")
proc loadLib(): LibHandle =
raise newException(OSError, "loadLib not implemented on Nintendo Switch!")
@@ -158,7 +158,7 @@ elif defined(windows) or defined(dos):
#
type
HMODULE {.importc: "HMODULE".} = pointer
FARPROC {.importc: "FARPROC".} = pointer
FARPROC {.importc: "FARPROC".} = pointer
proc FreeLibrary(lib: HMODULE) {.importc, header: "<windows.h>", stdcall.}
proc winLoadLibrary(path: cstring): HMODULE {.
@@ -166,7 +166,7 @@ elif defined(windows) or defined(dos):
proc getProcAddress(lib: HMODULE, name: cstring): FARPROC {.
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
proc loadLib(path: string, globalSymbols=false): LibHandle =
proc loadLib(path: string, globalSymbols = false): LibHandle =
result = cast[LibHandle](winLoadLibrary(path))
proc loadLib(): LibHandle =
result = cast[LibHandle](winLoadLibrary(nil))

View File

@@ -34,66 +34,68 @@ when defined(windows):
while i < a.len and j < b.len:
if a[i] in {'-', '_'}: inc i
if b[j] in {'-', '_'}: inc j
if i < a.len and j < b.len and a[i].toLowerAscii != b[j].toLowerAscii: return false
if i < a.len and j < b.len and
a[i].toLowerAscii != b[j].toLowerAscii:
return false
inc i
inc j
result = i == a.len and j == b.len
const
winEncodings = [
(1, "OEMCP"), # current OEM codepage
(037, "IBM037"), # IBM EBCDIC US-Canada
(437, "IBM437"), # OEM United States
(500, "IBM500"), # IBM EBCDIC International
(708, "ASMO-708"), # Arabic (ASMO 708)
(709, "ASMO_449"), # Arabic (ASMO-449+, BCON V4)
(710, ""), # Arabic - Transparent Arabic
(720, "DOS-720"), # Arabic (Transparent ASMO); Arabic (DOS)
(737, "ibm737"), # OEM Greek (formerly 437G); Greek (DOS)
(775, "ibm775"), # OEM Baltic; Baltic (DOS)
(850, "ibm850"), # OEM Multilingual Latin 1; Western European (DOS)
(852, "ibm852"), # OEM Latin 2; Central European (DOS)
(855, "IBM855"), # OEM Cyrillic (primarily Russian)
(857, "ibm857"), # OEM Turkish; Turkish (DOS)
(858, "IBM00858"), # OEM Multilingual Latin 1 + Euro symbol
(860, "IBM860"), # OEM Portuguese; Portuguese (DOS)
(861, "ibm861"), # OEM Icelandic; Icelandic (DOS)
(862, "DOS-862"), # OEM Hebrew; Hebrew (DOS)
(863, "IBM863"), # OEM French Canadian; French Canadian (DOS)
(864, "IBM864"), # OEM Arabic; Arabic (864)
(865, "IBM865"), # OEM Nordic; Nordic (DOS)
(866, "cp866"), # OEM Russian; Cyrillic (DOS)
(869, "ibm869"), # OEM Modern Greek; Greek, Modern (DOS)
(870, "IBM870"), # IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2
(874, "windows-874"), # ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows)
(875, "cp875"), # IBM EBCDIC Greek Modern
(932, "shift_jis"), # ANSI/OEM Japanese; Japanese (Shift-JIS)
(936, "gb2312"), # ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)
(1, "OEMCP"), # current OEM codepage
(037, "IBM037"), # IBM EBCDIC US-Canada
(437, "IBM437"), # OEM United States
(500, "IBM500"), # IBM EBCDIC International
(708, "ASMO-708"), # Arabic (ASMO 708)
(709, "ASMO_449"), # Arabic (ASMO-449+, BCON V4)
(710, ""), # Arabic - Transparent Arabic
(720, "DOS-720"), # Arabic (Transparent ASMO); Arabic (DOS)
(737, "ibm737"), # OEM Greek (formerly 437G); Greek (DOS)
(775, "ibm775"), # OEM Baltic; Baltic (DOS)
(850, "ibm850"), # OEM Multilingual Latin 1; Western European (DOS)
(852, "ibm852"), # OEM Latin 2; Central European (DOS)
(855, "IBM855"), # OEM Cyrillic (primarily Russian)
(857, "ibm857"), # OEM Turkish; Turkish (DOS)
(858, "IBM00858"), # OEM Multilingual Latin 1 + Euro symbol
(860, "IBM860"), # OEM Portuguese; Portuguese (DOS)
(861, "ibm861"), # OEM Icelandic; Icelandic (DOS)
(862, "DOS-862"), # OEM Hebrew; Hebrew (DOS)
(863, "IBM863"), # OEM French Canadian; French Canadian (DOS)
(864, "IBM864"), # OEM Arabic; Arabic (864)
(865, "IBM865"), # OEM Nordic; Nordic (DOS)
(866, "cp866"), # OEM Russian; Cyrillic (DOS)
(869, "ibm869"), # OEM Modern Greek; Greek, Modern (DOS)
(870, "IBM870"), # IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2
(874, "windows-874"), # ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows)
(875, "cp875"), # IBM EBCDIC Greek Modern
(932, "shift_jis"), # ANSI/OEM Japanese; Japanese (Shift-JIS)
(936, "gb2312"), # ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)
(949, "ks_c_5601-1987"), # ANSI/OEM Korean (Unified Hangul Code)
(950, "big5"), # ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5)
(1026, "IBM1026"), # IBM EBCDIC Turkish (Latin 5)
(1047, "IBM01047"), # IBM EBCDIC Latin 1/Open System
(1140, "IBM01140"), # IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro)
(1141, "IBM01141"), # IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro)
(1142, "IBM01142"), # IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro)
(1143, "IBM01143"), # IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro)
(1144, "IBM01144"), # IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro)
(1145, "IBM01145"), # IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro)
(1146, "IBM01146"), # IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro)
(1147, "IBM01147"), # IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro)
(1148, "IBM01148"), # IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro)
(1149, "IBM01149"), # IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro)
(1200, "utf-16"), # Unicode UTF-16, little endian byte order (BMP of ISO 10646); available only to managed applications
(1201, "unicodeFFFE"), # Unicode UTF-16, big endian byte order; available only to managed applications
(1250, "windows-1250"), # ANSI Central European; Central European (Windows)
(1251, "windows-1251"), # ANSI Cyrillic; Cyrillic (Windows)
(1252, "windows-1252"), # ANSI Latin 1; Western European (Windows)
(1253, "windows-1253"), # ANSI Greek; Greek (Windows)
(1254, "windows-1254"), # ANSI Turkish; Turkish (Windows)
(1255, "windows-1255"), # ANSI Hebrew; Hebrew (Windows)
(1256, "windows-1256"), # ANSI Arabic; Arabic (Windows)
(1257, "windows-1257"), # ANSI Baltic; Baltic (Windows)
(1258, "windows-1258"), # ANSI/OEM Vietnamese; Vietnamese (Windows)
(950, "big5"), # ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5)
(1026, "IBM1026"), # IBM EBCDIC Turkish (Latin 5)
(1047, "IBM01047"), # IBM EBCDIC Latin 1/Open System
(1140, "IBM01140"), # IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro)
(1141, "IBM01141"), # IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro)
(1142, "IBM01142"), # IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro)
(1143, "IBM01143"), # IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro)
(1144, "IBM01144"), # IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro)
(1145, "IBM01145"), # IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro)
(1146, "IBM01146"), # IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro)
(1147, "IBM01147"), # IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro)
(1148, "IBM01148"), # IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro)
(1149, "IBM01149"), # IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro)
(1200, "utf-16"), # Unicode UTF-16, little endian byte order (BMP of ISO 10646); available only to managed applications
(1201, "unicodeFFFE"), # Unicode UTF-16, big endian byte order; available only to managed applications
(1250, "windows-1250"), # ANSI Central European; Central European (Windows)
(1251, "windows-1251"), # ANSI Cyrillic; Cyrillic (Windows)
(1252, "windows-1252"), # ANSI Latin 1; Western European (Windows)
(1253, "windows-1253"), # ANSI Greek; Greek (Windows)
(1254, "windows-1254"), # ANSI Turkish; Turkish (Windows)
(1255, "windows-1255"), # ANSI Hebrew; Hebrew (Windows)
(1256, "windows-1256"), # ANSI Arabic; Arabic (Windows)
(1257, "windows-1257"), # ANSI Baltic; Baltic (Windows)
(1258, "windows-1258"), # ANSI/OEM Vietnamese; Vietnamese (Windows)
(1250, "cp-1250"), # ANSI Central European; Central European (Windows)
(1251, "cp-1251"), # ANSI Cyrillic; Cyrillic (Windows)
@@ -105,106 +107,106 @@ when defined(windows):
(1257, "cp-1257"), # ANSI Baltic; Baltic (Windows)
(1258, "cp-1258"), # ANSI/OEM Vietnamese; Vietnamese (Windows)
(1361, "Johab"), # Korean (Johab)
(10000, "macintosh"), # MAC Roman; Western European (Mac)
(10001, "x-mac-japanese"), # Japanese (Mac)
(10002, "x-mac-chinesetrad"), # MAC Traditional Chinese (Big5); Chinese Traditional (Mac)
(10003, "x-mac-korean"), # Korean (Mac)
(10004, "x-mac-arabic"), # Arabic (Mac)
(10005, "x-mac-hebrew"), # Hebrew (Mac)
(10006, "x-mac-greek"), # Greek (Mac)
(10007, "x-mac-cyrillic"), # Cyrillic (Mac)
(10008, "x-mac-chinesesimp"), # MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac)
(10010, "x-mac-romanian"), # Romanian (Mac)
(10017, "x-mac-ukrainian"), # Ukrainian (Mac)
(10021, "x-mac-thai"), # Thai (Mac)
(10029, "x-mac-ce"), # MAC Latin 2; Central European (Mac)
(10079, "x-mac-icelandic"), # Icelandic (Mac)
(10081, "x-mac-turkish"), # Turkish (Mac)
(10082, "x-mac-croatian"), # Croatian (Mac)
(12000, "utf-32"), # Unicode UTF-32, little endian byte order; available only to managed applications
(12001, "utf-32BE"), # Unicode UTF-32, big endian byte order; available only to managed applications
(20000, "x-Chinese_CNS"), # CNS Taiwan; Chinese Traditional (CNS)
(20001, "x-cp20001"), # TCA Taiwan
(20002, "x_Chinese-Eten"), # Eten Taiwan; Chinese Traditional (Eten)
(20003, "x-cp20003"), # IBM5550 Taiwan
(20004, "x-cp20004"), # TeleText Taiwan
(20005, "x-cp20005"), # Wang Taiwan
(20105, "x-IA5"), # IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5)
(20106, "x-IA5-German"), # IA5 German (7-bit)
(20107, "x-IA5-Swedish"), # IA5 Swedish (7-bit)
(20108, "x-IA5-Norwegian"), # IA5 Norwegian (7-bit)
(20127, "us-ascii"), # US-ASCII (7-bit)
(20261, "x-cp20261"), # T.61
(20269, "x-cp20269"), # ISO 6937 Non-Spacing Accent
(20273, "IBM273"), # IBM EBCDIC Germany
(20277, "IBM277"), # IBM EBCDIC Denmark-Norway
(20278, "IBM278"), # IBM EBCDIC Finland-Sweden
(20280, "IBM280"), # IBM EBCDIC Italy
(20284, "IBM284"), # IBM EBCDIC Latin America-Spain
(20285, "IBM285"), # IBM EBCDIC United Kingdom
(20290, "IBM290"), # IBM EBCDIC Japanese Katakana Extended
(20297, "IBM297"), # IBM EBCDIC France
(20420, "IBM420"), # IBM EBCDIC Arabic
(20423, "IBM423"), # IBM EBCDIC Greek
(20424, "IBM424"), # IBM EBCDIC Hebrew
(1361, "Johab"), # Korean (Johab)
(10000, "macintosh"), # MAC Roman; Western European (Mac)
(10001, "x-mac-japanese"), # Japanese (Mac)
(10002, "x-mac-chinesetrad"), # MAC Traditional Chinese (Big5); Chinese Traditional (Mac)
(10003, "x-mac-korean"), # Korean (Mac)
(10004, "x-mac-arabic"), # Arabic (Mac)
(10005, "x-mac-hebrew"), # Hebrew (Mac)
(10006, "x-mac-greek"), # Greek (Mac)
(10007, "x-mac-cyrillic"), # Cyrillic (Mac)
(10008, "x-mac-chinesesimp"), # MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac)
(10010, "x-mac-romanian"), # Romanian (Mac)
(10017, "x-mac-ukrainian"), # Ukrainian (Mac)
(10021, "x-mac-thai"), # Thai (Mac)
(10029, "x-mac-ce"), # MAC Latin 2; Central European (Mac)
(10079, "x-mac-icelandic"), # Icelandic (Mac)
(10081, "x-mac-turkish"), # Turkish (Mac)
(10082, "x-mac-croatian"), # Croatian (Mac)
(12000, "utf-32"), # Unicode UTF-32, little endian byte order; available only to managed applications
(12001, "utf-32BE"), # Unicode UTF-32, big endian byte order; available only to managed applications
(20000, "x-Chinese_CNS"), # CNS Taiwan; Chinese Traditional (CNS)
(20001, "x-cp20001"), # TCA Taiwan
(20002, "x_Chinese-Eten"), # Eten Taiwan; Chinese Traditional (Eten)
(20003, "x-cp20003"), # IBM5550 Taiwan
(20004, "x-cp20004"), # TeleText Taiwan
(20005, "x-cp20005"), # Wang Taiwan
(20105, "x-IA5"), # IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5)
(20106, "x-IA5-German"), # IA5 German (7-bit)
(20107, "x-IA5-Swedish"), # IA5 Swedish (7-bit)
(20108, "x-IA5-Norwegian"), # IA5 Norwegian (7-bit)
(20127, "us-ascii"), # US-ASCII (7-bit)
(20261, "x-cp20261"), # T.61
(20269, "x-cp20269"), # ISO 6937 Non-Spacing Accent
(20273, "IBM273"), # IBM EBCDIC Germany
(20277, "IBM277"), # IBM EBCDIC Denmark-Norway
(20278, "IBM278"), # IBM EBCDIC Finland-Sweden
(20280, "IBM280"), # IBM EBCDIC Italy
(20284, "IBM284"), # IBM EBCDIC Latin America-Spain
(20285, "IBM285"), # IBM EBCDIC United Kingdom
(20290, "IBM290"), # IBM EBCDIC Japanese Katakana Extended
(20297, "IBM297"), # IBM EBCDIC France
(20420, "IBM420"), # IBM EBCDIC Arabic
(20423, "IBM423"), # IBM EBCDIC Greek
(20424, "IBM424"), # IBM EBCDIC Hebrew
(20833, "x-EBCDIC-KoreanExtended"), # IBM EBCDIC Korean Extended
(20838, "IBM-Thai"), # IBM EBCDIC Thai
(20866, "koi8-r"), # Russian (KOI8-R); Cyrillic (KOI8-R)
(20871, "IBM871"), # IBM EBCDIC Icelandic
(20880, "IBM880"), # IBM EBCDIC Cyrillic Russian
(20905, "IBM905"), # IBM EBCDIC Turkish
(20924, "IBM00924"), # IBM EBCDIC Latin 1/Open System (1047 + Euro symbol)
(20932, "EUC-JP"), # Japanese (JIS 0208-1990 and 0121-1990)
(20936, "x-cp20936"), # Simplified Chinese (GB2312); Chinese Simplified (GB2312-80)
(20949, "x-cp20949"), # Korean Wansung
(21025, "cp1025"), # IBM EBCDIC Cyrillic Serbian-Bulgarian
(21027, ""), # (deprecated)
(21866, "koi8-u"), # Ukrainian (KOI8-U); Cyrillic (KOI8-U)
(28591, "iso-8859-1"), # ISO 8859-1 Latin 1; Western European (ISO)
(28592, "iso-8859-2"), # ISO 8859-2 Central European; Central European (ISO)
(28593, "iso-8859-3"), # ISO 8859-3 Latin 3
(28594, "iso-8859-4"), # ISO 8859-4 Baltic
(28595, "iso-8859-5"), # ISO 8859-5 Cyrillic
(28596, "iso-8859-6"), # ISO 8859-6 Arabic
(28597, "iso-8859-7"), # ISO 8859-7 Greek
(28598, "iso-8859-8"), # ISO 8859-8 Hebrew; Hebrew (ISO-Visual)
(28599, "iso-8859-9"), # ISO 8859-9 Turkish
(28603, "iso-8859-13"), # ISO 8859-13 Estonian
(28605, "iso-8859-15"), # ISO 8859-15 Latin 9
(29001, "x-Europa"), # Europa 3
(38598, "iso-8859-8-i"), # ISO 8859-8 Hebrew; Hebrew (ISO-Logical)
(50220, "iso-2022-jp"), # ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS)
(50221, "csISO2022JP"), # ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana)
(50222, "iso-2022-jp"), # ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI)
(50225, "iso-2022-kr"), # ISO 2022 Korean
(50227, "x-cp50227"), # ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022)
(50229, ""), # ISO 2022 Traditional Chinese
(50930, ""), # EBCDIC Japanese (Katakana) Extended
(50931, ""), # EBCDIC US-Canada and Japanese
(50933, ""), # EBCDIC Korean Extended and Korean
(50935, ""), # EBCDIC Simplified Chinese Extended and Simplified Chinese
(50936, ""), # EBCDIC Simplified Chinese
(50937, ""), # EBCDIC US-Canada and Traditional Chinese
(50939, ""), # EBCDIC Japanese (Latin) Extended and Japanese
(51932, "euc-jp"), # EUC Japanese
(51936, "EUC-CN"), # EUC Simplified Chinese; Chinese Simplified (EUC)
(51949, "euc-kr"), # EUC Korean
(51950, ""), # EUC Traditional Chinese
(52936, "hz-gb-2312"), # HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ)
(54936, "GB18030"), # Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030)
(57002, "x-iscii-de"), # ISCII Devanagari
(57003, "x-iscii-be"), # ISCII Bengali
(57004, "x-iscii-ta"), # ISCII Tamil
(57005, "x-iscii-te"), # ISCII Telugu
(57006, "x-iscii-as"), # ISCII Assamese
(57007, "x-iscii-or"), # ISCII Oriya
(57008, "x-iscii-ka"), # ISCII Kannada
(57009, "x-iscii-ma"), # ISCII Malayalam
(57010, "x-iscii-gu"), # ISCII Gujarati
(57011, "x-iscii-pa"), # ISCII Punjabi
(65000, "utf-7"), # Unicode (UTF-7)
(65001, "utf-8")] # Unicode (UTF-8)
(20838, "IBM-Thai"), # IBM EBCDIC Thai
(20866, "koi8-r"), # Russian (KOI8-R); Cyrillic (KOI8-R)
(20871, "IBM871"), # IBM EBCDIC Icelandic
(20880, "IBM880"), # IBM EBCDIC Cyrillic Russian
(20905, "IBM905"), # IBM EBCDIC Turkish
(20924, "IBM00924"), # IBM EBCDIC Latin 1/Open System (1047 + Euro symbol)
(20932, "EUC-JP"), # Japanese (JIS 0208-1990 and 0121-1990)
(20936, "x-cp20936"), # Simplified Chinese (GB2312); Chinese Simplified (GB2312-80)
(20949, "x-cp20949"), # Korean Wansung
(21025, "cp1025"), # IBM EBCDIC Cyrillic Serbian-Bulgarian
(21027, ""), # (deprecated)
(21866, "koi8-u"), # Ukrainian (KOI8-U); Cyrillic (KOI8-U)
(28591, "iso-8859-1"), # ISO 8859-1 Latin 1; Western European (ISO)
(28592, "iso-8859-2"), # ISO 8859-2 Central European; Central European (ISO)
(28593, "iso-8859-3"), # ISO 8859-3 Latin 3
(28594, "iso-8859-4"), # ISO 8859-4 Baltic
(28595, "iso-8859-5"), # ISO 8859-5 Cyrillic
(28596, "iso-8859-6"), # ISO 8859-6 Arabic
(28597, "iso-8859-7"), # ISO 8859-7 Greek
(28598, "iso-8859-8"), # ISO 8859-8 Hebrew; Hebrew (ISO-Visual)
(28599, "iso-8859-9"), # ISO 8859-9 Turkish
(28603, "iso-8859-13"), # ISO 8859-13 Estonian
(28605, "iso-8859-15"), # ISO 8859-15 Latin 9
(29001, "x-Europa"), # Europa 3
(38598, "iso-8859-8-i"), # ISO 8859-8 Hebrew; Hebrew (ISO-Logical)
(50220, "iso-2022-jp"), # ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS)
(50221, "csISO2022JP"), # ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana)
(50222, "iso-2022-jp"), # ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI)
(50225, "iso-2022-kr"), # ISO 2022 Korean
(50227, "x-cp50227"), # ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022)
(50229, ""), # ISO 2022 Traditional Chinese
(50930, ""), # EBCDIC Japanese (Katakana) Extended
(50931, ""), # EBCDIC US-Canada and Japanese
(50933, ""), # EBCDIC Korean Extended and Korean
(50935, ""), # EBCDIC Simplified Chinese Extended and Simplified Chinese
(50936, ""), # EBCDIC Simplified Chinese
(50937, ""), # EBCDIC US-Canada and Traditional Chinese
(50939, ""), # EBCDIC Japanese (Latin) Extended and Japanese
(51932, "euc-jp"), # EUC Japanese
(51936, "EUC-CN"), # EUC Simplified Chinese; Chinese Simplified (EUC)
(51949, "euc-kr"), # EUC Korean
(51950, ""), # EUC Traditional Chinese
(52936, "hz-gb-2312"), # HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ)
(54936, "GB18030"), # Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030)
(57002, "x-iscii-de"), # ISCII Devanagari
(57003, "x-iscii-be"), # ISCII Bengali
(57004, "x-iscii-ta"), # ISCII Tamil
(57005, "x-iscii-te"), # ISCII Telugu
(57006, "x-iscii-as"), # ISCII Assamese
(57007, "x-iscii-or"), # ISCII Oriya
(57008, "x-iscii-ka"), # ISCII Kannada
(57009, "x-iscii-ma"), # ISCII Malayalam
(57010, "x-iscii-gu"), # ISCII Gujarati
(57011, "x-iscii-pa"), # ISCII Punjabi
(65000, "utf-7"), # Unicode (UTF-7)
(65001, "utf-8")] # Unicode (UTF-8)
when false:
# not needed yet:
@@ -231,7 +233,8 @@ when defined(windows):
result = ""
proc getACP(): CodePage {.stdcall, importc: "GetACP", dynlib: "kernel32".}
proc getGetConsoleCP(): CodePage {.stdcall, importc: "GetConsoleCP", dynlib: "kernel32".}
proc getGetConsoleCP(): CodePage {.stdcall, importc: "GetConsoleCP",
dynlib: "kernel32".}
proc multiByteToWideChar(
codePage: CodePage,
@@ -249,8 +252,8 @@ when defined(windows):
cchWideChar: cint,
lpMultiByteStr: cstring,
cbMultiByte: cint,
lpDefaultChar: cstring=nil,
lpUsedDefaultChar: pointer=nil): cint {.
lpDefaultChar: cstring = nil,
lpUsedDefaultChar: pointer = nil): cint {.
stdcall, importc: "WideCharToMultiByte", dynlib: "kernel32".}
else:
@@ -394,7 +397,8 @@ when defined(windows):
else:
assert(false) # cannot happen
proc convertWin(codePageFrom: CodePage, codePageTo: CodePage, s: string): string =
proc convertWin(codePageFrom: CodePage, codePageTo: CodePage,
s: string): string =
# special case: empty string: needed because MultiByteToWideChar, WideCharToMultiByte
# return 0 in case of error
if s.len == 0: return ""
@@ -410,8 +414,10 @@ when defined(windows):
raise newException(EncodingError, message)
# in case it's already UTF-16 little endian - conversion can be simplified
let wideString = if int(codePageFrom) == 1200: s else: convertToWideString(codePageFrom, s)
return if int(codePageTo) == 1200: wideString else: convertFromWideString(codePageTo, wideString)
let wideString = if int(codePageFrom) == 1200: s
else: convertToWideString(codePageFrom, s)
return if int(codePageTo) == 1200: wideString
else: convertFromWideString(codePageTo, wideString)
proc convert*(c: EncodingConverter, s: string): string =
## converts `s` to `destEncoding` that was given to the converter `c`. It
@@ -540,4 +546,4 @@ when not defined(testing) and isMainModule and defined(windows):
result = convert(original, "utf-8", "utf-16")
doAssert(result == "")
result = convert(original, "windows-1251", "koi8-r")
doAssert(result == "")
doAssert(result == "")

View File

@@ -55,13 +55,13 @@ when useBuiltinSwap:
tmp = op(tmp)
copyMem(outp, addr tmp, sizeof(T))
proc swapEndian64*(outp, inp: pointer) {.inline, noSideEffect.}=
proc swapEndian64*(outp, inp: pointer) {.inline, noSideEffect.} =
swapOpImpl(uint64, builtin_bswap64)
proc swapEndian32*(outp, inp: pointer) {.inline, noSideEffect.}=
proc swapEndian32*(outp, inp: pointer) {.inline, noSideEffect.} =
swapOpImpl(uint32, builtin_bswap32)
proc swapEndian16*(outp, inp: pointer) {.inline, noSideEffect.}=
proc swapEndian16*(outp, inp: pointer) {.inline, noSideEffect.} =
swapOpImpl(uint16, builtin_bswap16)
else:

View File

@@ -10,7 +10,7 @@
## Floating-point environment. Handling of floating-point rounding and
## exceptions (overflow, division by zero, etc.).
{.deadCodeElim: on.} # dce option deprecated
{.deadCodeElim: on.} # dce option deprecated
when defined(Posix) and not defined(genode):
{.passl: "-lm".}
@@ -103,26 +103,26 @@ proc feupdateenv*(envp: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
## according to saved exceptions.
const
FLT_RADIX = 2 ## the radix of the exponent representation
FLT_RADIX = 2 ## the radix of the exponent representation
FLT_MANT_DIG = 24 ## the number of base FLT_RADIX digits in the mantissa part of a float
FLT_DIG = 6 ## the number of digits of precision of a float
FLT_MIN_EXP = -125 # the minimum value of base FLT_RADIX in the exponent part of a float
FLT_MAX_EXP = 128 # the maximum value of base FLT_RADIX in the exponent part of a float
FLT_MIN_10_EXP = -37 ## the minimum value in base 10 of the exponent part of a float
FLT_MAX_10_EXP = 38 ## the maximum value in base 10 of the exponent part of a float
FLT_MIN = 1.17549435e-38'f32 ## the minimum value of a float
FLT_MAX = 3.40282347e+38'f32 ## the maximum value of a float
FLT_EPSILON = 1.19209290e-07'f32 ## the difference between 1 and the least value greater than 1 of a float
FLT_MANT_DIG = 24 ## the number of base FLT_RADIX digits in the mantissa part of a float
FLT_DIG = 6 ## the number of digits of precision of a float
FLT_MIN_EXP = -125 ## the minimum value of base FLT_RADIX in the exponent part of a float
FLT_MAX_EXP = 128 ## the maximum value of base FLT_RADIX in the exponent part of a float
FLT_MIN_10_EXP = -37 ## the minimum value in base 10 of the exponent part of a float
FLT_MAX_10_EXP = 38 ## the maximum value in base 10 of the exponent part of a float
FLT_MIN = 1.17549435e-38'f32 ## the minimum value of a float
FLT_MAX = 3.40282347e+38'f32 ## the maximum value of a float
FLT_EPSILON = 1.19209290e-07'f32 ## the difference between 1 and the least value greater than 1 of a float
DBL_MANT_DIG = 53 ## the number of base FLT_RADIX digits in the mantissa part of a double
DBL_DIG = 15 ## the number of digits of precision of a double
DBL_MIN_EXP = -1021 ## the minimum value of base FLT_RADIX in the exponent part of a double
DBL_MAX_EXP = 1024 ## the maximum value of base FLT_RADIX in the exponent part of a double
DBL_MIN_10_EXP = -307 ## the minimum value in base 10 of the exponent part of a double
DBL_MAX_10_EXP = 308 ## the maximum value in base 10 of the exponent part of a double
DBL_MIN = 2.2250738585072014E-308 ## the minimal value of a double
DBL_MAX = 1.7976931348623157E+308 ## the minimal value of a double
DBL_MANT_DIG = 53 ## the number of base FLT_RADIX digits in the mantissa part of a double
DBL_DIG = 15 ## the number of digits of precision of a double
DBL_MIN_EXP = -1021 ## the minimum value of base FLT_RADIX in the exponent part of a double
DBL_MAX_EXP = 1024 ## the maximum value of base FLT_RADIX in the exponent part of a double
DBL_MIN_10_EXP = -307 ## the minimum value in base 10 of the exponent part of a double
DBL_MAX_10_EXP = 308 ## the maximum value in base 10 of the exponent part of a double
DBL_MIN = 2.2250738585072014E-308 ## the minimal value of a double
DBL_MAX = 1.7976931348623157E+308 ## the minimal value of a double
DBL_EPSILON = 2.2204460492503131E-16 ## the difference between 1 and the least value greater than 1 of a double
template fpRadix*: int = FLT_RADIX

View File

@@ -45,7 +45,7 @@
## * `tables module <tables.html>`_ for hash tables
type
Hash* = int ## A hash value. Hash tables using these values should
Hash* = int ## A hash value. Hash tables using these values should
## always have a size of a power of two and can use the ``and``
## operator instead of ``mod`` for truncation of the hash value.
@@ -451,7 +451,7 @@ when isMainModule:
doAssert hashIgnoreStyle("aa_bb_AAaa1234") == hashIgnoreCase("aaBBAAAa1234")
block smallSize: # no multibyte hashing
let
xx = @['H','i']
xx = @['H', 'i']
ii = @[72'u8, 105]
ss = "Hi"
doAssert hash(xx) == hash(ii)
@@ -460,8 +460,8 @@ when isMainModule:
doAssert hash(ss) == hash(ss, 0, ss.high)
block largeSize: # longer than 4 characters
let
xx = @['H','e','l','l','o']
xxl = @['H','e','l','l','o','w','e','e','n','s']
xx = @['H', 'e', 'l', 'l', 'o']
xxl = @['H', 'e', 'l', 'l', 'o', 'w', 'e', 'e', 'n', 's']
ssl = "Helloweens"
doAssert hash(xxl) == hash(ssl)
doAssert hash(xxl) == hash(xxl, 0, xxl.high)

View File

@@ -32,7 +32,7 @@ import
const
coreAttr* = " accesskey class contenteditable dir hidden id lang " &
"spellcheck style tabindex title translate " ## HTML DOM Core Attributes
"spellcheck style tabindex title translate " ## HTML DOM Core Attributes
eventAttr* = "onabort onblur oncancel oncanplay oncanplaythrough onchange " &
"onclick oncuechange ondblclick ondurationchange onemptied onended " &
"onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload " &
@@ -41,7 +41,7 @@ const
"onpause onplay onplaying onprogress onratechange onreset onresize " &
"onscroll onseeked onseeking onselect onshow onstalled onsubmit " &
"onsuspend ontimeupdate ontoggle onvolumechange onwaiting " ## HTML DOM Event Attributes
ariaAttr* = " role " ## HTML DOM Aria Attributes
ariaAttr* = " role " ## HTML DOM Aria Attributes
commonAttr* = coreAttr & eventAttr & ariaAttr ## HTML DOM Common Attributes
proc getIdent(e: NimNode): string {.compileTime.} =
@@ -572,7 +572,7 @@ macro title*(e: varargs[untyped]): untyped =
macro tr*(e: varargs[untyped]): untyped =
## generates the HTML ``tr`` element.
result = xmlCheckedTag(e, "tr", commonAttr)
result = xmlCheckedTag(e, "tr", commonAttr)
macro track*(e: varargs[untyped]): untyped =
## generates the HTML ``track`` element.
@@ -606,7 +606,7 @@ macro wbr*(e: varargs[untyped]): untyped =
runnableExamples:
let nim = "Nim"
assert h1(a(href="http://nim-lang.org", nim)) ==
assert h1(a(href = "http://nim-lang.org", nim)) ==
"""<h1><a href="http://nim-lang.org">Nim</a></h1>"""
assert form(action="test", `accept-charset` = "Content-Type") ==
assert form(action = "test", `accept-charset` = "Content-Type") ==
"""<form action="test" accept-charset="Content-Type"></form>"""

View File

@@ -52,7 +52,7 @@
import strutils, streams, parsexml, xmltree, unicode, strtabs
type
HtmlTag* = enum ## list of all supported HTML tags; order will always be
HtmlTag* = enum ## list of all supported HTML tags; order will always be
## alphabetically
tagUnknown, ## unknown HTML element
tagA, ## the HTML ``a`` element
@@ -1945,7 +1945,8 @@ proc untilElementEnd(x: var XmlParser, result: XmlNode,
adderr(expected(x, result))
# this seems to do better match error corrections in browsers:
while x.kind in {xmlElementEnd, xmlWhitespace}:
if x.kind == xmlElementEnd and cmpIgnoreCase(x.elemName, result.tag) == 0:
if x.kind == xmlElementEnd and cmpIgnoreCase(x.elemName,
result.tag) == 0:
break
next(x)
next(x)
@@ -2025,7 +2026,7 @@ proc parseHtml*(s: Stream, filename: string,
#if x.kind != xmlEof:
# adderr(errorMsg(x, "EOF expected"))
while x.kind != xmlEof:
var oldPos = x.bufpos # little hack to see if we made any progess
var oldPos = x.bufpos # little hack to see if we made any progress
result.addNode(parse(x, errors))
if x.bufpos == oldPos:
# force progress!

View File

@@ -254,9 +254,9 @@ type
MultipartData* = ref object
content: seq[string]
ProtocolError* = object of IOError ## exception that is raised when server
## does not conform to the implemented
## protocol
ProtocolError* = object of IOError ## exception that is raised when server
## does not conform to the implemented
## protocol
HttpRequestError* = object of IOError ## Thrown in the ``getContent`` proc
## and ``postContent`` proc,
@@ -302,11 +302,11 @@ proc add*(p: var MultipartData, name, content: string, filename: string = "",
## Add a value to the multipart data. Raises a `ValueError` exception if
## `name`, `filename` or `contentType` contain newline characters.
if {'\c','\L'} in name:
if {'\c', '\L'} in name:
raise newException(ValueError, "name contains a newline character")
if {'\c','\L'} in filename:
if {'\c', '\L'} in filename:
raise newException(ValueError, "filename contains a newline character")
if {'\c','\L'} in contentType:
if {'\c', '\L'} in contentType:
raise newException(ValueError, "contentType contains a newline character")
var str = "Content-Disposition: form-data; name=\"" & name & "\""
@@ -470,11 +470,11 @@ type
HttpClientBase*[SocketType] = ref object
socket: SocketType
connected: bool
currentURL: Uri ## Where we are currently connected.
currentURL: Uri ## Where we are currently connected.
headers*: HttpHeaders ## Headers to send in requests.
maxRedirects: int
userAgent: string
timeout*: int ## Only used for blocking HttpClient for now.
timeout*: int ## Only used for blocking HttpClient for now.
proxy: Proxy
## ``nil`` or the callback to call when request progress changes.
when SocketType is Socket:
@@ -492,7 +492,7 @@ type
parseBodyFut: Future[void]
else:
bodyStream: Stream
getBody: bool ## When `false`, the body is never read in requestAux.
getBody: bool ## When `false`, the body is never read in requestAux.
type
HttpClient* = HttpClientBase[Socket]
@@ -563,7 +563,7 @@ proc close*(client: HttpClient | AsyncHttpClient) =
client.socket.close()
client.connected = false
proc getSocket*(client: HttpClient): Socket =
proc getSocket*(client: HttpClient): Socket =
## Get network socket, useful if you want to find out more details about the connection
##
## this example shows info about local and remote endpoints
@@ -575,7 +575,7 @@ proc getSocket*(client: HttpClient): Socket =
##
return client.socket
proc getSocket*(client: AsyncHttpClient): AsyncSocket =
proc getSocket*(client: AsyncHttpClient): AsyncSocket =
return client.socket
proc reportProgress(client: HttpClient | AsyncHttpClient,
@@ -756,7 +756,7 @@ proc parseResponse(client: HttpClient | AsyncHttpClient,
if line[linei] != ':': httpError("invalid headers")
inc(linei) # Skip :
result.headers.add(name, line[linei.. ^1].strip())
result.headers.add(name, line[linei .. ^1].strip())
if result.headers.len > headerLimit:
httpError("too many headers")
@@ -827,7 +827,8 @@ proc newConnection(client: HttpClient | AsyncHttpClient,
connectUrl.hostname = url.hostname
connectUrl.port = if url.port != "": url.port else: "443"
let proxyHeaderString = generateHeaders(connectUrl, $HttpConnect, newHttpHeaders(), "", client.proxy)
let proxyHeaderString = generateHeaders(connectUrl, $HttpConnect,
newHttpHeaders(), "", client.proxy)
await client.socket.send(proxyHeaderString)
let proxyResp = await parseResponse(client, false)

View File

@@ -28,24 +28,24 @@ type
HttpVer11,
HttpVer10
HttpMethod* = enum ## the requested HttpMethod
HttpHead, ## Asks for the response identical to the one that would
## correspond to a GET request, but without the response
## body.
HttpGet, ## Retrieves the specified resource.
HttpPost, ## Submits data to be processed to the identified
## resource. The data is included in the body of the
## request.
HttpPut, ## Uploads a representation of the specified resource.
HttpDelete, ## Deletes the specified resource.
HttpTrace, ## Echoes back the received request, so that a client
## can see what intermediate servers are adding or
## changing in the request.
HttpOptions, ## Returns the HTTP methods that the server supports
## for specified address.
HttpConnect, ## Converts the request connection to a transparent
## TCP/IP tunnel, usually used for proxies.
HttpPatch ## Applies partial modifications to a resource.
HttpMethod* = enum ## the requested HttpMethod
HttpHead, ## Asks for the response identical to the one that would
## correspond to a GET request, but without the response
## body.
HttpGet, ## Retrieves the specified resource.
HttpPost, ## Submits data to be processed to the identified
## resource. The data is included in the body of the
## request.
HttpPut, ## Uploads a representation of the specified resource.
HttpDelete, ## Deletes the specified resource.
HttpTrace, ## Echoes back the received request, so that a client
## can see what intermediate servers are adding or
## changing in the request.
HttpOptions, ## Returns the HTTP methods that the server supports
## for specified address.
HttpConnect, ## Converts the request connection to a transparent
## TCP/IP tunnel, usually used for proxies.
HttpPatch ## Applies partial modifications to a resource.
const
@@ -323,4 +323,4 @@ when isMainModule:
test[key] = value
doAssert test["foobar"] == ""
doAssert parseHeader("foobar:") == ("foobar", @[""])
doAssert parseHeader("foobar:") == ("foobar", @[""])

View File

@@ -30,7 +30,7 @@
## ``JNull``. You check the kind of this object variant by using the ``kind``
## accessor.
##
## For a ``JsonNode`` who's kind is ``JObject``, you can acess its fields using
## For a ``JsonNode`` who's kind is ``JObject``, you can access its fields using
## the ``[]`` operator. The following example shows how to do this:
##
## .. code-block:: Nim
@@ -406,7 +406,7 @@ macro `%*`*(x: untyped): untyped =
## `%` for every element.
result = toJson(x)
proc `==`* (a, b: JsonNode): bool =
proc `==`*(a, b: JsonNode): bool =
## Check two nodes for equality
if a.isNil:
if b.isNil: return true
@@ -428,13 +428,13 @@ proc `==`* (a, b: JsonNode): bool =
of JArray:
result = a.elems == b.elems
of JObject:
# we cannot use OrderedTable's equality here as
# the order does not matter for equality here.
if a.fields.len != b.fields.len: return false
for key, val in a.fields:
if not b.fields.hasKey(key): return false
if b.fields[key] != val: return false
result = true
# we cannot use OrderedTable's equality here as
# the order does not matter for equality here.
if a.fields.len != b.fields.len: return false
for key, val in a.fields:
if not b.fields.hasKey(key): return false
if b.fields[key] != val: return false
result = true
proc hash*(n: OrderedTable[string, JsonNode]): Hash {.noSideEffect.}
@@ -502,7 +502,8 @@ proc contains*(node: JsonNode, val: JsonNode): bool =
assert(node.kind == JArray)
find(node.elems, val) >= 0
proc existsKey*(node: JsonNode, key: string): bool {.deprecated: "use 'hasKey' instead".} =
proc existsKey*(node: JsonNode, key: string): bool {.
deprecated: "use 'hasKey' instead".} =
node.hasKey(key)
proc `{}`*(node: JsonNode, keys: varargs[string]): JsonNode =
@@ -538,7 +539,8 @@ proc getOrDefault*(node: JsonNode, key: string): JsonNode =
if not isNil(node) and node.kind == JObject:
result = node.fields.getOrDefault(key)
template simpleGetOrDefault*{`{}`(node, [key])}(node: JsonNode, key: string): JsonNode = node.getOrDefault(key)
template simpleGetOrDefault*{`{}`(node, [key])}(node: JsonNode,
key: string): JsonNode = node.getOrDefault(key)
proc `{}=`*(node: JsonNode, keys: varargs[string], value: JsonNode) =
## Traverses the node and tries to set the value at the given location
@@ -691,7 +693,7 @@ proc pretty*(node: JsonNode, indent = 2): string =
## Similar to prettyprint in Python.
runnableExamples:
let j = %* {"name": "Isaac", "books": ["Robot Dreams"],
"details": {"age":35, "pi":3.1415}}
"details": {"age": 35, "pi": 3.1415}}
doAssert pretty(j) == """
{
"name": "Isaac",
@@ -721,14 +723,14 @@ proc toUgly*(result: var string, node: JsonNode) =
result.add "["
for child in node.elems:
if comma: result.add ","
else: comma = true
else: comma = true
result.toUgly child
result.add "]"
of JObject:
result.add "{"
for key, value in pairs(node.fields):
if comma: result.add ","
else: comma = true
else: comma = true
key.escapeJson(result)
result.add ":"
result.toUgly value
@@ -1331,7 +1333,8 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
(
var map = `tableInit`[`tableKeyType`, `tableValueType`]();
verifyJsonKind(`jsonNode`, {JObject}, astToStr(`jsonNode`));
for `forLoopKey` in keys(`jsonNode`.fields): map[`forLoopKey`] = `constructorNode`;
for `forLoopKey` in keys(`jsonNode`.fields): map[
`forLoopKey`] = `constructorNode`;
map
)
of "ref":
@@ -1374,7 +1377,8 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
(
var list: `typeSym`;
verifyJsonKind(`jsonNode`, {JArray}, astToStr(`jsonNode`));
for `forLoopI` in 0 ..< `jsonNode`.len: list[`forLoopI`] =`constructorNode`;
for `forLoopI` in 0 ..< `jsonNode`.len: list[
`forLoopI`] = `constructorNode`;
list
)
of "tuple":
@@ -1640,11 +1644,11 @@ when isMainModule:
except:
doAssert(false, "IndexError thrown for valid index")
doAssert(testJson{"b"}.getStr()=="asd", "Couldn't fetch a singly nested key with {}")
doAssert(testJson{"b"}.getStr() == "asd", "Couldn't fetch a singly nested key with {}")
doAssert(isNil(testJson{"nonexistent"}), "Non-existent keys should return nil")
doAssert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
doAssert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
doAssert(testJson{"a"}==parseJson"[1, 2, 3, 4]", "Didn't return a non-JObject when there was one to be found")
doAssert(testJson{"a"} == parseJson"[1, 2, 3, 4]", "Didn't return a non-JObject when there was one to be found")
doAssert(isNil(parseJson("[1, 2, 3]"){"foo"}), "Indexing directly into a list should return nil")
# Generator:
@@ -1669,10 +1673,10 @@ when isMainModule:
const hisAge = 31
var j3 = %*
[ { "name": "John"
[ {"name": "John"
, "age": herAge
}
, { "name": "Susan"
, {"name": "Susan"
, "age": hisAge
}
]
@@ -1708,7 +1712,8 @@ when isMainModule:
except IndexError: doAssert(true)
var parsed2 = parseFile("tests/testdata/jsontest2.json")
doAssert(parsed2{"repository", "description"}.str=="IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}")
doAssert(parsed2{"repository", "description"}.str ==
"IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}")
doAssert escapeJsonUnquoted("\10Foo🎃barÄ") == "\\nFoo🎃barÄ"
doAssert escapeJsonUnquoted("\0\7\20") == "\\u0000\\u0007\\u0014" # for #7887
@@ -1752,15 +1757,15 @@ when isMainModule:
# Generate constructors for range[T] types
block:
type
Q1 = range[0'u8 .. 50'u8]
Q1 = range[0'u8 .. 50'u8]
Q2 = range[0'u16 .. 50'u16]
Q3 = range[0'u32 .. 50'u32]
Q4 = range[0'i8 .. 50'i8]
Q4 = range[0'i8 .. 50'i8]
Q5 = range[0'i16 .. 50'i16]
Q6 = range[0'i32 .. 50'i32]
Q7 = range[0'f32 .. 50'f32]
Q8 = range[0'f64 .. 50'f64]
Q9 = range[0 .. 50]
Q9 = range[0 .. 50]
X = object
m1: Q1

View File

@@ -12,7 +12,7 @@
## which work for mixed float/int operands.
## All operations convert the integer operand into the
## type of the float operand. For numerical expressions, the return
## type is always the type of the float involved in the expresssion,
## type is always the type of the float involved in the expression,
## i.e., there is no auto conversion from float32 to float64.
##
## Note: In general, auto-converting from int to float loses

View File

@@ -15,7 +15,7 @@ import
strutils, streams
const
EndOfFile* = '\0' ## end of file marker
EndOfFile* = '\0' ## end of file marker
NewLines* = {'\c', '\L'}
# Buffer handling:
@@ -27,13 +27,13 @@ const
type
BaseLexer* = object of RootObj ## the base lexer. Inherit your lexer from
## this object.
bufpos*: int ## the current position within the buffer
buf*: string ## the buffer itself
input: Stream ## the input stream
lineNumber*: int ## the current line number
bufpos*: int ## the current position within the buffer
buf*: string ## the buffer itself
input: Stream ## the input stream
lineNumber*: int ## the current line number
sentinel: int
lineStart: int # index of last line start in buffer
offsetBase*: int # use ``offsetBase + bufpos`` to get the offset
lineStart: int # index of last line start in buffer
offsetBase*: int # use ``offsetBase + bufpos`` to get the offset
refillChars: set[char]
proc close*(L: var BaseLexer) =
@@ -65,11 +65,11 @@ proc fillBuffer(L: var BaseLexer) =
charsRead = L.input.readDataStr(L.buf, toCopy ..< toCopy + L.sentinel + 1)
s = toCopy + charsRead
if charsRead < L.sentinel + 1:
L.buf[s] = EndOfFile # set end marker
L.buf[s] = EndOfFile # set end marker
L.sentinel = s
else:
# compute sentinel:
dec(s) # BUGFIX (valgrind)
dec(s) # BUGFIX (valgrind)
while true:
assert(s < L.buf.len)
while s >= 0 and L.buf[s] notin L.refillChars: dec(s)
@@ -92,7 +92,7 @@ proc fillBuffer(L: var BaseLexer) =
proc fillBaseLexer(L: var BaseLexer, pos: int): int =
assert(pos <= L.sentinel)
if pos < L.sentinel:
result = pos + 1 # nothing to do
result = pos + 1 # nothing to do
else:
fillBuffer(L)
L.offsetBase += pos
@@ -142,7 +142,7 @@ proc open*(L: var BaseLexer, input: Stream, bufLen: int = 8192;
L.buf = newString(bufLen)
L.sentinel = bufLen - 1
L.lineStart = 0
L.lineNumber = 1 # lines start at 1
L.lineNumber = 1 # lines start at 1
fillBuffer(L)
skipUtf8Bom(L)

View File

@@ -147,7 +147,7 @@ when not defined(js):
import os
type
Level* = enum
Level* = enum ## \
## Enumeration of logging levels.
##
## Debug messages represent the lowest logging level, and fatal error
@@ -173,22 +173,21 @@ type
## any messages with a level lower than the threshold. There is also
## a global filter that applies to all log messages, and it can be changed
## using the `setLogFilter proc<#setLogFilter,Level>`_.
lvlAll, ## All levels active
lvlDebug, ## Debug level and above are active
lvlInfo, ## Info level and above are active
lvlNotice, ## Notice level and above are active
lvlWarn, ## Warn level and above are active
lvlError, ## Error level and above are active
lvlFatal, ## Fatal level and above are active
lvlNone ## No levels active; nothing is logged
lvlAll, ## All levels active
lvlDebug, ## Debug level and above are active
lvlInfo, ## Info level and above are active
lvlNotice, ## Notice level and above are active
lvlWarn, ## Warn level and above are active
lvlError, ## Error level and above are active
lvlFatal, ## Fatal level and above are active
lvlNone ## No levels active; nothing is logged
const
LevelNames*: array[Level, string] = [
"DEBUG", "DEBUG", "INFO", "NOTICE", "WARN", "ERROR", "FATAL", "NONE"
] ## Array of strings representing each logging level.
] ## Array of strings representing each logging level.
defaultFmtStr* = "$levelname " ## \
## The default format string.
defaultFmtStr* = "$levelname " ## The default format string.
verboseFmtStr* = "$levelid, [$datetime] -- $appname: " ## \
## A more verbose format string.
##
@@ -211,8 +210,8 @@ type
## * `ConsoleLogger<#ConsoleLogger>`_
## * `FileLogger<#FileLogger>`_
## * `RollingFileLogger<#RollingFileLogger>`_
levelThreshold*: Level ## Only messages that are at or above this
## threshold will be logged
levelThreshold*: Level ## Only messages that are at or above this
## threshold will be logged
fmtStr*: string ## Format string to prepend to each log message;
## defaultFmtStr is the default
@@ -240,7 +239,7 @@ when not defined(js):
## See also:
## * `ConsoleLogger<#ConsoleLogger>`_
## * `RollingFileLogger<#RollingFileLogger>`_
file*: File ## The wrapped file
file*: File ## The wrapped file
RollingFileLogger* = ref object of FileLogger
## A logger that writes log messages to a file while performing log
@@ -255,17 +254,18 @@ when not defined(js):
## * `ConsoleLogger<#ConsoleLogger>`_
## * `FileLogger<#FileLogger>`_
maxLines: int # maximum number of lines
curLine : int
curLine: int
baseName: string # initial filename
baseMode: FileMode # initial file mode
logFiles: int # how many log files already created, e.g. basename.1, basename.2...
bufSize: int # size of output buffer (-1: use system defaults, 0: unbuffered, >0: fixed buffer size)
var
level {.threadvar.}: Level ## global log filter
level {.threadvar.}: Level ## global log filter
handlers {.threadvar.}: seq[Logger] ## handlers with their own log levels
proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): string =
proc substituteLog*(frmt: string, level: Level,
args: varargs[string, `$`]): string =
## Formats a log message at the specified level with the given format string.
##
## The `format variables<#basic-usage-format-strings>`_ present within
@@ -307,7 +307,7 @@ proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): str
of "date": result.add(getDateStr())
of "time": result.add(getClockStr())
of "datetime": result.add(getDateStr() & "T" & getClockStr())
of "app": result.add(app)
of "app": result.add(app)
of "appdir":
when not defined(js): result.add(app.splitFile.dir)
of "appname":
@@ -369,13 +369,14 @@ method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) =
try:
var handle = stdout
if logger.useStderr:
handle = stderr
handle = stderr
writeLine(handle, ln)
if level in {lvlError, lvlFatal}: flushFile(handle)
except IOError:
discard
proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr, useStderr=false): ConsoleLogger =
proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr,
useStderr = false): ConsoleLogger =
## Creates a new `ConsoleLogger<#ConsoleLogger>`_.
##
## By default, log messages are written to ``stdout``. If ``useStderr`` is
@@ -563,7 +564,7 @@ when not defined(js):
result.fmtStr = fmtStr
result.maxLines = maxLines
result.bufSize = bufSize
result.file = open(filename, mode, bufSize=result.bufSize)
result.file = open(filename, mode, bufSize = result.bufSize)
result.curLine = 0
result.baseName = filename
result.baseMode = mode
@@ -616,7 +617,8 @@ when not defined(js):
rotate(logger)
logger.logFiles.inc
logger.curLine = 0
logger.file = open(logger.baseName, logger.baseMode, bufSize = logger.bufSize)
logger.file = open(logger.baseName, logger.baseMode,
bufSize = logger.bufSize)
writeLine(logger.file, substituteLog(logger.fmtStr, level, args))
if level in {lvlError, lvlFatal}: flushFile(logger.file)

View File

@@ -384,7 +384,7 @@ when not defined(testing) and isMainModule:
test4.b = "ref string test: B"
testit(test4)
var test5 = @[(0,1),(2,3),(4,5)]
var test5 = @[(0, 1), (2, 3), (4, 5)]
testit(test5)
var test6: set[char] = {'A'..'Z', '_'}

Some files were not shown because too many files have changed in this diff Show More