Merge branch 'devel' into pr_guten

This commit is contained in:
ringabout
2025-09-11 19:08:49 +08:00
committed by GitHub
29 changed files with 337 additions and 89 deletions

View File

@@ -23,6 +23,8 @@ errors.
- With `-d:nimPreviewCStringComparisons`, comparsions (`<`, `>`, `<=`, `>=`) between cstrings switch from reference semantics to value semantics like `==` and `!=`.
- `std/parsesql` has been moved to a nimble package, use `nimble` or `atlas` to install it.
## Standard library additions and changes
[//]: # "Additions:"

View File

@@ -819,6 +819,7 @@ type
# nodes are compared by structure!
counter*: int
data*: TNodePairSeq
ignoreTypes*: bool
TObjectSeq* = seq[RootRef]
TObjectSet* = object
@@ -1641,8 +1642,8 @@ proc initObjectSet*(): TObjectSet =
result = TObjectSet(counter: 0)
newSeq(result.data, StartSize)
proc initNodeTable*(): TNodeTable =
result = TNodeTable(counter: 0)
proc initNodeTable*(ignoreTypes=false): TNodeTable =
result = TNodeTable(counter: 0, ignoreTypes: ignoreTypes)
newSeq(result.data, StartSize)
proc skipTypes*(t: PType, kinds: TTypeKinds; maxIters: int): PType =

View File

@@ -981,7 +981,11 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
var a: TLoc = initLocExpr(p, e[0])
if e[0].kind in {nkHiddenStdConv, nkHiddenSubConv, nkConv} and not ignoreConv(e[0]):
# addr (conv x) introduces a temp because `conv x` is not a rvalue
putIntoDest(p, d, e, addrLoc(p.config, expressionsNeedsTmp(p, a)), a.storage)
# transform addr ( conv ( x ) ) -> conv ( addr ( x ) )
var exprLoc: TLoc = initLocExpr(p, e[0][1])
var tmp = getTemp(p, e.typ, needsInit=false)
putIntoDest(p, tmp, e, cCast(getTypeDesc(p.module, e.typ), addrLoc(p.config, exprLoc)))
putIntoDest(p, d, e, rdLoc(tmp))
else:
putIntoDest(p, d, e, addrLoc(p.config, a), a.storage)

View File

@@ -379,7 +379,9 @@ proc useVar(a: PEffects, n: PNode) =
# If the variable is explicitly marked as .noinit. do not emit any error
a.init.add s.id
elif s.id notin a.init:
if s.typ.requiresInit:
if s.kind == skResult and tfRequiresInit in s.typ.flags:
localError(a.config, n.info, "'result' requires explicit initialization")
elif s.typ.requiresInit:
message(a.config, n.info, warnProveInit, s.name.s)
elif a.leftPartOfAsgn <= 0:
if strictDefs in a.c.features:

View File

@@ -725,7 +725,7 @@ template isLocalSym(sym: PSym): bool =
sym.typ.kind == tyTypeDesc or
sfCompileTime in sym.flags) or
sym.kind in {skProc, skFunc, skIterator} and
sfGlobal notin sym.flags
sfGlobal notin sym.flags and sym.typ.callConv == ccClosure
proc usesLocalVar(n: PNode): bool =
case n.kind

View File

@@ -1147,7 +1147,9 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
let t = newTypeS(tySink, c, result)
result = t
else: discard
if result.kind == tyRef and c.config.selectedGC in {gcArc, gcOrc, gcAtomicArc}:
if result.kind == tyRef and
c.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and
tfTriggersCompileTime notin result.flags:
result.flags.incl tfHasAsgn
proc findEnforcedStaticType(t: PType): PType =

View File

