Compare commits

...

53 Commits

Author SHA1 Message Date
narimiran
dde13f38c9 revert adding a test, should have been part of 00cd7b8ca backport 2020-10-26 11:22:09 +01:00
Jason Beetham
fabbb7ea3e Fixed iteration limit hit from execproc (#15723) [backport:1.2] [backport:1.4]
When calling procs from Nim in Nimscript you could hit the VM iteration limit even though the code is functioning properly. This resolves that by making the iteration limit reset eachtime you call a proc.

(cherry picked from commit a87617956f)
2020-10-26 11:14:55 +01:00
Danil Yarantsev
76971596ad Add support to the latest LibreSSL version (#15715) [backport:1.2] [backport:1.4]
(cherry picked from commit b2740f5c63)
2020-10-26 11:14:49 +01:00
Timothee Cour
d777a8f86c fix #15704 #15597 wrong VM register was freed (#15705)
(cherry picked from commit d4c2e2c53f)
2020-10-26 10:29:54 +01:00
Clyybber
00cd7b8ca4 Revert "fixes #15280 [backport:1.2] (#15281)" (#15700)
This reverts commit 3f00a738db.

(cherry picked from commit d4022ebe53)
2020-10-24 17:18:44 +02:00
narimiran
714fd81199 remove tests that shouldn't have been backported in previous commit 2020-10-15 14:00:15 +02:00
Andreas Rumpf
59b5bdc2c6 renamed '=' to '=copy' [backport:1.2] (#15585)
(cherry picked from commit da4aa2e1fb)
2020-10-15 13:32:25 +02:00
Igor Ribeiro de Assis
4642a3485c Fix crash in parsexml (#15582) (#15583)
Co-authored-by: Igor Ribeiro de Assis <igor.ribeiro_de_assis@zeiss.com>
(cherry picked from commit 42c180c665)
2020-10-15 13:27:46 +02:00
genotrance
58d711ec57 Bump nimble (#15573)
(cherry picked from commit a4c28394be)
2020-10-15 13:27:29 +02:00
narimiran
8f3f264160 bump NimVersion to 1.2.8 2020-10-14 11:01:02 +02:00
Andreas Rumpf
2ce9352285 sigmatch: hotfix [backport] (#15565)
(cherry picked from commit c664fb2843)
2020-10-14 11:00:47 +02:00
alaviss
825f358c8b terminal: fix fgColor/bgColor commands [backport] (#15554)
Since #8296, fgSetColor is no longer a global. These commands were
probably left out from the change as an oversight, so some tests have
been added to make sure this won't happen again.

(cherry picked from commit d1af9587b8)
2020-10-13 21:21:52 +02:00
Christopher Dunn
17bed3c966 Fix doc for CountTable (#15561) [backport]
(cherry picked from commit f1d81dc6e6)
2020-10-13 08:43:46 +02:00
Christian Ulrich
eb51fa5ead close socket in getPrimaryIPAddr (#15538) [backport]
(cherry picked from commit c7ccbfac39)
2020-10-13 08:43:27 +02:00
alaviss
dc1c251a2c tslow_tables: wait for an additional 2 seconds (#14266)
This test runtime tends to hover around the 5s mark depending on how
loaded the system currently is. This causes the test to fail a lot
during CI, per analytics:
https://dev.azure.com/nim-lang/Nim/_test/analytics?definitionId=1&contextType=build

Give the test an extra 2 seconds to account for unrelated overhead.

(cherry picked from commit 83435fe696)
2020-10-09 15:09:48 +02:00
narimiran
d6c8a91b72 fix wrong word-wrap in tunknown_named_parameter 2020-10-09 14:55:20 +02:00
Araq
991902e286 fixes a renderer regression
(cherry picked from commit 0ac74ddd74)
2020-10-09 12:06:05 +02:00
narimiran
5534c56d05 manually backport #15506 2020-10-09 12:03:07 +02:00
cooldome
777c28cf45 fix #15516 (#15518)
(cherry picked from commit fe187719ab)
2020-10-09 10:04:24 +02:00
alaviss
3f0432bf8d koch: unify nimble building scripts [backport:1.4] (#15443)
This commit gets rid of buildNimble in favor of the simpler
bundleNimbleExe, which does pretty much the same thing.

(cherry picked from commit 3919f0aa54)
2020-10-07 20:11:18 +02:00
alaviss
bc42ec515e tools/deps: fix git dir check (#15470)
On Windows, a successful call will have a trailing newline appended, so
strip that away before doing any checks.

(cherry picked from commit e3eae3f7c7)
2020-10-07 19:44:35 +02:00
alaviss
60783ccc11 koch, compiler: bundle fusion as part of the source archive (#15409)
This allows distributions to build Nim from the downloaded source
archive without an Internet connection.

(cherry picked from commit d4892e9388)
2020-10-07 19:44:00 +02:00
Andreas Rumpf
9599d95caa fixes https://github.com/nim-lang/RFCs/issues/257 [backport:1.2] (#15479)
(cherry picked from commit 2288188fe9)
2020-10-06 09:50:36 +02:00
Andreas Rumpf
e3c85f5885 remove nim.cfg file change lefover [backport:1.2] (#15469)
(cherry picked from commit ff70ff529d)
2020-10-06 08:49:06 +02:00
Andreas Rumpf
da03b5ca8b closureiters: fixes #15243 (#15454) [backport:1.2]
* fixes #15243 [backport:1.2]

(cherry picked from commit aa1d7fe1e9)
2020-10-06 08:48:44 +02:00
Miran
736e1dd0a0 various documentation fixes [backport] (#15422)
(cherry picked from commit eb2a4961c7)
2020-10-06 08:46:54 +02:00
Yuriy Glukhov
c6d51805be Dont assert on setstacksize result in iOS (#15427) [backport:1.2]
(cherry picked from commit 22d0a39932)
2020-10-06 08:46:41 +02:00
Andreas Rumpf
c53c6458b0 finish the stacktraces.nim implementation [backport:1.2] (#15393)
(cherry picked from commit e2d80b15a6)
2020-10-06 08:46:25 +02:00
Andreas Rumpf
eefb13d638 better nativestacktrace support; refs #15284; backport [1.2] (#15384)
* nimStackTraceOverride: enable stack traces in exceptions

This is a two-step stack trace collection scheme, because re-raised
exceptions will collect multiple stack traces but use them rarely, when
printing info about an uncaught exception, so it makes sense to only do
the cheap stack unwinding all the time and the relatively expensive
debugging information collection on-demand.

`asyncfutures` implements its own `$` proc for printing
`seq[StackTraceEntry]`, so we have to add the debugging info there, just
like we do for the private `$` proc in `system/excpt`.

* cleaned up PR #15284

Co-authored-by: Ștefan Talpalaru <stefantalpalaru@yahoo.com>
(cherry picked from commit 1fae66e4df)
2020-10-06 08:45:13 +02:00
Andreas Rumpf
7ef706fef9 fixes #15360 [backport:1.2] (#15378)
(cherry picked from commit c2434d939e)
2020-09-21 18:19:13 +02:00
Andreas Rumpf
4827bf5e88 base64: fixes the error message for an invalid base64 input character [backport:1.2]
(cherry picked from commit cbdda631db)
2020-09-21 18:19:04 +02:00
Andreas Rumpf
2624de0588 fixes #9754 [backport] (#15342)
(cherry picked from commit 8b66412a8b)
2020-09-21 18:18:44 +02:00
flywind
183f876bd1 remove annoying messages when creating orderedTables (#15309)
* nativesockets docs minor [backport: 1.2]

* remove annoying messages

(cherry picked from commit a41b243fea)
2020-09-21 18:15:54 +02:00
alaviss
6eb656a75b Small optimization for the CI pipeline. (#15088)
* azure-pipelines: cache csources to speed up build

Building csources takes about 2-4 mins, and since it hasn't changed for
a long time, employ some caching to cut the time spent.

* azure-pipelines: remove ppa avoidance configs

Testing shows that there aren't any difference between having this and
not having it, so removing this to simplify the code.

(cherry picked from commit c292c57e48)
2020-09-14 09:07:03 +02:00
narimiran
0e457ae92c disable package 'ws' 2020-09-12 08:47:17 +02:00
narimiran
5254e0693e fix failing tests 2020-09-11 15:54:17 +02:00
slangmgh
abe72ba1b3 fix #14203 (#14204)
(cherry picked from commit b56432bd8a)
2020-09-11 14:49:21 +02:00
narimiran
e980256794 fix RangeDefect to RangeError 2020-09-11 14:39:51 +02:00
Andreas Rumpf
7bba0deb1d fixes #15280 [backport:1.2] (#15281)
* fixes #15280 [backport:1.2]

* make tests green again

* adapt tests

(cherry picked from commit 3f00a738db)
2020-09-11 13:58:04 +02:00
flywind
0845e88110 nativesockets docs minor [backport: 1.2] (#15285)
(cherry picked from commit a81610230d)
2020-09-11 13:58:04 +02:00
flywind
040ac6cd2b more Protocol supports in windows (#15274) [backport:1.2]
(cherry picked from commit e08b802d79)
2020-09-11 13:58:04 +02:00
shirleyquirk
1c8ed1de0e Fix c_malloc inside syslocks.nim to take size_t (#15268) [backport]
* update c_malloc's to csize_t

(cherry picked from commit 57f98dae9a)
2020-09-11 13:58:04 +02:00
Miran
b5c90a3431 fix #15257, toHex couldn't handle large uint64 (#15261) [backport:1.2]
(cherry picked from commit 4fb17bc03b)
2020-09-11 13:58:04 +02:00
PMunch
53f3bd9376 Fix sets for architectures with default integers smaller than 32 bits (#15258) [backport]
(cherry picked from commit 244760197c)
2020-09-11 13:58:04 +02:00
Andreas Rumpf
ae688aa7f5 fixes #15210 [backport:1.2] (#15237)
* fixes #15210 [backport:1.2]

* use patched version of bigints library

(cherry picked from commit ff13f8cc3c)
2020-09-11 13:58:04 +02:00
Araq
4e428c5a18 fixes #15207 [backport:1.2]
(cherry picked from commit 40969296e9)
2020-09-11 13:58:04 +02:00
Miran
dc3f74f1c2 [backport] fix #15064, strscans.scanf edge case for '$+' (#15223)
(cherry picked from commit 15ff89cec1)
2020-09-11 13:58:04 +02:00
alaviss
98e73512d1 asyncnet: don't try to close the socket again [backport] (#15174)
The closed flag isn't a good design by any means, but let's have this
working first before I get rid of the flag and potentially create a
non-backportable commit.

(cherry picked from commit 957bf15a08)
2020-09-11 13:58:04 +02:00
Andreas Rumpf
a41ece8d86 fixes #15101 [backport] (#15171)
(cherry picked from commit 2a8bf470af)
2020-09-11 13:58:04 +02:00
Andreas Rumpf
67d729aa2e fixes a collect() bug reported on the forum (#15156) [backport:1.2]
(cherry picked from commit 64aec6eb85)
2020-09-11 13:58:04 +02:00
Andreas Rumpf
0ddf7153b8 fixes #15129 [backport:1.2] (#15144)
(cherry picked from commit d6161e7e9e)
2020-09-11 13:58:04 +02:00
Andreas Rumpf
0aec43e850 fixes #15071 [backport] (#15131)
(cherry picked from commit d23ae49535)
2020-09-11 13:58:04 +02:00
narimiran
f94a3fa671 bump Nim version to 1.2.7 2020-09-11 13:58:04 +02:00
63 changed files with 693 additions and 261 deletions

View File

@@ -51,9 +51,10 @@ jobs:
condition: eq(variables['Agent.OS'], 'Windows_NT')
- checkout: self
fetchDepth: 1
- bash: git clone --depth 1 https://github.com/nim-lang/csources.git
displayName: 'Checkout csources'
- bash: git clone --depth 1 https://github.com/nim-lang/csources
displayName: 'Checkout Nim csources'
- task: NodeTool@0
inputs:
@@ -71,19 +72,12 @@ jobs:
- bash: |
sudo dpkg --add-architecture i386
# Downgrade llvm, libgcc and libstdc++:
# Downgrade llvm:
# - llvm has to be downgraded to have 32bit version installed for sfml.
# - libgcc and libstdc++ have to be downgraded as an optimization to
# prevent the use of the toolchain ppa, which has a terrible download
# speed.
cat << EOF | sudo tee /etc/apt/preferences.d/pin-to-rel
Package: libllvm6.0 libgcc1 libstdc++6
Package: libllvm6.0
Pin: origin "azure.archive.ubuntu.com"
Pin-Priority: 1001
Package: *
Pin: release o=LP-PPA-ubuntu-toolchain-r-test
Pin-Priority: 100
EOF
sudo apt-fast update -qq
@@ -139,8 +133,18 @@ jobs:
make -v
displayName: 'System information'
- bash: echo '##vso[task.setvariable variable=csources_version]'"$(git -C csources rev-parse HEAD)"
displayName: 'Get csources version'
- task: Cache@2
inputs:
key: 'csources | "$(Agent.OS)" | $(CPU) | $(csources_version)'
path: csources/bin
displayName: 'Restore built csources'
- bash: |
ncpu=
ext=
case '$(Agent.OS)' in
'Linux')
ncpu=$(nproc)
@@ -150,19 +154,25 @@ jobs:
;;
'Windows_NT')
ncpu=$NUMBER_OF_PROCESSORS
ext=.exe
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu=$(CPU)
displayName: 'Build csources'
if [[ -x csources/bin/nim$ext ]]; then
echo "Found cached compiler, skipping build"
else
make -C csources -j $ncpu CC=gcc ucpu=$(CPU) koch=no
fi
cp csources/bin/nim$ext bin
displayName: 'Build 1-stage compiler from csources'
- bash: nim c koch
displayName: 'Build koch'
# set result to omit the "bash exited with error code '1'" message
- bash: |
./koch runCI || echo '##vso[task.complete result=Failed]'
- bash: ./koch runCI || echo '##vso[task.complete result=Failed]'
displayName: 'Run CI'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)

View File

@@ -129,6 +129,19 @@
## Language changes
- In newruntime it is now allowed to assign discriminator field without restrictions as long as case object doesn't have custom destructor. Discriminator value doesn't have to be a constant either. If you have custom destructor for case object and you do want to freely assign discriminator fields, it is recommended to refactor object into 2 objects like this:
- The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts
`wasMoved` calls where needed.
- The `=` hook is now called `=copy` for clarity. The old name `=` is still available so there
is no need to update your code. This change was backported to 1.2 too so you can use the
more readability `=copy` without loss of compatibility.
- In the newruntime it is now allowed to assign to the discriminator field
without restrictions as long as case object doesn't have custom destructor.
The discriminator value doesn't have to be a constant either. If you have a
custom destructor for a case object and you do want to freely assign discriminator
fields, it is recommended to refactor object into 2 objects like this:
```nim
type
MyObj = object

View File

@@ -1327,7 +1327,7 @@ const
MaxLockLevel* = 1000'i16
UnknownLockLevel* = TLockLevel(1001'i16)
AttachedOpToStr*: array[TTypeAttachedOp, string] = [
"=destroy", "=", "=sink", "=trace", "=dispose", "=deepcopy"]
"=destroy", "=copy", "=sink", "=trace", "=dispose", "=deepcopy"]
proc `$`*(x: TLockLevel): string =
if x.ord == UnspecifiedLockLevel.ord: result = "<unspecified>"

View File

@@ -1781,9 +1781,9 @@ template binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) =
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) =
case int(getSize(p.config, skipTypes(e[1].typ, abstractVar)))
of 1: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&7U)))!=0)")
of 2: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&15U)))!=0)")
of 4: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&31U)))!=0)")
of 1: binaryExprIn(p, e, a, b, d, "(($1 &((NU8)1<<((NU)($2)&7U)))!=0)")
of 2: binaryExprIn(p, e, a, b, d, "(($1 &((NU16)1<<((NU)($2)&15U)))!=0)")
of 4: binaryExprIn(p, e, a, b, d, "(($1 &((NU32)1<<((NU)($2)&31U)))!=0)")
of 8: binaryExprIn(p, e, a, b, d, "(($1 &((NU64)1<<((NU)($2)&63U)))!=0)")
else: binaryExprIn(p, e, a, b, d, "(($1[(NU)($2)>>3] &(1U<<((NU)($2)&7U)))!=0)")
@@ -1981,25 +1981,30 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc) =
checkUnsignedConversions notin p.config.legacyFeatures):
discard "no need to generate a check because it was disabled"
else:
let raiser =
case skipTypes(n.typ, abstractVarRange).kind
of tyUInt..tyUInt64, tyChar: "raiseRangeErrorU"
of tyFloat..tyFloat128: "raiseRangeErrorF"
else: "raiseRangeErrorI"
discard cgsym(p.module, raiser)
# This seems to be bug-compatible with Nim version 1 but what we
# should really do here is to check if uint64Value < high(int)
let n0t = n[0].typ
let boundaryCast =
if n0t.skipTypes(abstractVarRange).kind in {tyUInt, tyUInt32, tyUInt64} or
(n0t.sym != nil and sfSystemModule in n0t.sym.owner.flags and n0t.sym.name.s == "csize"):
"(NI64)"
else:
""
# emit range check:
linefmt(p, cpsStmts, "if ($6($1) < $2 || $6($1) > $3){ $4($1, $2, $3); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), boundaryCast])
if n0t.kind in {tyUInt, tyUInt64}:
linefmt(p, cpsStmts, "if ($1 > ($6)($3)){ #raiseRangeErrorNoArgs(); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), getTypeDesc(p.module, n0t)])
else:
let raiser =
case skipTypes(n.typ, abstractVarRange).kind
of tyUInt..tyUInt64, tyChar: "raiseRangeErrorU"
of tyFloat..tyFloat128: "raiseRangeErrorF"
else: "raiseRangeErrorI"
discard cgsym(p.module, raiser)
let boundaryCast =
if n0t.skipTypes(abstractVarRange).kind in {tyUInt, tyUInt32, tyUInt64} or
(n0t.sym != nil and sfSystemModule in n0t.sym.owner.flags and n0t.sym.name.s == "csize"):
"(NI64)"
else:
""
linefmt(p, cpsStmts, "if ($6($1) < $2 || $6($1) > $3){ $4($1, $2, $3); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), boundaryCast])
putIntoDest(p, d, n, "(($1) ($2))" %
[getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage)
@@ -2665,9 +2670,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
expr(p, n[1][0], d)
of nkObjDownConv: downConv(p, n, d)
of nkObjUpConv: upConv(p, n, d)
of nkChckRangeF: genRangeChck(p, n, d)
of nkChckRange64: genRangeChck(p, n, d)
of nkChckRange: genRangeChck(p, n, d)
of nkChckRangeF, nkChckRange64, nkChckRange: genRangeChck(p, n, d)
of nkStringToCString: convStrToCStr(p, n, d)
of nkCStringToString: convCStrToStr(p, n, d)
of nkLambdaKinds:
@@ -2941,7 +2944,23 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool): Rope =
proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope =
case n.kind
of nkHiddenStdConv, nkHiddenSubConv:
result = genBracedInit(p, n[1], isConst)
when false:
# XXX The frontend doesn't keep conversions to openArray for us. :-(
# We need to change 'transformConv' first, but that is hard.
if n.typ.kind == tyOpenArray:
assert n[1].kind == nkBracket
let data = genBracedInit(p, n[1], isConst)
let payload = getTempName(p.module)
let ctype = getTypeDesc(p.module, n.typ.skipTypes(abstractInst)[0])
let arrLen = n[1].len
appcg(p.module, cfsData,
"static $5 $1 $3[$2] = $4;$n", [
ctype, arrLen, payload, data,
if isConst: "const" else: ""])
result = "{($1*)&$2, $3}" % [ctype, payload, rope arrLen]
else:
result = genBracedInit(p, n[1], isConst)
else:
var ty = tyNone
if n.typ == nil:

View File

@@ -130,7 +130,8 @@
import
ast, msgs, idents,
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos,
tables, options
type
Ctx = object
@@ -1102,7 +1103,7 @@ proc skipEmptyStates(ctx: Ctx, stateIdx: int): int =
result = ctx.states[stateIdx][0].intVal.int
proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode =
proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode=
result = n
case n.kind
of nkSkip:
@@ -1282,6 +1283,101 @@ proc deleteEmptyStates(ctx: var Ctx) =
else:
inc i
type
PreprocessContext = object
finallys: seq[PNode]
config: ConfigRef
blocks: seq[(PNode, int)]
FreshVarsContext = object
tab: Table[int, PSym]
config: ConfigRef
info: TLineInfo
proc freshVars(n: PNode; c: var FreshVarsContext): PNode =
case n.kind
of nkSym:
let x = c.tab.getOrDefault(n.sym.id)
if x == nil:
result = n
else:
result = newSymNode(x, n.info)
of nkSkip - {nkSym}:
result = n
of nkLetSection, nkVarSection:
result = copyNode(n)
for it in n:
if it.kind in {nkIdentDefs, nkVarTuple}:
let idefs = copyNode(it)
for v in 0..it.len-3:
if it[v].kind == nkSym:
let x = copySym(it[v].sym)
c.tab[it[v].sym.id] = x
idefs.add newSymNode(x)
else:
idefs.add it[v]
for rest in it.len-2 ..< it.len: idefs.add it[rest]
result.add idefs
else:
result.add it
of nkRaiseStmt:
localError(c.config, c.info, "unsupported control flow: 'finally: ... raise' duplicated because of 'break'")
else:
result = n
for i in 0..<n.safeLen:
result[i] = freshVars(n[i], c)
proc preprocess(c: var PreprocessContext; n: PNode): PNode =
# in order to fix bug #15243 without risking regressions, we preprocess
# the AST so that 'break' statements inside a 'try finally' also have the
# finally section. We need to duplicate local variables here and also
# detect: 'finally: raises X' which is currently not supported. We produce
# an error for this case for now. All this will be done properly with Yuriy's
# patch.
result = n
case n.kind
of nkTryStmt:
let f = n.lastSon
if f.kind == nkFinally:
c.finallys.add f.lastSon
for i in 0 ..< n.len:
result[i] = preprocess(c, n[i])
if f.kind == nkFinally:
discard c.finallys.pop()
of nkWhileStmt, nkBlockStmt:
c.blocks.add((n, c.finallys.len))
for i in 0 ..< n.len:
result[i] = preprocess(c, n[i])
discard c.blocks.pop()
of nkBreakStmt:
if c.blocks.len == 0:
discard
else:
var fin = -1
if n[0].kind == nkEmpty:
fin = c.blocks[^1][1]
elif n[0].kind == nkSym:
for i in countdown(c.blocks.high, 0):
if c.blocks[i][0].kind == nkBlockStmt and c.blocks[i][0][0].kind == nkSym and
c.blocks[i][0][0].sym == n[0].sym:
fin = c.blocks[i][1]
break
if fin >= 0:
result = newNodeI(nkStmtList, n.info)
for i in countdown(c.finallys.high, fin):
var vars = FreshVarsContext(tab: initTable[int, PSym](), config: c.config, info: n.info)
result.add freshVars(preprocess(c, c.finallys[i]), vars)
result.add n
of nkSkip: discard
else:
for i in 0 ..< n.len:
result[i] = preprocess(c, n[i])
proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
var ctx: Ctx
ctx.g = g
@@ -1294,7 +1390,10 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
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)
var n = n.toStmtList
var pc = PreprocessContext(finallys: @[], config: g.config)
var n = preprocess(pc, n.toStmtList)
#echo "transformed into ", n
#var n = n.toStmtList
discard ctx.newState(n, nil)
let gotoOut = newTree(nkGotoState, g.newIntLit(n.info, -1))

View File

@@ -116,3 +116,4 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimNewIntegerOps")
defineSymbol("nimHasInvariant")
defineSymbol("nimHasStacktraceMsgs")
defineSymbol("nimHasStacktracesModule")

View File

@@ -212,7 +212,7 @@ template isUnpackedTuple(n: PNode): bool =
proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) =
var m = "'" & opname & "' is not available for type <" & typeToString(t) & ">"
if opname == "=" and ri != nil:
if (opname == "=" or opname == "=copy") and ri != nil:
m.add "; requires a copy because it's not the last read of '"
m.add renderTree(ri)
m.add '\''
@@ -301,7 +301,7 @@ proc genCopy(c: var Con; dest, ri: PNode): PNode =
if tfHasOwned in t.flags and ri.kind != nkNilLit:
# try to improve the error message here:
if c.otherRead == nil: discard isLastRead(ri, c)
checkForErrorPragma(c, t, ri, "=")
checkForErrorPragma(c, t, ri, "=copy")
result = genCopyNoCheck(c, dest, ri)
proc addTopVar(c: var Con; v: PNode) =

View File

@@ -77,6 +77,7 @@ Files: "lib"
[Other]
Files: "examples"
Files: "dist/nimble"
Files: "dist/fusion"
Files: "tests"

View File

@@ -62,6 +62,7 @@ type
tkComma, tkSemiColon,
tkColon, tkColonColon, tkEquals, tkDot, tkDotDot, tkBracketLeColon,
tkOpr, tkComment, tkAccent,
# these are fake tokens used by renderer.nim
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr
TTokTypes* = set[TTokType]

View File

@@ -19,5 +19,6 @@ define:useStdoutAsStdmsg
styleCheck:error
@end
#define:useNodeIds
#gc:markAndSweep

View File

@@ -31,6 +31,7 @@ type
TSrcGen* = object
indent*: int
lineLen*: int
col: int
pos*: int # current position for iteration over the buffer
idx*: int # current token index for iteration over the buffer
tokens*: TRenderTokSeq
@@ -109,11 +110,10 @@ proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags; config: ConfigRef) =
g.config = config
proc addTok(g: var TSrcGen, kind: TTokType, s: string; sym: PSym = nil) =
setLen(g.tokens, g.tokens.len + 1)
g.tokens[^1].kind = kind
g.tokens[^1].length = int16(s.len)
g.tokens[^1].sym = sym
g.tokens.add TRenderTok(kind: kind, length: int16(s.len), sym: sym)
g.buf.add(s)
if kind != tkSpaces:
inc g.col, s.len
proc addPendingNL(g: var TSrcGen) =
if g.pendingNL >= 0:
@@ -123,6 +123,7 @@ proc addPendingNL(g: var TSrcGen) =
const newlines = "\n"
addTok(g, tkSpaces, newlines & spaces(g.pendingNL))
g.lineLen = g.pendingNL
g.col = g.pendingNL
g.pendingNL = - 1
g.pendingWhitespace = -1
elif g.pendingWhitespace >= 0:
@@ -131,7 +132,10 @@ proc addPendingNL(g: var TSrcGen) =
proc putNL(g: var TSrcGen, indent: int) =
if g.pendingNL >= 0: addPendingNL(g)
else: addTok(g, tkSpaces, "\n")
else:
addTok(g, tkSpaces, "\n")
g.col = 0
g.pendingNL = indent
g.lineLen = indent
g.pendingWhitespace = -1
@@ -173,16 +177,17 @@ proc put(g: var TSrcGen, kind: TTokType, s: string; sym: PSym = nil) =
addPendingNL(g)
if s.len > 0:
addTok(g, kind, s, sym)
inc(g.lineLen, s.len)
else:
g.pendingWhitespace = s.len
inc g.col, s.len
inc(g.lineLen, s.len)
proc putComment(g: var TSrcGen, s: string) =
if s.len == 0: return
var i = 0
let hi = s.len - 1
var isCode = (s.len >= 2) and (s[1] != ' ')
var ind = g.lineLen
let isCode = (s.len >= 2) and (s[1] != ' ')
let ind = g.col
var com = "## "
while i <= hi:
case s[i]
@@ -208,7 +213,7 @@ proc putComment(g: var TSrcGen, s: string) =
# compute length of the following word:
var j = i
while j <= hi and s[j] > ' ': inc(j)
if not isCode and (g.lineLen + (j - i) > MaxLineLen):
if not isCode and (g.col + (j - i) > MaxLineLen):
put(g, tkComment, com)
optNL(g, ind)
com = "## "
@@ -290,15 +295,18 @@ proc shouldRenderComment(g: var TSrcGen, n: PNode): bool =
proc gcom(g: var TSrcGen, n: PNode) =
assert(n != nil)
if shouldRenderComment(g, n):
var oneSpaceAdded = 0
if (g.pendingNL < 0) and (g.buf.len > 0) and (g.buf[^1] != ' '):
put(g, tkSpaces, Space)
oneSpaceAdded = 1
# Before long comments we cannot make sure that a newline is generated,
# because this might be wrong. But it is no problem in practice.
if (g.pendingNL < 0) and (g.buf.len > 0) and
(g.lineLen < LineCommentColumn):
(g.col < LineCommentColumn):
var ml = maxLineLength(n.comment)
if ml + LineCommentColumn <= MaxLineLen:
put(g, tkSpaces, spaces(LineCommentColumn - g.lineLen))
put(g, tkSpaces, spaces(LineCommentColumn - g.col))
dec g.col, oneSpaceAdded
putComment(g, n.comment) #assert(g.comStack[high(g.comStack)] = n);
proc gcoms(g: var TSrcGen) =

View File

@@ -23,7 +23,7 @@ proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
result = newNode(nkEmpty)
return
case n.kind
of nkEmpty..pred(nkIdent), succ(nkSym)..nkNilLit: result = n
of nkEmpty..pred(nkIdent), succ(nkSym)..nkNilLit: result = copyNode(n)
of nkIdent, nkSym:
result = n
let ident = considerQuotedIdent(c.c, n)
@@ -52,8 +52,7 @@ proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
if n.kind == nkContinueStmt:
localError(c.c.config, n.info,
"'continue' not supported in a 'fields' loop")
result = copyNode(n)
newSons(result, n.len)
result = shallowCopy(n)
for i in 0..<n.len:
result[i] = instFieldLoopBody(c, n[i], forLoop)

View File

@@ -785,7 +785,7 @@ proc track(tracked: PEffects, n: PNode) =
if n.sym.typ != nil and tfHasAsgn in n.sym.typ.flags:
tracked.owner.flags.incl sfInjectDestructors
# bug #15038: ensure consistency
if not hasDestructor(n.typ): n.typ = n.sym.typ
if not hasDestructor(n.typ) and sameType(n.typ, n.sym.typ): n.typ = n.sym.typ
of nkRaiseStmt:
if n[0].kind != nkEmpty:
n[0].info = n.info

View File

@@ -161,7 +161,7 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode =
if it.len == 2:
openScope(c)
it[0] = forceBool(c, semExprWithType(c, it[0]))
it[1] = semExprBranch(c, it[1])
it[1] = semExprBranch(c, it[1], flags)
typ = commonType(typ, it[1])
closeScope(c)
elif it.len == 1:
@@ -722,7 +722,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n
let iterBase = n[^2].typ
var iter = skipTypes(iterBase, {tyGenericInst, tyAlias, tySink, tyOwned})
var iterAfterVarLent = iter.skipTypes({tyLent, tyVar})
var iterAfterVarLent = iter.skipTypes({tyGenericInst, tyAlias, tyLent, tyVar})
# n.len == 3 means that there is one for loop variable
# and thus no tuple unpacking:
if iterAfterVarLent.kind != tyTuple or n.len == 3:
@@ -1748,7 +1748,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
"signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T")
incl(s.flags, sfUsed)
incl(s.flags, sfOverriden)
of "=", "=sink":
of "=", "=copy", "=sink":
if s.magic == mAsgn: return
incl(s.flags, sfUsed)
incl(s.flags, sfOverriden)
@@ -1770,7 +1770,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
# attach these ops to the canonical tySequence
obj = canonType(c, obj)
#echo "ATTACHING TO ", obj.id, " ", s.name.s, " ", cast[int](obj)
let k = if name == "=": attachedAsgn else: attachedSink
let k = if name == "=" or name == "=copy": attachedAsgn else: attachedSink
if obj.attachedOps[k] == s:
discard "forward declared op"
elif obj.attachedOps[k].isNil and tfCheckedForDestructor notin obj.flags:

View File

@@ -1086,7 +1086,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
let x = typeRel(c, f, branch, flags + {trDontBind})
if x == isNone: return isNone
if x < result: result = x
return
return result
of tyAnd:
# XXX: deal with the current dual meaning of tyGenericParam
@@ -1421,7 +1421,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
let ff = rootf[i]
let aa = roota[i]
let res = typeRel(c, ff, aa, nextFlags)
if res != isEqual: result = isGeneric
if res != isNone and res != isEqual: result = isGeneric
if res notin {isEqual, isGeneric}:
if trNoCovariance notin flags and ff.kind == aa.kind:
let paramFlags = rootf.base[i-1].flags

View File

@@ -138,12 +138,13 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, packed: bool, a
accum.offset = szUnknownSize
accum.maxAlign = szUnknownSize
else:
# the union neds to be aligned first, before the offsets can be assigned
# the union needs to be aligned first, before the offsets can be assigned
accum.align(maxChildAlign)
let accumRoot = accum # copy, because each branch should start af the same offset
for i in 1..<n.len:
var branchAccum = accumRoot
var branchAccum = OffsetAccum(offset: accumRoot.offset, maxAlign: 1)
computeObjectOffsetsFoldFunction(conf, n[i].lastSon, packed, branchAccum)
discard finish(branchAccum)
accum.mergeBranch(branchAccum)
of nkRecList:
for i, child in n.sons:
@@ -173,9 +174,10 @@ proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; accum: var
localError(conf, n.info, "Illegal use of ``case`` in union type.")
of nkRecList:
let accumRoot = accum # copy, because each branch should start af the same offset
for i, child in n.sons:
var branchAccum = accumRoot
for child in n.sons:
var branchAccum = OffsetAccum(offset: accumRoot.offset, maxAlign: 1)
computeUnionObjectOffsetsFoldFunction(conf, child, branchAccum)
discard finish(branchAccum)
accum.mergeBranch(branchAccum)
of nkSym:
var size = szUnknownSize

View File

@@ -830,13 +830,6 @@ proc transformExceptBranch(c: PTransf, n: PNode): PNode =
else:
result = transformSons(c, n)
proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} =
# symbols that expand to a complex constant (array, etc.) should not be
# inlined, unless it's the empty array:
result = orig.kind == nkSym and
cnst.kind in {nkCurly, nkPar, nkTupleConstr, nkBracket} and
cnst.len != 0
proc commonOptimizations*(g: ModuleGraph; c: PSym, n: PNode): PNode =
result = n
for i in 0..<n.safeLen:
@@ -1090,15 +1083,15 @@ proc liftDeferAux(n: PNode) =
if n[i].kind == nkDefer:
let deferPart = newNodeI(nkFinally, n[i].info)
deferPart.add n[i][0]
var tryStmt = newNodeI(nkTryStmt, n[i].info)
var body = newNodeI(n.kind, n[i].info)
var tryStmt = newNodeIT(nkTryStmt, n[i].info, n.typ)
var body = newNodeIT(n.kind, n[i].info, n.typ)
if i < last:
body.sons = n.sons[(i+1)..last]
tryStmt.add body
tryStmt.add deferPart
n[i] = tryStmt
n.sons.setLen(i+1)
n.typ = n[i].typ
n.typ = tryStmt.typ
goOn = true
break
for i in 0..n.safeLen-1:

View File

@@ -169,3 +169,10 @@ proc flattenStmts*(n: PNode): PNode =
proc extractRange*(k: TNodeKind, n: PNode, a, b: int): PNode =
result = newNodeI(k, n.info, b-a+1)
for i in 0..b-a: result[i] = n[i+a]
proc dontInlineConstant*(orig, cnst: PNode): bool {.inline.} =
# symbols that expand to a complex constant (array, etc.) should not be
# inlined, unless it's the empty array:
result = orig.kind == nkSym and
cnst.kind in {nkCurly, nkPar, nkTupleConstr, nkBracket, nkObjConstr} and
cnst.len > ord(cnst.kind == nkObjConstr)

View File

@@ -2086,6 +2086,7 @@ proc execute(c: PCtx, start: int): PNode =
result = rawExecute(c, start, tos).regToNode
proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
c.loopIterations = c.config.maxLoopIterationsVM
if sym.kind in routineKinds:
if sym.typ.len-1 != args.len:
localError(c.config, sym.info,

View File

@@ -247,6 +247,8 @@ proc freeTemp(c: PCtx; r: TRegister) =
proc getTempRange(cc: PCtx; n: int; kind: TSlotKind): TRegister =
# if register pressure is high, we re-use more aggressively:
let c = cc.prc
# we could also customize via the following (with proper caching in ConfigRef):
# let highRegisterPressure = cc.config.getConfigVar("vm.highRegisterPressure", "40").parseInt
if c.maxSlots >= HighRegisterPressure or c.maxSlots+n >= high(TRegister):
for i in 0..c.maxSlots-n:
if not c.slots[i].inUse:
@@ -1521,14 +1523,14 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
let tmp = c.genx(ri)
c.preventFalseAlias(le[0], opcWrObj, objR, idx, tmp)
c.freeTemp(tmp)
c.freeTemp(idx)
# c.freeTemp(idx) # BUGFIX, see nkDotExpr
c.freeTemp(objR)
of nkDotExpr:
let dest = c.genx(le[0], {gfNode})
let idx = genField(c, le[1])
let tmp = c.genx(ri)
c.preventFalseAlias(le, opcWrObj, dest, idx, tmp)
c.freeTemp(idx)
# c.freeTemp(idx) # BUGFIX: idx is an immediate (field position), not a register
c.freeTemp(tmp)
c.freeTemp(dest)
of nkDerefExpr, nkHiddenDeref:

View File

@@ -41,7 +41,7 @@ written as:
dealloc(x.data)
x.data = nil
proc `=`*[T](a: var myseq[T]; b: myseq[T]) =
proc `=copy`*[T](a: var myseq[T]; b: myseq[T]) =
# do nothing for self-assignments:
if a.data == b.data: return
`=destroy`(a)
@@ -134,7 +134,7 @@ not free the resources afterwards by setting the object to its default value
default value is written as ``wasMoved(x)``. When not provided the compiler
is using a combination of `=destroy` and `copyMem` instead. This is efficient
hence users rarely need to implement their own `=sink` operator, it is enough to
provide `=destroy` and `=`, compiler will take care about the rest.
provide `=destroy` and `=copy`, compiler will take care about the rest.
The prototype of this hook for a type ``T`` needs to be:
@@ -156,10 +156,10 @@ The general pattern in ``=sink`` looks like:
How self-assignments are handled is explained later in this document.
`=` (copy) hook
`=copy` hook
---------------
The ordinary assignment in Nim conceptually copies the values. The ``=`` hook
The ordinary assignment in Nim conceptually copies the values. The ``=copy`` hook
is called for assignments that couldn't be transformed into ``=sink``
operations.
@@ -167,21 +167,21 @@ The prototype of this hook for a type ``T`` needs to be:
.. code-block:: nim
proc `=`(dest: var T; source: T)
proc `=copy`(dest: var T; source: T)
The general pattern in ``=`` looks like:
The general pattern in ``=copy`` looks like:
.. code-block:: nim
proc `=`(dest: var T; source: T) =
proc `=copy`(dest: var T; source: T) =
# protect against self-assignments:
if dest.field != source.field:
`=destroy`(dest)
dest.field = duplicateResource(source.field)
The ``=`` proc can be marked with the ``{.error.}`` pragma. Then any assignment
The ``=copy`` proc can be marked with the ``{.error.}`` pragma. Then any assignment
that otherwise would lead to a copy is prevented at compile-time.
@@ -199,7 +199,7 @@ Swap
====
The need to check for self-assignments and also the need to destroy previous
objects inside ``=`` and ``=sink`` is a strong indicator to treat
objects inside ``=copy`` and ``=sink`` is a strong indicator to treat
``system.swap`` as a builtin primitive of its own that simply swaps every
field in the involved objects via ``copyMem`` or a comparable mechanism.
In other words, ``swap(a, b)`` is **not** implemented
@@ -320,7 +320,7 @@ not destroyed at the scope exit, but at the proc exit.
x = y
------------------ (copy)
`=`(x, y)
`=copy`(x, y)
f_sink(g())
@@ -330,7 +330,7 @@ not destroyed at the scope exit, but at the proc exit.
f_sink(notLastReadOf y)
-------------------------- (copy-to-sink)
(let tmp; `=`(tmp, y);
(let tmp; `=copy`(tmp, y);
f_sink(tmp))

View File

@@ -10,7 +10,7 @@
#
const
NimbleStableCommit = "63695f490728e3935692c29f3d71944d83bb1e83" # master
NimbleStableCommit = "8f7af860c5ce9634af880a7081c6435e1f2a5148" # master
when not defined(windows):
const
@@ -136,35 +136,11 @@ proc bundleC2nim(args: string) =
proc bundleNimbleExe(latest: bool, args: string) =
let commit = if latest: "HEAD" else: NimbleStableCommit
cloneDependency(distDir, "https://github.com/nim-lang/nimble.git", commit = commit)
cloneDependency(distDir, "https://github.com/nim-lang/nimble.git",
commit = commit, allowBundled = true)
# installer.ini expects it under $nim/bin
nimCompile("dist/nimble/src/nimble.nim",
options = "-d:release --nilseqs:on " & args)
proc buildNimble(latest: bool, args: string) =
# if koch is used for a tar.xz, build the dist/nimble we shipped
# with the tarball:
var installDir = "dist/nimble"
if not latest and dirExists(installDir) and not dirExists("dist/nimble/.git"):
discard "don't do the git dance"
else:
if not dirExists("dist/nimble/.git"):
if dirExists(installDir):
var id = 0
while dirExists("dist/nimble" & $id):
inc id
installDir = "dist/nimble" & $id
# consider using/adapting cloneDependency
exec("git clone -q https://github.com/nim-lang/nimble.git " & installDir)
withDir(installDir):
if latest:
exec("git checkout -f master")
exec("git pull")
else:
exec("git fetch")
exec("git checkout " & NimbleStableCommit)
nimCompile(installDir / "src/nimble.nim",
options = "--noNimblePath --nilseqs:on -d:release " & args)
options = "-d:release --noNimblePath " & args)
proc bundleNimsuggest(args: string) =
nimCompileFold("Compile nimsuggest", "nimsuggest/nimsuggest.nim",
@@ -664,13 +640,13 @@ when isMainModule:
of "temp": temp(op.cmdLineRest)
of "xtemp": xtemp(op.cmdLineRest)
of "wintools": bundleWinTools(op.cmdLineRest)
of "nimble": buildNimble(latest, op.cmdLineRest)
of "nimble": bundleNimbleExe(latest, op.cmdLineRest)
of "nimsuggest": bundleNimsuggest(op.cmdLineRest)
of "toolsnonimble":
buildTools(op.cmdLineRest)
of "tools":
buildTools(op.cmdLineRest)
buildNimble(latest, op.cmdLineRest)
bundleNimbleExe(latest, op.cmdLineRest)
of "pushcsource", "pushcsources": pushCsources()
of "valgrind": valgrind(op.cmdLineRest)
of "c2nim": bundleC2nim(op.cmdLineRest)

View File

@@ -271,7 +271,7 @@ proc setPointer*(x: Any, y: pointer) =
## ``akPointer``, ``akSequence``.
assert x.rawType.kind in {tyString, tyCString, tyRef, tyPtr, tyPointer,
tySequence, tyProc}
cast[ppointer](x.value)[] = y
genericAssign(x.value, y, x.rawType)
proc fieldsAux(p: pointer, n: ptr TNimNode,
ret: var seq[tuple[name: cstring, any: Any]]) =

View File

@@ -531,7 +531,7 @@ proc matchImpl(str: string, pattern: Regex, start, endpos: int, flags: int): Opt
raise RegexInternalError(msg : "Unknown internal error: " & $execRet)
proc match*(str: string, pattern: Regex, start = 0, endpos = int.high): Option[RegexMatch] =
## Like ` ``find(...)`` <#proc-find>`_, but anchored to the start of the
## Like `find(...)<#find,string,Regex,int>`_, but anchored to the start of the
## string.
##
runnableExamples:
@@ -541,11 +541,11 @@ proc match*(str: string, pattern: Regex, start = 0, endpos = int.high): Option[R
return str.matchImpl(pattern, start, endpos, pcre.ANCHORED)
iterator findIter*(str: string, pattern: Regex, start = 0, endpos = int.high): RegexMatch =
## Works the same as ` ``find(...)`` <#proc-find>`_, but finds every
## Works the same as `find(...)<#find,string,Regex,int>`_, but finds every
## non-overlapping match. ``"2222".find(re"22")`` is ``"22", "22"``, not
## ``"22", "22", "22"``.
##
## Arguments are the same as ` ``find(...)`` <#proc-find>`_
## Arguments are the same as `find(...)<#find,string,Regex,int>`_
##
## Variants:
##
@@ -624,7 +624,7 @@ proc split*(str: string, pattern: Regex, maxSplit = -1, start = 0): seq[string]
## Splits the string with the given regex. This works according to the
## rules that Perl and Javascript use.
##
## ``start`` behaves the same as in ` ``find(...)`` <#proc-find>`_.
## ``start`` behaves the same as in `find(...)<#find,string,Regex,int>`_.
##
runnableExamples:
# - If the match is zero-width, then the string is still split:

View File

@@ -9,6 +9,8 @@
import os, tables, strutils, times, heapqueue, options, deques, cstrutils
import "system/stacktraces"
# TODO: This shouldn't need to be included, but should ideally be exported.
type
CallbackFunc = proc () {.closure, gcsafe.}
@@ -311,7 +313,12 @@ proc getHint(entry: StackTraceEntry): string =
if cmpIgnoreStyle(entry.filename, "asyncmacro.nim") == 0:
return "Resumes an async procedure"
proc `$`*(entries: seq[StackTraceEntry]): string =
proc `$`*(stackTraceEntries: seq[StackTraceEntry]): string =
when defined(nimStackTraceOverride):
let entries = addDebuggingInfo(stackTraceEntries)
else:
let entries = stackTraceEntries
result = ""
# Find longest filename & line number combo for alignment purposes.
var longestLeft = 0
@@ -326,10 +333,10 @@ proc `$`*(entries: seq[StackTraceEntry]): string =
# Format the entries.
for entry in entries:
if entry.procname.isNil:
if entry.line == -10:
if entry.line == reraisedFromBegin:
result.add(spaces(indent) & "#[\n")
indent.inc(2)
else:
elif entry.line == reraisedFromEnd:
indent.dec(2)
result.add(spaces(indent) & "]#\n")
continue

View File

@@ -691,8 +691,12 @@ elif defined(nimdoc):
proc close*(socket: AsyncSocket) =
## Closes the socket.
if socket.closed: return
defer:
socket.fd.AsyncFD.closeSocket()
socket.closed = true # TODO: Add extra debugging checks for this.
when defineSsl:
if socket.isSsl:
let res = SSL_shutdown(socket.sslHandle)
@@ -701,7 +705,6 @@ proc close*(socket: AsyncSocket) =
discard
elif res != 1:
raiseSSLError()
socket.closed = true # TODO: Add extra debugging checks for this.
when defineSsl:
proc wrapSocket*(ctx: SslContext, socket: AsyncSocket) =

View File

@@ -230,11 +230,11 @@ proc decode*(s: string): string =
template inputChar(x: untyped) =
let x = int decodeTable[ord(s[inputIndex])]
inc inputIndex
if x == invalidChar:
raise newException(ValueError,
"Invalid base64 format character `" & s[inputIndex] &
"` (ord " & $s[inputIndex].ord & ") at location " & $inputIndex & ".")
inc inputIndex
template outputChar(x: untyped) =
result[outputIndex] = char(x and 255)

View File

@@ -1808,7 +1808,7 @@ proc newOrderedTable*[A, B](pairs: openArray[(A, B)]): <//>OrderedTableRef[A, B]
assert b == {'a': 5, 'b': 9}.newOrderedTable
result = newOrderedTable[A, B](rightSize(pairs.len))
for key, val in items(pairs): result.add(key, val)
for key, val in items(pairs): result[key] = val
proc `[]`*[A, B](t: OrderedTableRef[A, B], key: A): var B =
@@ -2634,7 +2634,7 @@ proc `[]`*[A](t: CountTableRef[A], key: A): int =
## See also:
## * `getOrDefault<#getOrDefault,CountTableRef[A],A,int>`_ to return
## a custom value if the key doesn't exist
## * `mget proc<#mget,CountTableRef[A],A>`_
## * `inc proc<#inc,CountTableRef[A],A>`_ to inc even if missing
## * `[]= proc<#[]%3D,CountTableRef[A],A,int>`_ for inserting a new
## (key, value) pair in the table
## * `hasKey proc<#hasKey,CountTableRef[A],A>`_ for checking if a key
@@ -3002,37 +3002,37 @@ when isMainModule:
block: #5482
var a = [("wrong?", "foo"), ("wrong?", "foo2")].newOrderedTable()
var b = newOrderedTable[string, string](initialSize = 2)
b.add("wrong?", "foo")
b.add("wrong?", "foo2")
b["wrong?"] = "foo"
b["wrong?"] = "foo2"
assert a == b
block: #5482
var a = {"wrong?": "foo", "wrong?": "foo2"}.newOrderedTable()
var b = newOrderedTable[string, string](initialSize = 2)
b.add("wrong?", "foo")
b.add("wrong?", "foo2")
b["wrong?"] = "foo"
b["wrong?"] = "foo2"
assert a == b
block: #5487
var a = {"wrong?": "foo", "wrong?": "foo2"}.newOrderedTable()
var b = newOrderedTable[string, string]() # notice, default size!
b.add("wrong?", "foo")
b.add("wrong?", "foo2")
b["wrong?"] = "foo"
b["wrong?"] = "foo2"
assert a == b
block: #5487
var a = [("wrong?", "foo"), ("wrong?", "foo2")].newOrderedTable()
var b = newOrderedTable[string, string]() # notice, default size!
b.add("wrong?", "foo")
b.add("wrong?", "foo2")
b["wrong?"] = "foo"
b["wrong?"] = "foo2"
assert a == b
block:
var a = {"wrong?": "foo", "wrong?": "foo2"}.newOrderedTable()
var b = [("wrong?", "foo"), ("wrong?", "foo2")].newOrderedTable()
var c = newOrderedTable[string, string]() # notice, default size!
c.add("wrong?", "foo")
c.add("wrong?", "foo2")
c["wrong?"] = "foo"
c["wrong?"] = "foo2"
assert a == b
assert a == c

View File

@@ -68,11 +68,11 @@ type
Protocol* = enum ## third argument to `socket` proc
IPPROTO_TCP = 6, ## Transmission control protocol.
IPPROTO_UDP = 17, ## User datagram protocol.
IPPROTO_IP, ## Internet protocol. Unsupported on Windows.
IPPROTO_IPV6, ## Internet Protocol Version 6. Unsupported on Windows.
IPPROTO_IP, ## Internet protocol.
IPPROTO_IPV6, ## Internet Protocol Version 6.
IPPROTO_RAW, ## Raw IP Packets Protocol. Unsupported on Windows.
IPPROTO_ICMP ## Control message protocol. Unsupported on Windows.
IPPROTO_ICMPV6 ## Control message protocol for IPv6. Unsupported on Windows.
IPPROTO_ICMP ## Internet Control message protocol.
IPPROTO_ICMPV6 ## Internet Control message protocol for IPv6.
Servent* = object ## information about a service
name*: string
@@ -113,7 +113,7 @@ proc `==`*(a, b: Port): bool {.borrow.}
## ``==`` for ports.
proc `$`*(p: Port): string {.borrow.}
## returns the port number as a string
## Returns the port number as a string
proc toInt*(domain: Domain): cint
## Converts the Domain enum to a platform-dependent ``cint``.
@@ -174,7 +174,21 @@ else:
result = cint(ord(typ))
proc toInt(p: Protocol): cint =
result = cint(ord(p))
case p
of IPPROTO_IP:
result = 0.cint
of IPPROTO_ICMP:
result = 1.cint
of IPPROTO_TCP:
result = 6.cint
of IPPROTO_UDP:
result = 17.cint
of IPPROTO_IPV6:
result = 41.cint
of IPPROTO_ICMPV6:
result = 58.cint
else:
result = cint(ord(p))
proc toSockType*(protocol: Protocol): SockType =
result = case protocol
@@ -414,7 +428,7 @@ proc getHostname*(): string {.tags: [ReadIOEffect].} =
result.setLen(x)
proc getSockDomain*(socket: SocketHandle): Domain =
## returns the socket's domain (AF_INET or AF_INET6).
## Returns the socket's domain (AF_INET or AF_INET6).
var name: Sockaddr_in6
var namelen = sizeof(name).SockLen
if getsockname(socket, cast[ptr SockAddr](addr(name)),
@@ -426,7 +440,7 @@ proc getSockDomain*(socket: SocketHandle): Domain =
raise newException(IOError, "Unknown socket family in getSockDomain")
proc getAddrString*(sockAddr: ptr SockAddr): string =
## return the string representation of address within sockAddr
## Returns the string representation of address within sockAddr
if sockAddr.sa_family.cint == nativeAfInet:
result = $inet_ntoa(cast[ptr Sockaddr_in](sockAddr).sin_addr)
elif sockAddr.sa_family.cint == nativeAfInet6:
@@ -459,7 +473,7 @@ when defined(posix) and not defined(nimdoc):
copyMem(addr result.sun_path, path.cstring, path.len + 1)
proc getSockName*(socket: SocketHandle): Port =
## returns the socket's associated port number.
## Returns the socket's associated port number.
var name: Sockaddr_in
when useWinVersion:
name.sin_family = uint16(ord(AF_INET))
@@ -474,7 +488,7 @@ proc getSockName*(socket: SocketHandle): Port =
result = Port(nativesockets.ntohs(name.sin_port))
proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
## returns the socket's local address and port number.
## Returns the socket's local address and port number.
##
## Similar to POSIX's `getsockname`:idx:.
case domain
@@ -511,7 +525,7 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
## returns the socket's peer address and port number.
## Returns the socket's peer address and port number.
##
## Similar to POSIX's `getpeername`:idx:
case domain

View File

@@ -1816,4 +1816,5 @@ proc getPrimaryIPAddr*(dest = parseIpAddress("8.8.8.8")): IpAddress =
else:
newSocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
socket.connect($dest, 80.Port)
socket.getLocalAddr()[0].parseIpAddress()
result = socket.getLocalAddr()[0].parseIpAddress()
socket.close()

View File

@@ -630,8 +630,11 @@ when defined(Windows) and not defined(useNimRtl):
success = winlean.createProcessW(nil, tmp, nil, nil, 1, flags,
ee, wwd, si, procInfo)
else:
var ee =
if e.str.isNil: cstring(nil)
else: cstring(e.str)
success = winlean.createProcessA(nil,
cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, si, procInfo)
cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, ee, wd, si, procInfo)
let lastError = osLastError()
if poParentStreams notin options:

View File

@@ -672,6 +672,9 @@ proc parseAttribute(my: var XmlParser) =
parseEntity(my, my.b)
my.kind = xmlAttribute # parseEntity overwrites my.kind!
pos = my.bufpos
elif c == '/':
pos = lexbase.handleRefillChar(my, pos)
add(my.b, '/')
else:
add(my.b, c)
inc(pos)

View File

@@ -396,7 +396,7 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
var resLen = genSym(nskLet, "resLen")
conds.add newLetStmt(resLen, newCall(bindSym"parseUntil", inp,
results[i], newLit(token), idx))
conds.add newCall(bindSym"!=", resLen, newLit min)
conds.add newCall(bindSym">=", resLen, newLit min)
conds.add resLen
else:
matchError

View File

@@ -917,6 +917,31 @@ proc toOct*(x: BiggestInt, len: Positive): string {.noSideEffect,
inc shift, 3
mask = mask shl BiggestUInt(3)
proc toHexImpl(x: BiggestUInt, len: Positive, handleNegative: bool): string {.noSideEffect.} =
const
HexChars = "0123456789ABCDEF"
var n = x
result = newString(len)
for j in countdown(len-1, 0):
result[j] = HexChars[int(n and 0xF)]
n = n shr 4
# handle negative overflow
if n == 0 and handleNegative: n = not(BiggestUInt 0)
proc toHex*(x: BiggestUInt, len: Positive): string {.noSideEffect.} =
## Converts `x` to its hexadecimal representation.
##
## The resulting string will be exactly `len` characters long. No prefix like
## ``0x`` is generated.
runnableExamples:
let
a = 62'u64
b = 4097'u64
doAssert a.toHex(3) == "03E"
doAssert b.toHex(3) == "001"
doAssert b.toHex(4) == "1001"
toHexImpl(x, len, false)
proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
rtl, extern: "nsuToHex".} =
## Converts `x` to its hexadecimal representation.
@@ -927,25 +952,19 @@ proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
let
a = 62
b = 4097
c = -8
doAssert a.toHex(3) == "03E"
doAssert b.toHex(3) == "001"
doAssert b.toHex(4) == "1001"
const
HexChars = "0123456789ABCDEF"
var
n = x
result = newString(len)
for j in countdown(len-1, 0):
result[j] = HexChars[int(n and 0xF)]
n = n shr 4
# handle negative overflow
if n == 0 and x < 0: n = -1
doAssert c.toHex(6) == "FFFFF8"
toHexImpl(cast[BiggestUInt](x), len, x < 0)
proc toHex*[T: SomeInteger](x: T): string =
proc toHex*[T: SomeInteger](x: T): string {.noSideEffect.} =
## Shortcut for ``toHex(x, T.sizeof * 2)``
runnableExamples:
doAssert toHex(1984'i64) == "00000000000007C0"
toHex(BiggestInt(x), T.sizeof * 2)
doAssert toHex(1984'i16) == "07C0"
toHexImpl(cast[BiggestUInt](x), 2*sizeof(T), x < 0)
proc toHex*(s: string): string {.noSideEffect, rtl.} =
## Converts a bytes string to its hexadecimal representation.
@@ -1806,7 +1825,7 @@ proc initSkipTable*(a: var SkipTable, sub: string)
proc find*(a: SkipTable, s, sub: string, start: Natural = 0, last = 0): int
{.noSideEffect, rtl, extern: "nsuFindStrA".} =
## Searches for `sub` in `s` inside range `start`..`last` using preprocessed
## Searches for `sub` in `s` inside range `start..last` using preprocessed
## table `a`. If `last` is unspecified, it defaults to `s.high` (the last
## element).
##

View File

@@ -369,3 +369,13 @@ when isMainModule:
of "bird": "word"
else: d
assert z == @["word", "word"]
proc tforum =
let ans = collect(newSeq):
for y in 0..10:
if y mod 5 == 2:
for x in 0..y:
x
tforum()

View File

@@ -689,10 +689,9 @@ template styledEchoProcessArg(f: File, color: Color) =
template styledEchoProcessArg(f: File, cmd: TerminalCmd) =
when cmd == resetStyle:
resetAttributes(f)
when cmd == fgColor:
fgSetColor = true
when cmd == bgColor:
fgSetColor = false
elif cmd in {fgColor, bgColor}:
let term = getTerminal()
term.fgSetColor = cmd == fgColor
macro styledWrite*(f: File, m: varargs[typed]): untyped =
## Similar to ``write``, but treating terminal style arguments specially.
@@ -776,25 +775,20 @@ when defined(windows):
## ``true`` otherwise.
password.string.setLen(0)
stdout.write(prompt)
while true:
let c = getch()
case c.char
of '\r', chr(0xA):
break
of '\b':
# ensure we delete the whole UTF-8 character:
var i = 0
var x = 1
while i < password.len:
x = runeLenAt(password.string, i)
inc i, x
password.string.setLen(max(password.len - x, 0))
of chr(0x0):
# modifier key - ignore - for details see
# https://github.com/nim-lang/Nim/issues/7764
continue
else:
password.string.add(toUTF8(c.Rune))
let hi = createFileA("CONIN$",
GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0)
var mode = DWORD 0
discard getConsoleMode(hi, addr mode)
let origMode = mode
const
ENABLE_PROCESSED_INPUT = 1
ENABLE_ECHO_INPUT = 4
mode = (mode or ENABLE_PROCESSED_INPUT) and not ENABLE_ECHO_INPUT
discard setConsoleMode(hi, mode)
result = readLine(stdin, password)
discard setConsoleMode(hi, origMode)
discard closeHandle(hi)
stdout.write "\n"
else:

View File

@@ -1357,6 +1357,12 @@ type # these work for most platforms:
culonglong* {.importc: "unsigned long long", nodecl.} = uint64
## This is the same as the type ``unsigned long long`` in *C*.
# There is a disparity on macOS where Nim's `uint` is `unsigned long long` and
# `uintptr_t` is `unsigned long`. Even though both data types are the same
# size (64 bits), clang++ refuses to do automatic conversion between them.
cuintptr_t* {.importc: "uintptr_t", nodecl.} = uint
## This is the same as the type ``uintptr_t`` in *C*.
cstringArray* {.importc: "char**", nodecl.} = ptr UncheckedArray[cstring]
## This is binary compatible to the type ``char**`` in *C*. The array's
## high value is large enough to disable bounds checking in practice.
@@ -2052,7 +2058,7 @@ const
NimMinor* {.intdefine.}: int = 2
## is the minor number of Nim's version.
NimPatch* {.intdefine.}: int = 6
NimPatch* {.intdefine.}: int = 8
## is the patch number of Nim's version.
NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch

View File

@@ -38,6 +38,9 @@ proc raiseRangeErrorU(i, a, b: uint64) {.compilerproc, noinline.} =
# todo: better error reporting
sysFatal(RangeError, "value out of range")
proc raiseRangeErrorNoArgs() {.compilerproc, noinline.} =
sysFatal(RangeError, "value out of range")
proc raiseObjectConversionError() {.compilerproc, noinline.} =
sysFatal(ObjectConversionError, "invalid object conversion")

View File

@@ -25,6 +25,11 @@ type
## rendered at a later time, we should ensure the stacktrace
## data isn't invalidated; any pointer into PFrame is
## subject to being invalidated so shouldn't be stored.
when defined(nimStackTraceOverride):
programCounter*: uint ## Program counter - will be used to get the rest of the info,
## when `$` is called on this type. We can't use
## "cuintptr_t" in here.
procnameStr*, filenameStr*: string ## GC-ed objects holding the cstrings in "procname" and "filename"
Exception* {.compilerproc, magic: "Exception".} = object of RootObj ## \
## Base exception class.

View File

@@ -10,6 +10,8 @@
# Exception handling code. Carefully coded so that tiny programs which do not
# use the heap (and nor exceptions) do not include the GC or memory allocator.
import stacktraces
var
errorMessageWriter*: (proc(msg: string) {.tags: [WriteIOEffect], benign,
nimcall.})
@@ -133,20 +135,6 @@ const
hasSomeStackTrace = NimStackTrace or defined(nimStackTraceOverride) or
(defined(nativeStackTrace) and nativeStackTraceSupported)
when defined(nimStackTraceOverride):
type StackTraceOverrideProc* = proc (): string {.nimcall, noinline, benign, raises: [], tags: [].}
## Procedure type for overriding the default stack trace.
var stackTraceOverrideGetTraceback: StackTraceOverrideProc = proc(): string {.noinline.} =
result = "Stack trace override procedure not registered.\n"
proc registerStackTraceOverride*(overrideProc: StackTraceOverrideProc) =
## Override the default stack trace inside rawWriteStackTrace() with your
## own procedure.
stackTraceOverrideGetTraceback = overrideProc
proc auxWriteStackTraceWithOverride(s: var string) =
add(s, stackTraceOverrideGetTraceback())
when defined(nativeStacktrace) and nativeStackTraceSupported:
type
@@ -164,13 +152,13 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
when not hasThreadSupport:
var
tempAddresses: array[0..127, pointer] # should not be alloc'd on stack
tempAddresses: array[maxStackTraceLines, pointer] # should not be alloc'd on stack
tempDlInfo: TDl_info
proc auxWriteStackTraceWithBacktrace(s: var string) =
when hasThreadSupport:
var
tempAddresses: array[0..127, pointer] # but better than a threadvar
tempAddresses: array[maxStackTraceLines, pointer] # but better than a threadvar
tempDlInfo: TDl_info
# This is allowed to be expensive since it only happens during crashes
# (but this way you don't need manual stack tracing)
@@ -198,11 +186,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
when hasSomeStackTrace and not hasThreadSupport:
var
tempFrames: array[0..127, PFrame] # should not be alloc'd on stack
const
reraisedFromBegin = -10
reraisedFromEnd = -100
tempFrames: array[maxStackTraceLines, PFrame] # should not be alloc'd on stack
template reraisedFrom(z): untyped =
StackTraceEntry(procname: nil, line: z, filename: nil)
@@ -253,7 +237,12 @@ template addFrameEntry(s: var string, f: StackTraceEntry|PFrame) =
for i in first..<f.frameMsgLen: add(s, frameMsgBuf[i])
add(s, "\n")
proc `$`(s: seq[StackTraceEntry]): string =
proc `$`(stackTraceEntries: seq[StackTraceEntry]): string =
when defined(nimStackTraceOverride):
let s = addDebuggingInfo(stackTraceEntries)
else:
let s = stackTraceEntries
result = newStringOfCap(2000)
for i in 0 .. s.len-1:
if s[i].line == reraisedFromBegin: result.add "[[reraised from:\n"
@@ -265,7 +254,7 @@ when hasSomeStackTrace:
proc auxWriteStackTrace(f: PFrame, s: var string) =
when hasThreadSupport:
var
tempFrames: array[0..127, PFrame] # but better than a threadvar
tempFrames: array[maxStackTraceLines, PFrame] # but better than a threadvar
const
firstCalls = 32
var
@@ -324,7 +313,9 @@ when hasSomeStackTrace:
add(s, "No stack traceback available\n")
proc rawWriteStackTrace(s: var seq[StackTraceEntry]) =
when NimStackTrace:
when defined(nimStackTraceOverride):
auxWriteStackTraceWithOverride(s)
elif NimStackTrace:
auxWriteStackTrace(framePtr, s)
else:
s = @[]
@@ -463,7 +454,12 @@ proc raiseExceptionEx(e: sink(ref Exception), ename, procname, filename: cstring
if e.name.isNil: e.name = ename
when hasSomeStackTrace:
when defined(nimStackTraceOverride):
e.trace = @[]
if e.trace.len == 0:
rawWriteStackTrace(e.trace)
else:
e.trace.add reraisedFrom(reraisedFromBegin)
auxWriteStackTraceWithOverride(e.trace)
e.trace.add reraisedFrom(reraisedFromEnd)
elif NimStackTrace:
if e.trace.len == 0:
rawWriteStackTrace(e.trace)

View File

@@ -0,0 +1,83 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# Additional code for customizable stack traces. Unstable API, for internal
# usage only.
const
reraisedFromBegin* = -10
reraisedFromEnd* = -100
maxStackTraceLines* = 128
when defined(nimStackTraceOverride):
## Procedure types for overriding the default stack trace.
type
cuintptr_t {.importc: "uintptr_t", nodecl.} = uint
## This is the same as the type ``uintptr_t`` in C.
StackTraceOverrideGetTracebackProc* = proc (): string {.
nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.}
StackTraceOverrideGetProgramCountersProc* = proc (maxLength: cint): seq[cuintptr_t] {.
nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.}
StackTraceOverrideGetDebuggingInfoProc* =
proc (programCounters: seq[cuintptr_t], maxLength: cint): seq[StackTraceEntry] {.
nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.}
# Default procedures (not normally used, because people opting in on this
# override are supposed to register their own versions).
var
stackTraceOverrideGetTraceback: StackTraceOverrideGetTracebackProc =
proc (): string {.nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.} =
discard
#result = "Stack trace override procedure not registered.\n"
stackTraceOverrideGetProgramCounters: StackTraceOverrideGetProgramCountersProc =
proc (maxLength: cint): seq[cuintptr_t] {.nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.} =
discard
stackTraceOverrideGetDebuggingInfo: StackTraceOverrideGetDebuggingInfoProc =
proc (programCounters: seq[cuintptr_t], maxLength: cint): seq[StackTraceEntry] {.
nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.} =
discard
# Custom procedure registration.
proc registerStackTraceOverride*(overrideProc: StackTraceOverrideGetTracebackProc) =
## Override the default stack trace inside rawWriteStackTrace() with your
## own procedure.
stackTraceOverrideGetTraceback = overrideProc
proc registerStackTraceOverrideGetProgramCounters*(overrideProc: StackTraceOverrideGetProgramCountersProc) =
stackTraceOverrideGetProgramCounters = overrideProc
proc registerStackTraceOverrideGetDebuggingInfo*(overrideProc: StackTraceOverrideGetDebuggingInfoProc) =
stackTraceOverrideGetDebuggingInfo = overrideProc
# Custom stack trace manipulation.
proc auxWriteStackTraceWithOverride*(s: var string) =
add(s, stackTraceOverrideGetTraceback())
proc auxWriteStackTraceWithOverride*(s: var seq[StackTraceEntry]) =
let programCounters = stackTraceOverrideGetProgramCounters(maxStackTraceLines)
if s.len == 0:
s = newSeqOfCap[StackTraceEntry](programCounters.len)
for programCounter in programCounters:
s.add(StackTraceEntry(programCounter: cast[uint](programCounter)))
# We may have more stack trace lines in the output, due to inlined procedures.
proc addDebuggingInfo*(s: seq[StackTraceEntry]): seq[StackTraceEntry] =
var programCounters: seq[cuintptr_t]
# We process program counters in groups from complete stack traces, because
# we have logic that keeps track of certain functions being inlined or not.
for entry in s:
if entry.procname.isNil and entry.programCounter != 0:
programCounters.add(cast[cuintptr_t](entry.programCounter))
elif entry.procname.isNil and (entry.line == reraisedFromBegin or entry.line == reraisedFromEnd):
result.add(stackTraceOverrideGetDebuggingInfo(programCounters, maxStackTraceLines))
programCounters = @[]
result.add(entry)
else:
result.add(entry)
if programCounters.len > 0:
result.add(stackTraceOverrideGetDebuggingInfo(programCounters, maxStackTraceLines))

View File

@@ -145,13 +145,13 @@ else:
SysCond = ptr SysCondObj
when not declared(c_malloc):
proc c_malloc(size: csize): pointer {.
proc c_malloc(size: csize_t): pointer {.
importc: "malloc", header: "<stdlib.h>".}
proc c_free(p: pointer) {.
importc: "free", header: "<stdlib.h>".}
proc initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) =
L = cast[SysLock](c_malloc(sizeof(SysLockObj)))
L = cast[SysLock](c_malloc(csize_t(sizeof(SysLockObj))))
initSysLockAux(L[], attr)
proc deinitSys(L: var SysLock) =
@@ -201,7 +201,7 @@ else:
when defined(ios):
proc initSysCond(cond: var SysCond, cond_attr: ptr SysCondAttr = nil) =
cond = cast[SysCond](c_malloc(sizeof(SysCondObj)))
cond = cast[SysCond](c_malloc(csize_t(sizeof(SysCondObj))))
initSysCondAux(cond[], cond_attr)
proc deinitSysCond(cond: var SysCond) =

View File

@@ -311,7 +311,10 @@ else:
when hasSharedHeap: t.core.stackSize = ThreadStackSize
var a {.noinit.}: Pthread_attr
doAssert pthread_attr_init(a) == 0
doAssert pthread_attr_setstacksize(a, ThreadStackSize) == 0
let setstacksizeResult = pthread_attr_setstacksize(a, ThreadStackSize)
when not defined(ios):
# This fails on iOS
doAssert(setstacksizeResult == 0)
if pthread_create(t.sys, a, threadProcWrapper[TArg], addr(t)) != 0:
raise newException(ResourceExhaustedError, "cannot create thread")
doAssert pthread_attr_destroy(a) == 0

View File

@@ -717,22 +717,20 @@ proc setHandleInformation*(hObject: Handle, dwMask: DWORD,
proc getCurrentProcess*(): Handle{.stdcall, dynlib: "kernel32",
importc: "GetCurrentProcess".}
when useWinUnicode:
proc createFileW*(lpFileName: WideCString, dwDesiredAccess, dwShareMode: DWORD,
lpSecurityAttributes: pointer,
dwCreationDisposition, dwFlagsAndAttributes: DWORD,
hTemplateFile: Handle): Handle {.
stdcall, dynlib: "kernel32", importc: "CreateFileW".}
proc deleteFileW*(pathName: WideCString): int32 {.
importc: "DeleteFileW", dynlib: "kernel32", stdcall.}
else:
proc createFileA*(lpFileName: cstring, dwDesiredAccess, dwShareMode: DWORD,
lpSecurityAttributes: pointer,
dwCreationDisposition, dwFlagsAndAttributes: DWORD,
hTemplateFile: Handle): Handle {.
stdcall, dynlib: "kernel32", importc: "CreateFileA".}
proc deleteFileA*(pathName: cstring): int32 {.
importc: "DeleteFileA", dynlib: "kernel32", stdcall.}
proc createFileW*(lpFileName: WideCString, dwDesiredAccess, dwShareMode: DWORD,
lpSecurityAttributes: pointer,
dwCreationDisposition, dwFlagsAndAttributes: DWORD,
hTemplateFile: Handle): Handle {.
stdcall, dynlib: "kernel32", importc: "CreateFileW".}
proc deleteFileW*(pathName: WideCString): int32 {.
importc: "DeleteFileW", dynlib: "kernel32", stdcall.}
proc createFileA*(lpFileName: cstring, dwDesiredAccess, dwShareMode: DWORD,
lpSecurityAttributes: pointer,
dwCreationDisposition, dwFlagsAndAttributes: DWORD,
hTemplateFile: Handle): Handle {.
stdcall, dynlib: "kernel32", importc: "CreateFileA".}
proc deleteFileA*(pathName: cstring): int32 {.
importc: "DeleteFileA", dynlib: "kernel32", stdcall.}
proc setEndOfFile*(hFile: Handle): WINBOOL {.stdcall, dynlib: "kernel32",
importc: "SetEndOfFile".}

View File

@@ -64,9 +64,9 @@ elif useWinVersion:
from winlean import SocketHandle
else:
when defined(osx):
const versions = "(.1.1|.38|.39|.41|.43|.44|.45|.46|.47|.10|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|)"
const versions = "(.1.1|.38|.39|.41|.43|.44|.45|.46|.47|.48|.10|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|)"
else:
const versions = "(.1.1|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|.47|.46|.45|.44|.43|.41|.39|.38|.10|)"
const versions = "(.1.1|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|.48|.47|.46|.45|.44|.43|.41|.39|.38|.10|)"
when defined(macosx):
const

View File

@@ -9,7 +9,7 @@ pkg "argparse"
pkg "arraymancer", true, "nim c tests/tests_cpu.nim"
pkg "ast_pattern_matching", false, "nim c -r --oldgensym:on tests/test1.nim"
pkg "asyncmysql", true
pkg "bigints"
pkg "bigints", url = "https://github.com/Araq/nim-bigints"
pkg "binaryheap", false, "nim c -r binaryheap.nim"
# pkg "blscurve", true # pending https://github.com/status-im/nim-blscurve/issues/39
pkg "bncurve", true
@@ -91,6 +91,6 @@ pkg "unicodeplus", true
pkg "unpack"
# pkg "winim", true
pkg "with"
pkg "ws"
# pkg "ws"
pkg "yaml"
pkg "zero_functional", false, "nim c -r test.nim"

View File

@@ -0,0 +1,25 @@
discard """
output: '''
finally handler 8
do not duplicate this one
'''
"""
# bug #15243
import asyncdispatch
proc f() {.async.} =
try:
while true:
try:
await sleepAsync(400)
break
finally:
var localHere = 8
echo "finally handler ", localHere
finally:
echo "do not duplicate this one"
when isMainModule:
waitFor f()

View File

@@ -1,6 +1,6 @@
discard """
cmd: "nim c --newruntime $file"
errormsg: "'=' is not available for type <owned Foo>; requires a copy because it's not the last read of 'a'; another read is done here: tconsume_twice.nim(13, 10); routine: consumeTwice"
errormsg: "'=copy' is not available for type <owned Foo>; requires a copy because it's not the last read of 'a'; another read is done here: tconsume_twice.nim(13, 10); routine: consumeTwice"
line: 11
"""
type

View File

@@ -1,5 +1,5 @@
discard """
errormsg: "'=' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
errormsg: "'=copy' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
line: 29
"""

View File

@@ -1,5 +1,5 @@
discard """
errormsg: "'=' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
errormsg: "'=copy' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
file: "tprevent_assign2.nim"
line: 48
"""

View File

@@ -1,5 +1,5 @@
discard """
errormsg: "'=' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
errormsg: "'=copy' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
file: "tprevent_assign3.nim"
line: 46
"""

View File

@@ -1,6 +1,6 @@
discard """
cmd: '''nim c --newruntime $file'''
errormsg: "'=' is not available for type <owned Button>; requires a copy because it's not the last read of ':envAlt.b1'; another read is done here: tuse_ownedref_after_move.nim(52, 4)"
errormsg: "'=copy' is not available for type <owned Button>; requires a copy because it's not the last read of ':envAlt.b1'; another read is done here: tuse_ownedref_after_move.nim(52, 4)"
line: 48
"""

View File

@@ -10,7 +10,8 @@ proc rsplit(s: string; sep: string; maxsplit: int = -1): seq[string]
first type mismatch at position: 2
required type for sep: string
but expression '{':'}' is of type: set[char]
proc rsplit(s: string; seps: set[char] = Whitespace; maxsplit: int = -1): seq[string]
proc rsplit(s: string; seps: set[char] = Whitespace; maxsplit: int = -1): seq[
string]
first type mismatch at position: 3
unknown named parameter: maxsplits
@@ -22,6 +23,5 @@ expression: rsplit("abc:def", {':'}, maxsplits = 1)
# bug #8043
import strutils
"abc:def".rsplit({':'}, maxsplits = 1)

View File

@@ -55,3 +55,10 @@ const
for i in 0..len(stringArray)-1:
echo(stringArray[i])
# bug #15360
type Rule[T] = (int, T)
var t: seq[Rule[int]]
for (c, t) in t:
discard

View File

@@ -346,6 +346,21 @@ testinstance:
c: char
d: int32 # unaligned
Kind = enum
K1, K2
AnotherEnum = enum
X1, X2, X3
MyObject = object
s: string
case k: Kind
of K1: nil
of K2:
x: float
y: int32
z: AnotherEnum
const trivialSize = sizeof(TrivialType) # needs to be able to evaluate at compile time
proc main(): void =
@@ -361,6 +376,7 @@ testinstance:
var go : GenericObject[int64]
var po : PaddingOfSetEnum33
var capo: MyCustomAlignPackedObject
var issue15516: MyObject
var
e1: Enum1
@@ -379,7 +395,7 @@ testinstance:
else:
doAssert sizeof(SimpleAlignment) > 10
testSizeAlignOf(t,a,b,c,d,e,f,g,ro,go,po, e1, e2, e4, e8, eoa, eob, capo)
testSizeAlignOf(t,a,b,c,d,e,f,g,ro,go,po, e1, e2, e4, e8, eoa, eob, capo, issue15516)
type
WithBitsize {.objectconfig.} = object

View File

@@ -75,3 +75,14 @@ let rangeVar = 0'u64 ..< limit
doAssert repr(rangeVar) == """[a = 0,
b = 0]
"""
# bug #15210
let a3 = not 0'u64
var success = false
try:
discard a3.int64
except RangeError:
success = true
doAssert success, "conversion should fail at runtime"

View File

@@ -0,0 +1,29 @@
discard """
cmd: "nim c -r --styleCheck:hint --panics:on $options $file"
targets: "c"
nimout: ""
action: "run"
exitcode: 0
timeout: 60.0
"""
import nativesockets
when defined(windows):
doAssert toInt(IPPROTO_IP) == 0.cint
doAssert toInt(IPPROTO_ICMP) == 1.cint
doAssert toInt(IPPROTO_TCP) == 6.cint
doAssert toInt(IPPROTO_UDP) == 17.cint
doAssert toInt(IPPROTO_IPV6) == 41.cint
doAssert toInt(IPPROTO_ICMPV6) == 58.cint
doAssert toInt(IPPROTO_RAW) == 20.cint
# no changes to enum value
doAssert ord(IPPROTO_TCP) == 6
doAssert ord(IPPROTO_UDP) == 17
doAssert ord(IPPROTO_IP) == 18
doAssert ord(IPPROTO_IPV6) == 19
doAssert ord(IPPROTO_RAW) == 20
doAssert ord(IPPROTO_ICMP) == 21
doAssert ord(IPPROTO_ICMPV6) == 22

View File

@@ -79,8 +79,22 @@ block EmptyTuple:
block Arrow:
let text = "foo;bar;baz;"
var idx = 0
var res = ""
doAssert scanp(text, idx, +(~{';','\0'} -> (discard $_)), ';')
doAssert scanp(text, idx, +(~{';','\0'} -> (discard $_)), ';')
doAssert scanp(text, idx, +(~{';','\0'} -> (discard $_)), ';')
doAssert scanp(text, idx, +(~{';','\0'} -> (discard $_)), ';') == false
block issue15064:
var nick1, msg1: string
doAssert scanf("<abcd> a", "<$+> $+", nick1, msg1)
doAssert nick1 == "abcd"
doAssert msg1 == "a"
var nick2, msg2: string
doAssert(not scanf("<abcd> ", "<$+> $+", nick2, msg2))
var nick3, msg3: string
doAssert scanf("<abcd> ", "<$+> $*", nick3, msg3)
doAssert nick3 == "abcd"
doAssert msg3 == ""

View File

@@ -6,8 +6,6 @@ discard """
import
strutils
import macros
template rejectParse(e) =
try:
discard e
@@ -298,6 +296,10 @@ assert "/1/2/3".rfind('0') == -1
assert(toHex(100i16, 32) == "00000000000000000000000000000064")
assert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
assert(toHex(high(uint64)) == "FFFFFFFFFFFFFFFF")
assert(toHex(high(uint64), 16) == "FFFFFFFFFFFFFFFF")
assert(toHex(high(uint64), 32) == "0000000000000000FFFFFFFFFFFFFFFF")
assert "".parseHexStr == ""
assert "00Ff80".parseHexStr == "\0\xFF\x80"
try:

View File

@@ -0,0 +1,8 @@
discard """
action: compile
"""
import terminal, colors
styledEcho fgColor, colRed, "Test"
styledEcho bgColor, colBlue, "Test"

View File

@@ -0,0 +1,18 @@
discard """
cmd: "nim c -d:nimStacktraceOverride $file"
output: '''begin
Traceback (most recent call last, using override)
Error: unhandled exception: stack trace produced [ValueError]
'''
exitcode: 1
"""
import asyncfutures
proc main =
echo "begin"
if true:
raise newException(ValueError, "stack trace produced")
echo "unreachable"
main()

View File

@@ -1,5 +1,5 @@
discard """
timeout: "4"
timeout: "7"
action: "compile"
nimout: '''create
search

View File

@@ -1,13 +1,29 @@
import os, uri, strformat
import os, uri, strformat, osproc, strutils
proc exec(cmd: string) =
echo "deps.cmd: " & cmd
let status = execShellCmd(cmd)
doAssert status == 0, cmd
proc execEx(cmd: string): tuple[output: TaintedString, exitCode: int] =
echo "deps.cmd: " & cmd
execCmdEx(cmd, {poStdErrToStdOut, poUsePath, poEvalCommand})
proc isGitRepo(dir: string): bool =
# This command is used to get the relative path to the root of the repository.
# Using this, we can verify whether a folder is a git repository by checking
# whether the command success and if the output is empty.
let (output, status) = execEx fmt"git -C {quoteShell(dir)} rev-parse --show-cdup"
# On Windows there will be a trailing newline on success, remove it.
# The value of a successful call typically won't have a whitespace (it's
# usually a series of ../), so we know that it's safe to unconditionally
# remove trailing whitespaces from the result.
result = status == 0 and output.strip() == ""
const commitHead* = "HEAD"
proc cloneDependency*(destDirBase: string, url: string, commit = commitHead, appendRepoName = true) =
proc cloneDependency*(destDirBase: string, url: string, commit = commitHead,
appendRepoName = true, allowBundled = false) =
let destDirBase = destDirBase.absolutePath
let p = url.parseUri.path
let name = p.splitFile.name
@@ -18,5 +34,10 @@ proc cloneDependency*(destDirBase: string, url: string, commit = commitHead, app
# note: old code used `destDir / .git` but that wouldn't prevent git clone
# from failing
exec fmt"git clone -q {url} {destDir2}"
exec fmt"git -C {destDir2} fetch -q"
exec fmt"git -C {destDir2} checkout -q {commit}"
if isGitRepo(destDir):
exec fmt"git -C {destDir2} fetch -q"
exec fmt"git -C {destDir2} checkout -q {commit}"
elif allowBundled:
discard "this dependency was bundled with Nim, don't do anything"
else:
quit "FAILURE: " & destdir & " already exists but is not a git repo"