@@ -259,7 +259,8 @@ proc transformBlock(c: PTransf, n: PNode): PNode =
var labl: PSym
if c.inlining > 0:
labl = newLabel(c, n[0])
c.transCon.mapping[n[0].sym.itemId] = newSymNode(labl)
if n[0].kind != nkEmpty:
c.transCon.mapping[n[0].sym.itemId] = newSymNode(labl)
else:
labl =
if n[0].kind != nkEmpty:
@@ -827,12 +828,20 @@ proc transformFor(c: PTransf, n: PNode): PNode =
t = formal.ast.typ # better use the type that actually has a destructor.
elif t.destructor == nil and arg.typ.destructor != nil:
t = arg.typ
# generate a temporary and produce an assignment statement:
var temp = newTemp(c, t, formal.info)
#incl(temp.sym.flags, sfCursor)
addVar(v, temp)
stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg, true))
newC.mapping[formal.itemId] = temp
if arg.kind in {nkDerefExpr, nkHiddenDeref}:
# optimizes for `[]` # bug #24093
var temp = newTemp(c, arg[0].typ, formal.info)
addVar(v, temp)
stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg[0], true))
newC.mapping[formal.itemId] = newDeref(temp)
else:
# generate a temporary and produce an assignment statement:
var temp = newTemp(c, t, formal.info)
#incl(temp.sym.flags, sfCursor)
addVar(v, temp)
stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg, true))
newC.mapping[formal.itemId] = temp
of paVarAsgn:
assert(skipTypes(formal.typ, abstractInst).kind in {tyVar, tyLent})
newC.mapping[formal.itemId] = arg

View File

@@ -42,32 +42,37 @@ proc hashTree*(n: PNode): Hash =
#echo "hashTree ", result
#echo n
proc treesEquivalent(a, b: PNode): bool =
proc treesEquivalent(a, b: PNode; ignoreTypes: bool): bool =
if a == b:
result = true
elif (a != nil) and (b != nil) and (a.kind == b.kind):
case a.kind
of nkEmpty, nkNilLit, nkType: result = true
of nkEmpty: result = true
of nkSym: result = a.sym.id == b.sym.id
of nkIdent: result = a.ident.id == b.ident.id
of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
of nkFloatLit..nkFloat64Lit:
result = cast[uint64](a.floatVal) == cast[uint64](b.floatVal)
#result = a.floatVal == b.floatVal
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
of nkType, nkNilLit:
result = a.typ == b.typ
else:
if a.len == b.len:
for i in 0..<a.len:
if not treesEquivalent(a[i], b[i]): return
if not treesEquivalent(a[i], b[i], ignoreTypes): return
result = true
else:
result = false
if result: result = sameTypeOrNil(a.typ, b.typ)
if result and not ignoreTypes:
result = sameTypeOrNil(a.typ, b.typ)
else:
result = false
proc nodeTableRawGet(t: TNodeTable, k: Hash, key: PNode): int =
var h: Hash = k and high(t.data)
while t.data[h].key != nil:
if (t.data[h].h == k) and treesEquivalent(t.data[h].key, key):
if (t.data[h].h == k) and treesEquivalent(t.data[h].key, key, t.ignoreTypes):
return h
h = nextTry(h, high(t.data))
result = -1

View File

@@ -249,6 +249,7 @@ type
# to not slow down interpretation
globals*: PNode #
constants*: PNode # constant data
contstantTab*: TNodeTable
types*: seq[PType] # some instructions reference types (e.g. 'except')
currentExceptionA*, currentExceptionB*: PNode
exceptionInstr*: int # index of instruction that raised the exception
@@ -298,7 +299,8 @@ proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph; idgen: IdGenerator
prc: PProc(blocks: @[]), module: module, loopIterations: g.config.maxLoopIterationsVM,
callDepth: g.config.maxCallDepthVM,
comesFromHeuristic: unknownLineInfo, callbacks: @[], callbackIndex: initTable[string, int](), errorFlag: "",
cache: cache, config: g.config, graph: g, idgen: idgen)
cache: cache, config: g.config, graph: g, idgen: idgen,
contstantTab: initNodeTable(true))
proc refresh*(c: PCtx, module: PSym; idgen: IdGenerator) =
c.module = module

View File

@@ -33,7 +33,8 @@ when defined(nimPreviewSlimSystem):
import
ast, types, msgs, renderer, vmdef, trees,
magicsys, options, lowerings, lineinfos, transf, astmsgs
magicsys, options, lowerings, lineinfos, transf, astmsgs,
treetab
from modulegraphs import getBody
@@ -478,10 +479,16 @@ proc sameConstant*(a, b: PNode): bool =
result = true
proc genLiteral(c: PCtx; n: PNode): int =
# types do not matter here:
for i in 0..<c.constants.len:
if sameConstant(c.constants[i], n): return i
result = rawGenLiteral(c, n)
result = nodeTableTestOrSet(c.contstantTab, n, c.constants.len)
if result == c.constants.len:
let lit = rawGenLiteral(c, n)
assert lit == result
when false:
# types do not matter here:
for i in 0..<c.constants.len:
if sameConstant(c.constants[i], n): return i
result = rawGenLiteral(c, n)
proc unused(c: PCtx; n: PNode; x: TDest) {.inline.} =
if x >= 0:
@@ -1182,8 +1189,10 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMag
of mEqF64: genBinaryABC(c, n, dest, opcEqFloat)
of mLeF64: genBinaryABC(c, n, dest, opcLeFloat)
of mLtF64: genBinaryABC(c, n, dest, opcLtFloat)
of mLePtr, mLeU: genBinaryABC(c, n, dest, opcLeu)
of mLtPtr, mLtU: genBinaryABC(c, n, dest, opcLtu)
of mLeU: genBinaryABC(c, n, dest, opcLeu)
of mLtU: genBinaryABC(c, n, dest, opcLtu)
of mLePtr, mLtPtr:
globalError(c.config, n.info, "pointer comparisons are not available at compile-time")
of mEqProc, mEqRef:
genBinaryABC(c, n, dest, opcEqRef)
of mXor: genBinaryABC(c, n, dest, opcXor)
@@ -1547,8 +1556,7 @@ template cannotEval(c: PCtx; n: PNode) =
if c.config.cmd == cmdCheck and c.config.m.errorOutputs != {}:
# nim check command with no error outputs doesn't need to cascade here,
# includes `tryConstExpr` case which should not continue generating code
localError(c.config, n.info, "cannot evaluate at compile time: " &
n.renderTree)
localError(c.config, n.info, "cannot evaluate at compile time: " & n.renderTree)
c.cannotEval = true
return
globalError(c.config, n.info, "cannot evaluate at compile time: " &
@@ -1886,7 +1894,7 @@ proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
c.freeTemp(objR)
proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
if n[0].typ == nil:
if n[0].typ == nil:
globalError(c.config, n.info, "cannot access array with nil type")
return

View File

@@ -4062,7 +4062,7 @@ notation. (Thus an operator can have more than two parameters):
# Multiply and add
result = a * b + c
assert `*+`(3, 4, 6) == `+`(`*`(a, b), c)
assert `*+`(3, 4, 6) == `+`(`*`(3, 4), 6)
```

View File

@@ -224,6 +224,8 @@ directories (in this order; later files overwrite previous settings):
command-line option.
[NimScript files](nims.html) can also be used for configuration.
Command-line settings have priority over configuration file settings.
The default build of a project is a `debug build`:idx:. To compile a

View File

@@ -13,7 +13,7 @@ const
# examples of possible values for repos: Head, ea82b54
NimbleStableCommit = "9207e8b2bbdf66b5a4d1020214cff44d2d30df92" # 0.20.1
AtlasStableCommit = "26cecf4d0cc038d5422fc1aa737eec9c8803a82b" # 0.9
ChecksumsStableCommit = "f8f6bd34bfa3fe12c64b919059ad856a96efcba0" # 2.0.1
ChecksumsStableCommit = "0b8e46379c5bc1bf73d8b3011908389c60fb9b98" # 2.0.1
SatStableCommit = "faf1617f44d7632ee9601ebc13887644925dcc01"
NimonyStableCommit = "1dbabac403ae32e185ee4c29f006d04e04b50c6d" # unversioned \

View File

@@ -428,7 +428,7 @@ proc write*(f: AsyncFile, data: string): Future[void] =
dealloc buffer
buffer = nil
)
ol.offset = DWORD(f.offset and 0xffffffff)
ol.offset = cast[DWORD](f.offset and 0xffffffff)
ol.offsetHigh = DWORD(f.offset shr 32)
f.offset.inc(data.len)

View File

@@ -116,6 +116,11 @@ macro evalOnceAs(expAlias, exp: untyped,
newProc(name = genSym(nskTemplate, $expAlias), params = [getType(untyped)],
body = val, procType = nnkTemplateDef))
template unCheckedInc(x) =
{.push overflowChecks: off.}
inc(x)
{.pop.}
func concat*[T](seqs: varargs[seq[T]]): seq[T] =
## Takes several sequences' items and returns them inside a new sequence.
## All sequences must be of the same type.
@@ -139,7 +144,7 @@ func concat*[T](seqs: varargs[seq[T]]): seq[T] =
for s in items(seqs):
for itm in items(s):
result[i] = itm
inc(i)
unCheckedInc(i)
func addUnique*[T](s: var seq[T], x: sink T) =
## Adds `x` to the container `s` if it is not already present.
@@ -170,7 +175,7 @@ func count*[T](s: openArray[T], x: T): int =
result = 0
for itm in items(s):
if itm == x:
inc result
unCheckedInc result
func cycle*[T](s: openArray[T], n: Natural): seq[T] =
## Returns a new sequence with the items of the container `s` repeated
@@ -188,7 +193,7 @@ func cycle*[T](s: openArray[T], n: Natural): seq[T] =
for x in 0 ..< n:
for e in s:
result[o] = e
inc o
unCheckedInc o
proc repeat*[T](x: T, n: Natural): seq[T] =
## Returns a new sequence with the item `x` repeated `n` times.
@@ -321,6 +326,26 @@ func minmax*[T](x: openArray[T], cmp: proc(a, b: T): int): (T, T) {.effectsOf: c
elif cmp(result[1], x[i]) < 0: result[1] = x[i]
template findIt*(s, predicate: untyped): int =
## Iterates through a container and returns the index of the first item that
## fulfills the predicate, or -1
##
## Unlike the `find`, the predicate needs to be an expression using
## the `it` variable for testing, like: `findIt([3, 2, 1], it == 2)`.
var
res = -1
i = 0
# We must use items here since both `find` and `anyIt` are defined in terms
# of `items`
# (and not `pairs`)
for it {.inject.} in items(s):
if predicate:
res = i
break
unCheckedInc(i)
res
template zipImpl(s1, s2, retType: untyped): untyped =
proc zip*[S, T](s1: openArray[S], s2: openArray[T]): retType =
## Returns a new sequence with a combination of the two input containers.
@@ -417,7 +442,7 @@ func distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] =
if extra == 0 or spread == false:
# Use an algorithm which overcounts the stride and minimizes reading limits.
if extra > 0: inc(stride)
if extra > 0: unCheckedInc(stride)
for i in 0 ..< num:
result[i] = newSeq[T]()
for g in first ..< min(s.len, first + stride):
@@ -429,7 +454,7 @@ func distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] =
last = first + stride
if extra > 0:
extra -= 1
inc(last)
unCheckedInc(last)
result[i] = newSeq[T]()
for g in first ..< last:
result[i].add(s[g])
@@ -586,7 +611,7 @@ proc keepIf*[T](s: var seq[T], pred: proc(x: T): bool {.closure.})
s[pos] = move(s[i])
else:
shallowCopy(s[pos], s[i])
inc(pos)
unCheckedInc(pos)
setLen(s, pos)
func delete*[T](s: var seq[T]; slice: Slice[int]) =
@@ -617,8 +642,8 @@ func delete*[T](s: var seq[T]; slice: Slice[int]) =
s[i] = move(s[j])
else:
s[i].shallowCopy(s[j])
inc(i)
inc(j)
unCheckedInc(i)
unCheckedInc(j)
setLen(s, newLen)
when nimvm: defaultImpl()
else:
@@ -649,8 +674,8 @@ func delete*[T](s: var seq[T]; first, last: Natural) {.deprecated: "use `delete(
s[i] = move(s[j])
else:
s[i].shallowCopy(s[j])
inc(i)
inc(j)
unCheckedInc(i)
unCheckedInc(j)
setLen(s, newLen)
func insert*[T](dest: var seq[T], src: openArray[T], pos = 0) =
@@ -681,10 +706,10 @@ func insert*[T](dest: var seq[T], src: openArray[T], pos = 0) =
dec(i)
dec(j)
# Insert items from `dest` into `dest` at `pos`
inc(j)
unCheckedInc(j)
for item in src:
dest[j] = item
inc(j)
unCheckedInc(j)
template filterIt*(s, pred: untyped): untyped =
@@ -715,7 +740,7 @@ template filterIt*(s, pred: untyped): untyped =
var result = newSeq[typeof(s[0])]()
for it {.inject.} in items(s):
if pred: result.add(it)
result
move result
template keepItIf*(varSeq: seq, pred: untyped) =
## Keeps the items in the passed sequence (must be declared as a `var`)
@@ -743,7 +768,7 @@ template keepItIf*(varSeq: seq, pred: untyped) =
varSeq[pos] = move(varSeq[i])
else:
shallowCopy(varSeq[pos], varSeq[i])
inc(pos)
unCheckedInc(pos)
setLen(varSeq, pos)
since (1, 1):
@@ -842,12 +867,7 @@ template anyIt*(s, pred: untyped): bool =
assert numbers.anyIt(it > 8) == true
assert numbers.anyIt(it > 9) == false
var result = false
for it {.inject.} in items(s):
if pred:
result = true
break
result
findIt(s, pred) != -1
template toSeq1(s: not iterator): untyped =
# overload for typed but not iterator
@@ -875,7 +895,7 @@ template toSeq2(iter: iterator): untyped =
var result = newSeq[typeof(iter2)](iter2.len)
for x in iter2:
result[i] = x
inc i
unCheckedInc i
result
else:
type OutType = typeof(iter2())
@@ -920,7 +940,7 @@ template toSeq*(iter: untyped): untyped =
var i = 0
for x in iter2:
result[i] = x
inc i
unCheckedInc i
result
else:
var result: seq[typeof(iter)] = @[]

View File

@@ -12,6 +12,8 @@
##
## Unstable API.
{.deprecated: "use `nimble install parsesql` and import `pkg/parsesql` instead".}
import std/[strutils, lexbase]
import std/private/decode_helpers

View File

@@ -74,6 +74,7 @@ import std/parseutils
from std/math import pow, floor, log10
from std/algorithm import fill, reverse
import std/enumutils
from std/bitops import fastLog2
from std/unicode import toLower, toUpper
export toLower, toUpper
@@ -2639,37 +2640,35 @@ func formatSize*(bytes: int64,
## * `strformat module<strformat.html>`_ for string interpolation and formatting
runnableExamples:
doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB"
doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
doAssert formatSize((2.234*1024*1024).int) == "2.233MiB"
doAssert formatSize(4096, includeSpace = true) == "4 KiB"
doAssert formatSize(4096, prefix = bpColloquial, includeSpace = true) == "4 kB"
doAssert formatSize(4096) == "4KiB"
doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,13MB"
doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,129MB"
const iecPrefixes = ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"]
const collPrefixes = ["", "k", "M", "G", "T", "P", "E", "Z", "Y"]
var
xb: int64 = bytes
fbytes: float
lastXb: int64 = bytes
matchedIndex = 0
prefixes: array[9, string]
# It doesn't needs Zi and larger units until we use int72 or larger ints.
const iecPrefixes = ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei"]
const collPrefixes = ["", "k", "M", "G", "T", "P", "E"]
let lg2 = if bytes == 0:
0
else:
when hasWorkingInt64:
fastLog2(bytes)
else:
fastLog2(int32 bytes)
let matchedIndex = lg2 div 10
# Lower bits that are smaller than 0.001 when `bytes` is converted to a real number and added prefix, are discard.
# Then it is converted to float with round down.
let discardBits = (lg2 div 10 - 1) * 10
var prefixes: array[7, string]
if prefix == bpColloquial:
prefixes = collPrefixes
else:
prefixes = iecPrefixes
# Iterate through prefixes seeing if value will be greater than
# 0 in each case
for index in 1..<prefixes.len:
lastXb = xb
xb = bytes div (1'i64 shl (index*10))
matchedIndex = index
if xb == 0:
xb = lastXb
matchedIndex = index - 1
break
# xb has the integer number for the latest value; index should be correct
fbytes = bytes.float / (1'i64 shl (matchedIndex*10)).float
let fbytes = if lg2 < 10: bytes.float elif lg2 < 20: bytes.float / 1024.0 else: (bytes shr discardBits).float / 1024.0
result = formatFloat(fbytes, format = ffDecimal, precision = 3,
decimalSep = decimalSep)
result.trimZeros(decimalSep)

View File

@@ -1465,6 +1465,8 @@ proc isNil*[T: proc | iterator {.closure.}](x: T): bool {.noSideEffect, magic: "
## Fast check whether `x` is nil. This is sometimes more efficient than
## `== nil`.
proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".}
when defined(nimHasTopDownInference):
# magic used for seq type inference
proc `@`*[T](a: openArray[T]): seq[T] {.magic: "OpenArrayToSeq".} =
@@ -1472,8 +1474,17 @@ when defined(nimHasTopDownInference):
##
## This is not as efficient as turning a fixed length array into a sequence
## as it always copies every element of `a`.
newSeq(result, a.len)
for i in 0..a.len-1: result[i] = a[i]
let sz = a.len
when supportsCopyMem(T) and not defined(js):
result = newSeqUninit[T](sz)
when nimvm:
for i in 0..sz-1: result[i] = a[i]
else:
if sz != 0:
copyMem(addr result[0], addr a[0], sizeof(T) * sz)
else:
newSeq(result, sz)
for i in 0..sz-1: result[i] = a[i]
else:
proc `@`*[T](a: openArray[T]): seq[T] =
## Turns an *openArray* into a sequence.
@@ -1644,8 +1655,6 @@ when not defined(js) and defined(nimV2):
vTable: UncheckedArray[pointer] # vtable for types
PNimTypeV2 = ptr TNimTypeV2
proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".}
when notJSnotNims and defined(nimSeqsV2):
include "system/strs_v2"
include "system/seqs_v2"

View File

@@ -25,3 +25,23 @@ block:
var m = uint64(12)
foo(culonglong(m))
main()
block: # bug #25109
type T = culonglong
proc r(c: var T) = c = 1
proc h(a: var culonglong) = r(T(a))
var a: culonglong
h(a)
doAssert a == 1
block: # bug #25111
type T = culonglong
proc r(c: var T) = c = 1
proc foo =
var a: uint64
r(T(a))
doAssert a == 1
foo()

View File

@@ -53,11 +53,11 @@ proc nonStaticTests =
block: # formatSize tests
when not defined(js):
doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB" # <=== bug #8231
doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
doAssert formatSize((2.234*1024*1024).int) == "2.233MiB"
doAssert formatSize(4096) == "4KiB"
doAssert formatSize(4096, prefix=bpColloquial, includeSpace=true) == "4 kB"
doAssert formatSize(4096, includeSpace=true) == "4 KiB"
doAssert formatSize(5_378_934, prefix=bpColloquial, decimalSep=',') == "5,13MB"
doAssert formatSize(5_378_934, prefix=bpColloquial, decimalSep=',') == "5,129MB"
block: # formatEng tests
doAssert formatEng(0, 2, trim=false) == "0.00"

13
tests/errmsgs/t25117.nim Normal file
View File

@@ -0,0 +1,13 @@
discard """
errormsg: "'result' requires explicit initialization"
"""
type RI {.requiresInit.} = object
v: int
proc xxx(v: var RI) = discard
proc f(T: type): T =
xxx(result) # Should fail
discard f(RI)

6
tests/errmsgs/t25120.nim Normal file
View File

@@ -0,0 +1,6 @@
discard """
errormsg: "request to generate code for .compileTime proc: riesig"
"""
proc riesig(): NimNode = discard
discard riesig()

View File

@@ -0,0 +1,14 @@
discard """
errormsg: "cannot assign local to global variable"
line: 11
"""
proc main() =
var x = "hi"
proc p() =
echo x
let a {.global.} = p
p()
main()

View File

@@ -0,0 +1,17 @@
discard """
errormsg: "cannot assign local to global variable"
line: 14
"""
type X = object
p: proc() {.closure.}
proc main() =
var x = "hi"
proc p() =
echo x
let a {.global.} = X(p: p)
a.p()
main()

View File

@@ -0,0 +1,17 @@
discard """
output: "hi\nhi"
"""
type X = object
p: proc() {.nimcall.}
proc main() =
proc p() =
echo "hi"
let a {.global.} = p
let b {.global.} = X(p: p)
a()
b.p()
main()

View File

@@ -412,3 +412,15 @@ block: # bug #24033
collections.add (id, str, $num)
doAssert collections[1] == (1, "foo", "3.14")
block: # bug #25121
iterator k(): int =
when nimvm:
yield 0
else:
yield 0
for _ in k():
(proc() = (; let _ = block: 0))()

View File

@@ -258,6 +258,17 @@ block: # any
doAssert any(anumbers, proc (x: int): bool = return x > 8) == true
doAssert any(anumbers, proc (x: int): bool = return x > 9) == false
block: # findIt
let
numbers = @[1, 4, 5, 8, 9, 7, 4]
anumbers = [1, 4, 5, 8, 9, 7, 4]
len0seq: seq[int] = @[]
doAssert findIt(numbers, it == 4) == 1
doAssert findIt(numbers, it > 9) == -1
doAssert findIt(len0seq, true) == -1
doAssert findIt(anumbers, it > 8) == 4
doAssert findIt(anumbers, it > 9) == -1
block: # anyIt
let
numbers = @[1, 4, 5, 8, 9, 7, 4]

View File

@@ -789,12 +789,71 @@ bar
block: # formatSize
disableVm:
when hasWorkingInt64:
doAssert formatSize(1024'i64 * 1024 * 1024 * 2 - 1) == "1.999GiB"
doAssert formatSize(1024'i64 * 1024 * 1024 * 2) == "2GiB"
doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB" # <=== bug #8231
doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
doAssert formatSize(int64.high) == "7.999EiB"
doAssert formatSize(int64.high div 2 + 1) == "4EiB"
doAssert formatSize(int64.high div 2) == "3.999EiB"
doAssert formatSize(int64.high div 4 + 1) == "2EiB"
doAssert formatSize(int64.high div 4) == "1.999EiB"
doAssert formatSize(int64.high div 8 + 1) == "1EiB"
doAssert formatSize(int64.high div 8) == "1023.999PiB"
doAssert formatSize(int64.high div 16 + 1) == "512PiB"
doAssert formatSize(int64.high div 16) == "511.999PiB"
doAssert formatSize(0) == "0B"
doAssert formatSize(0, includeSpace = true) == "0 B"
doAssert formatSize(1) == "1B"
doAssert formatSize(2) == "2B"
doAssert formatSize(1022) == "1022B"
doAssert formatSize(1023) == "1023B"
doAssert formatSize(1024) == "1KiB"
doAssert formatSize(1025) == "1.001KiB"
doAssert formatSize(1026) == "1.002KiB"
doAssert formatSize(1024 * 2 - 2) == "1.998KiB"
doAssert formatSize(1024 * 2 - 1) == "1.999KiB"
doAssert formatSize(1024 * 2) == "2KiB"
doAssert formatSize(1024 * 2 + 1) == "2.001KiB"
doAssert formatSize(1024 * 2 + 2) == "2.002KiB"
doAssert formatSize(4096 - 1) == "3.999KiB"
doAssert formatSize(4096) == "4KiB"
doAssert formatSize(4096 + 1) == "4.001KiB"
doAssert formatSize(1024 * 512 - 1) == "511.999KiB"
doAssert formatSize(1024 * 512) == "512KiB"
doAssert formatSize(1024 * 512 + 1) == "512.001KiB"
doAssert formatSize(1024 * 1024 - 2) == "1023.998KiB"
doAssert formatSize(1024 * 1024 - 1) == "1023.999KiB"
doAssert formatSize(1024 * 1024) == "1MiB"
doAssert formatSize(1024 * 1024 + 1) == "1MiB"
doAssert formatSize(1024 * 1024 + 1023) == "1MiB"
doAssert formatSize(1024 * 1024 + 1024) == "1.001MiB"
doAssert formatSize(1024 * 1024 + 1024 * 2) == "1.002MiB"
doAssert formatSize(1024 * 1024 * 2 - 1) == "1.999MiB"
doAssert formatSize(1024 * 1024 * 2) == "2MiB"
doAssert formatSize(1024 * 1024 * 2 + 1) == "2MiB"
doAssert formatSize(1024 * 1024 * 2 + 1024) == "2.001MiB"
doAssert formatSize(1024 * 1024 * 2 + 1024 * 2) == "2.002MiB"
doAssert formatSize(1024 * 1024 * 4 - 1) == "3.999MiB"
doAssert formatSize(1024 * 1024 * 4) == "4MiB"
doAssert formatSize(1024 * (1024 * 4 + 1)) == "4.001MiB"
doAssert formatSize(1024 * 1024 * 512 - 1025) == "511.998MiB"
doAssert formatSize(1024 * 1024 * 512 - 1) == "511.999MiB"
doAssert formatSize(1024 * 1024 * 512) == "512MiB"
doAssert formatSize(1024 * 1024 * 512 + 1) == "512MiB"
doAssert formatSize(1024 * 1024 * 512 + 1024) == "512.001MiB"
doAssert formatSize(1024 * 1024 * 512 + 1024 * 2) == "512.002MiB"
doAssert formatSize(1024 * 1024 * 1024 - 1) == "1023.999MiB"
doAssert formatSize(1024 * 1024 * 1024) == "1GiB"
doAssert formatSize(1024 * 1024 * 1024 + 1) == "1GiB"
doAssert formatSize(1024 * 1024 * 1025) == "1.001GiB"
doAssert formatSize(1024 * 1024 * 1026) == "1.002GiB"
# != 2.234MiB as (2.234 * 1024 * 1024).int.float / (1024 * 1024) = 2.23399...
# and formatSize round down the value
doAssert formatSize((2.234*1024*1024).int) == "2.233MiB"
doAssert formatSize(4096, prefix = bpColloquial, includeSpace = true) == "4 kB"
doAssert formatSize(4096, includeSpace = true) == "4 KiB"
doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,13MB"
# (5378934).float / (1024 * 1024) = 5.12975...
doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,129MB"
block: # formatEng
disableVm:

View File

@@ -4,6 +4,18 @@ import re
import sys
import traceback
# Add compatibility for older GDB versions
if not hasattr(gdb, 'SYMBOL_FUNCTION_DOMAIN'):
gdb.SYMBOL_FUNCTION_DOMAIN = 0 # This is the value used in newer GDB versions
# Configure demangling for Itanium C++ ABI (which Nim uses)
try:
gdb.execute("set demangle-style gnu-v3") # GNU v3 style handles Itanium mangling
gdb.execute("set print asm-demangle on")
gdb.execute("set print demangle on")
except Exception as e:
gdb.write(f"Warning: Could not configure demangling: {str(e)}\n", gdb.STDERR)
# some feedback that the nim runtime support is loading, isn't a bad
# thing at all.
gdb.write("Loading Nim Runtime support.\n", gdb.STDERR)
@@ -70,12 +82,12 @@ class NimTypeRecognizer:
type_map_static = {
'NI': 'system.int', 'NI8': 'int8', 'NI16': 'int16', 'NI32': 'int32',
'NI64': 'int64',
'NU': 'uint', 'NU8': 'uint8','NU16': 'uint16', 'NU32': 'uint32',
'NU64': 'uint64',
'NF': 'float', 'NF32': 'float32', 'NF64': 'float64',
'NIM_BOOL': 'bool',
'NIM_CHAR': 'char', 'NCSTRING': 'cstring', 'NimStringDesc': 'string', 'NimStringV2': 'string'
@@ -556,7 +568,7 @@ class NimSeqPrinter:
except RuntimeError:
inaccessible = True
yield "data[{0}]".format(i), "inaccessible"
################################################################################
class NimArrayPrinter: