more progress on destructor based strings
This commit is contained in:
parent
5b59852406
commit
74bf316619
16 changed files with 279 additions and 244 deletions
|
|
@ -124,15 +124,19 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
|
||||||
of tyString, tySequence:
|
of tyString, tySequence:
|
||||||
if skipTypes(n.typ, abstractInst).kind == tyVar and
|
if skipTypes(n.typ, abstractInst).kind == tyVar and
|
||||||
not compileToCpp(p.module):
|
not compileToCpp(p.module):
|
||||||
result = "(*$1)$3, (*$1 ? (*$1)->$2 : 0)" % [a.rdLoc, lenField(p), dataField(p)]
|
var t: TLoc
|
||||||
|
t.r = "(*$1)" % [a.rdLoc]
|
||||||
|
result = "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
|
||||||
else:
|
else:
|
||||||
result = "$1$3, ($1 ? $1->$2 : 0)" % [a.rdLoc, lenField(p), dataField(p)]
|
result = "$1$3, $2" % [a.rdLoc, lenExpr(p, a), dataField(p)]
|
||||||
of tyArray:
|
of tyArray:
|
||||||
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))]
|
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))]
|
||||||
of tyPtr, tyRef:
|
of tyPtr, tyRef:
|
||||||
case lastSon(a.t).kind
|
case lastSon(a.t).kind
|
||||||
of tyString, tySequence:
|
of tyString, tySequence:
|
||||||
result = "(*$1)$3, (*$1 ? (*$1)->$2 : 0)" % [a.rdLoc, lenField(p), dataField(p)]
|
var t: TLoc
|
||||||
|
t.r = "(*$1)" % [a.rdLoc]
|
||||||
|
result = "(*$1)$3, (*$1 ? (*$1)->$2 : 0)" % [a.rdLoc, lenExpr(p, t), dataField(p)]
|
||||||
of tyArray:
|
of tyArray:
|
||||||
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, lastSon(a.t)))]
|
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, lastSon(a.t)))]
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,12 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
# tfShallow flag for the built-in string type too! So we check only
|
# tfShallow flag for the built-in string type too! So we check only
|
||||||
# here for this flag, where it is reasonably safe to do so
|
# here for this flag, where it is reasonably safe to do so
|
||||||
# (for objects, etc.):
|
# (for objects, etc.):
|
||||||
if needToCopy notin flags or
|
if p.config.selectedGC == gcDestructors:
|
||||||
|
useStringh(p.module)
|
||||||
|
linefmt(p, cpsStmts,
|
||||||
|
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
||||||
|
addrLoc(p.config, dest), addrLoc(p.config, src), rdLoc(dest))
|
||||||
|
elif needToCopy notin flags or
|
||||||
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
|
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
|
||||||
if dest.storage == OnStack or not usesWriteBarrier(p.config):
|
if dest.storage == OnStack or not usesWriteBarrier(p.config):
|
||||||
useStringh(p.module)
|
useStringh(p.module)
|
||||||
|
|
@ -280,14 +285,18 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
of tyRef:
|
of tyRef:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
if (needToCopy notin flags and src.storage != OnStatic) or canMove(src.lode):
|
if p.config.selectedGC == gcDestructors:
|
||||||
|
genGenericAsgn(p, dest, src, flags)
|
||||||
|
elif (needToCopy notin flags and src.storage != OnStatic) or canMove(src.lode):
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
||||||
addrLoc(p.config, dest), rdLoc(src),
|
addrLoc(p.config, dest), rdLoc(src),
|
||||||
genTypeInfo(p.module, dest.t, dest.lode.info))
|
genTypeInfo(p.module, dest.t, dest.lode.info))
|
||||||
of tyString:
|
of tyString:
|
||||||
if (needToCopy notin flags and src.storage != OnStatic) or canMove(src.lode):
|
if p.config.selectedGC == gcDestructors:
|
||||||
|
genGenericAsgn(p, dest, src, flags)
|
||||||
|
elif (needToCopy notin flags and src.storage != OnStatic) or canMove(src.lode):
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
if dest.storage == OnStack or not usesWriteBarrier(p.config):
|
if dest.storage == OnStack or not usesWriteBarrier(p.config):
|
||||||
|
|
@ -457,6 +466,13 @@ proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||||
initLocExpr(p, e.sons[2], b)
|
initLocExpr(p, e.sons[2], b)
|
||||||
lineCg(p, cpsStmts, frmt, rdLoc(a), rdLoc(b))
|
lineCg(p, cpsStmts, frmt, rdLoc(a), rdLoc(b))
|
||||||
|
|
||||||
|
proc binaryStmtAddr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||||
|
var a, b: TLoc
|
||||||
|
if d.k != locNone: internalError(p.config, e.info, "binaryStmtAddr")
|
||||||
|
initLocExpr(p, e.sons[1], a)
|
||||||
|
initLocExpr(p, e.sons[2], b)
|
||||||
|
lineCg(p, cpsStmts, frmt, addrLoc(p.config, a), rdLoc(b))
|
||||||
|
|
||||||
proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
if d.k != locNone: internalError(p.config, e.info, "unaryStmt")
|
if d.k != locNone: internalError(p.config, e.info, "unaryStmt")
|
||||||
|
|
@ -893,8 +909,8 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc) =
|
||||||
of tySequence, tyString:
|
of tySequence, tyString:
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
"if ($2-$1 != -1 && " &
|
"if ($2-$1 != -1 && " &
|
||||||
"(!$3 || (NU)($1) >= (NU)($3->$4) || (NU)($2) >= (NU)($3->$4))) #raiseIndexError();$n",
|
"((NU)($1) >= (NU)$3 || (NU)($2) >= (NU)$3)) #raiseIndexError();$n",
|
||||||
rdLoc(a), rdLoc(b), rdLoc(arr), lenField(p))
|
rdLoc(a), rdLoc(b), lenExpr(p, arr))
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||||
|
|
@ -918,12 +934,12 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||||
if optBoundsCheck in p.options:
|
if optBoundsCheck in p.options:
|
||||||
if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options):
|
if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options):
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
"if (!$2 || (NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
|
"if ((NU)($1) > (NU)$2) #raiseIndexError();$n",
|
||||||
rdLoc(b), rdLoc(a), lenField(p))
|
rdLoc(b), lenExpr(p, a))
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
"if (!$2 || (NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
"if ((NU)($1) >= (NU)$2) #raiseIndexError();$n",
|
||||||
rdLoc(b), rdLoc(a), lenField(p))
|
rdLoc(b), lenExpr(p, a))
|
||||||
if d.k == locNone: d.storage = OnHeap
|
if d.k == locNone: d.storage = OnHeap
|
||||||
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
||||||
a.r = ropecg(p.module, "(*$1)", a.r)
|
a.r = ropecg(p.module, "(*$1)", a.r)
|
||||||
|
|
@ -1013,6 +1029,12 @@ proc genEcho(p: BProc, n: PNode) =
|
||||||
proc gcUsage(conf: ConfigRef; n: PNode) =
|
proc gcUsage(conf: ConfigRef; n: PNode) =
|
||||||
if conf.selectedGC == gcNone: message(conf, n.info, warnGcMem, n.renderTree)
|
if conf.selectedGC == gcNone: message(conf, n.info, warnGcMem, n.renderTree)
|
||||||
|
|
||||||
|
proc strLoc(p: BProc; d: TLoc): Rope =
|
||||||
|
if p.config.selectedGc == gcDestructors:
|
||||||
|
result = addrLoc(p.config, d)
|
||||||
|
else:
|
||||||
|
result = rdLoc(d)
|
||||||
|
|
||||||
proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||||
# <Nim code>
|
# <Nim code>
|
||||||
# s = 'Hello ' & name & ', how do you feel?' & 'z'
|
# s = 'Hello ' & name & ', how do you feel?' & 'z'
|
||||||
|
|
@ -1040,13 +1062,14 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, e.sons[i + 1], a)
|
initLocExpr(p, e.sons[i + 1], a)
|
||||||
if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar:
|
if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar:
|
||||||
inc(L)
|
inc(L)
|
||||||
add(appends, ropecg(p.module, "#appendChar($1, $2);$n", tmp.r, rdLoc(a)))
|
add(appends, ropecg(p.module, "#appendChar($1, $2);$n", strLoc(p, tmp), rdLoc(a)))
|
||||||
else:
|
else:
|
||||||
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
|
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
inc(L, len(e.sons[i + 1].strVal))
|
inc(L, len(e.sons[i + 1].strVal))
|
||||||
else:
|
else:
|
||||||
addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)])
|
add(lens, lenExpr(p, a))
|
||||||
add(appends, ropecg(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a)))
|
add(lens, " + ")
|
||||||
|
add(appends, ropecg(p.module, "#appendString($1, $2);$n", strLoc(p, tmp), rdLoc(a)))
|
||||||
linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L))
|
linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L))
|
||||||
add(p.s(cpsStmts), appends)
|
add(p.s(cpsStmts), appends)
|
||||||
if d.k == locNone:
|
if d.k == locNone:
|
||||||
|
|
@ -1079,14 +1102,19 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar:
|
if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar:
|
||||||
inc(L)
|
inc(L)
|
||||||
add(appends, ropecg(p.module, "#appendChar($1, $2);$n",
|
add(appends, ropecg(p.module, "#appendChar($1, $2);$n",
|
||||||
rdLoc(dest), rdLoc(a)))
|
strLoc(p, dest), rdLoc(a)))
|
||||||
else:
|
else:
|
||||||
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
|
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
inc(L, len(e.sons[i + 2].strVal))
|
inc(L, len(e.sons[i + 2].strVal))
|
||||||
else:
|
else:
|
||||||
addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)])
|
add(lens, lenExpr(p, a))
|
||||||
|
add(lens, " + ")
|
||||||
add(appends, ropecg(p.module, "#appendString($1, $2);$n",
|
add(appends, ropecg(p.module, "#appendString($1, $2);$n",
|
||||||
rdLoc(dest), rdLoc(a)))
|
strLoc(p, dest), rdLoc(a)))
|
||||||
|
if p.config.selectedGC == gcDestructors:
|
||||||
|
linefmt(p, cpsStmts, "#prepareAdd($1, $2$3);$n",
|
||||||
|
addrLoc(p.config, dest), lens, rope(L))
|
||||||
|
else:
|
||||||
linefmt(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
|
linefmt(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
|
||||||
rdLoc(dest), lens, rope(L))
|
rdLoc(dest), lens, rope(L))
|
||||||
add(p.s(cpsStmts), appends)
|
add(p.s(cpsStmts), appends)
|
||||||
|
|
@ -1440,7 +1468,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
putIntoDest(p, b, e, "$1, $1Len_0" % [rdLoc(a)], a.storage)
|
putIntoDest(p, b, e, "$1, $1Len_0" % [rdLoc(a)], a.storage)
|
||||||
of tyString, tySequence:
|
of tyString, tySequence:
|
||||||
putIntoDest(p, b, e,
|
putIntoDest(p, b, e,
|
||||||
"$1$3, ($1 ? $1->$2 : 0)" % [rdLoc(a), lenField(p), dataField(p)], a.storage)
|
"$1$3, $2" % [rdLoc(a), lenExpr(p, a), dataField(p)], a.storage)
|
||||||
of tyArray:
|
of tyArray:
|
||||||
putIntoDest(p, b, e,
|
putIntoDest(p, b, e,
|
||||||
"$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))], a.storage)
|
"$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))], a.storage)
|
||||||
|
|
@ -1787,11 +1815,11 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if a.kind in {nkStrLit..nkTripleStrLit} and a.strVal == "":
|
if a.kind in {nkStrLit..nkTripleStrLit} and a.strVal == "":
|
||||||
initLocExpr(p, e.sons[2], x)
|
initLocExpr(p, e.sons[2], x)
|
||||||
putIntoDest(p, d, e,
|
putIntoDest(p, d, e,
|
||||||
ropecg(p.module, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
ropecg(p.module, "($1 == 0)", lenExpr(p, x)))
|
||||||
elif b.kind in {nkStrLit..nkTripleStrLit} and b.strVal == "":
|
elif b.kind in {nkStrLit..nkTripleStrLit} and b.strVal == "":
|
||||||
initLocExpr(p, e.sons[1], x)
|
initLocExpr(p, e.sons[1], x)
|
||||||
putIntoDest(p, d, e,
|
putIntoDest(p, d, e,
|
||||||
ropecg(p.module, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
ropecg(p.module, "($1 == 0)", lenExpr(p, x)))
|
||||||
else:
|
else:
|
||||||
binaryExpr(p, e, d, "#eqStrings($1, $2)")
|
binaryExpr(p, e, d, "#eqStrings($1, $2)")
|
||||||
|
|
||||||
|
|
@ -1851,7 +1879,11 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
getTypeDesc(p.module, ranged), res])
|
getTypeDesc(p.module, ranged), res])
|
||||||
|
|
||||||
of mConStrStr: genStrConcat(p, e, d)
|
of mConStrStr: genStrConcat(p, e, d)
|
||||||
of mAppendStrCh: binaryStmt(p, e, d, "$1 = #addChar($1, $2);$n")
|
of mAppendStrCh:
|
||||||
|
if p.config.selectedGC == gcDestructors:
|
||||||
|
binaryStmtAddr(p, e, d, "#nimAddCharV1($1, $2);$n")
|
||||||
|
else:
|
||||||
|
binaryStmt(p, e, d, "$1 = #addChar($1, $2);$n")
|
||||||
of mAppendStrStr: genStrAppend(p, e, d)
|
of mAppendStrStr: genStrAppend(p, e, d)
|
||||||
of mAppendSeqElem: genSeqElemAppend(p, e, d)
|
of mAppendSeqElem: genSeqElemAppend(p, e, d)
|
||||||
of mEqStr: genStrEquals(p, e, d)
|
of mEqStr: genStrEquals(p, e, d)
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,11 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) =
|
||||||
var i: TLoc
|
var i: TLoc
|
||||||
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo(), tyInt), i)
|
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo(), tyInt), i)
|
||||||
let oldCode = p.s(cpsStmts)
|
let oldCode = p.s(cpsStmts)
|
||||||
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2->$3; $1++) {$n",
|
var a: TLoc
|
||||||
[i.r, accessor, lenField(c.p)])
|
a.r = accessor
|
||||||
|
|
||||||
|
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
|
||||||
|
[i.r, lenExpr(c.p, a)])
|
||||||
let oldLen = p.s(cpsStmts).len
|
let oldLen = p.s(cpsStmts).len
|
||||||
genTraverseProc(c, "$1$3[$2]" % [accessor, i.r, dataField(c.p)], typ.sons[0])
|
genTraverseProc(c, "$1$3[$2]" % [accessor, i.r, dataField(c.p)], typ.sons[0])
|
||||||
if p.s(cpsStmts).len == oldLen:
|
if p.s(cpsStmts).len == oldLen:
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
|
||||||
of tyString:
|
of tyString:
|
||||||
case detectStrVersion(m)
|
case detectStrVersion(m)
|
||||||
of 2:
|
of 2:
|
||||||
discard cgsym(m, "string")
|
discard cgsym(m, "NimStringV2")
|
||||||
result = typeNameOrLiteral(m, typ, "NimStringV2")
|
result = typeNameOrLiteral(m, typ, "NimStringV2")
|
||||||
else:
|
else:
|
||||||
discard cgsym(m, "NimStringDesc")
|
discard cgsym(m, "NimStringDesc")
|
||||||
|
|
|
||||||
|
|
@ -235,9 +235,20 @@ proc getTempName(m: BModule): Rope =
|
||||||
result = m.tmpBase & rope(m.labels)
|
result = m.tmpBase & rope(m.labels)
|
||||||
inc m.labels
|
inc m.labels
|
||||||
|
|
||||||
|
proc rdLoc(a: TLoc): Rope =
|
||||||
|
# 'read' location (deref if indirect)
|
||||||
|
result = a.r
|
||||||
|
if lfIndirect in a.flags: result = "(*$1)" % [result]
|
||||||
|
|
||||||
proc lenField(p: BProc): Rope =
|
proc lenField(p: BProc): Rope =
|
||||||
result = rope(if p.module.compileToCpp: "len" else: "Sup.len")
|
result = rope(if p.module.compileToCpp: "len" else: "Sup.len")
|
||||||
|
|
||||||
|
proc lenExpr(p: BProc; a: TLoc): Rope =
|
||||||
|
if p.config.selectedGc == gcDestructors:
|
||||||
|
result = rdLoc(a) & ".len"
|
||||||
|
else:
|
||||||
|
result = "($1 ? $1->$2 : 0)" % [rdLoc(a), lenField(p)]
|
||||||
|
|
||||||
proc dataField(p: BProc): Rope =
|
proc dataField(p: BProc): Rope =
|
||||||
result = rope"->data"
|
result = rope"->data"
|
||||||
|
|
||||||
|
|
@ -246,11 +257,6 @@ include ccgtypes
|
||||||
|
|
||||||
# ------------------------------ Manager of temporaries ------------------
|
# ------------------------------ Manager of temporaries ------------------
|
||||||
|
|
||||||
proc rdLoc(a: TLoc): Rope =
|
|
||||||
# 'read' location (deref if indirect)
|
|
||||||
result = a.r
|
|
||||||
if lfIndirect in a.flags: result = "(*$1)" % [result]
|
|
||||||
|
|
||||||
proc addrLoc(conf: ConfigRef; a: TLoc): Rope =
|
proc addrLoc(conf: ConfigRef; a: TLoc): Rope =
|
||||||
result = a.r
|
result = a.r
|
||||||
if lfIndirect notin a.flags and mapType(conf, a.t) != ctArray:
|
if lfIndirect notin a.flags and mapType(conf, a.t) != ctArray:
|
||||||
|
|
|
||||||
|
|
@ -1049,8 +1049,8 @@ proc transformStmt*(g: ModuleGraph; module: PSym, n: PNode): PNode =
|
||||||
when useEffectSystem: trackTopLevelStmt(g, module, result)
|
when useEffectSystem: trackTopLevelStmt(g, module, result)
|
||||||
#if n.info ?? "temp.nim":
|
#if n.info ?? "temp.nim":
|
||||||
# echo renderTree(result, {renderIds})
|
# echo renderTree(result, {renderIds})
|
||||||
if c.needsDestroyPass:
|
#if c.needsDestroyPass:
|
||||||
result = injectDestructorCalls(g, module, result)
|
# result = injectDestructorCalls(g, module, result)
|
||||||
incl(result.flags, nfTransf)
|
incl(result.flags, nfTransf)
|
||||||
|
|
||||||
proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode): PNode =
|
proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode): PNode =
|
||||||
|
|
@ -1062,6 +1062,6 @@ proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode): PNode =
|
||||||
liftDefer(c, result)
|
liftDefer(c, result)
|
||||||
# expressions are not to be injected with destructor calls as that
|
# expressions are not to be injected with destructor calls as that
|
||||||
# the list of top level statements needs to be collected before.
|
# the list of top level statements needs to be collected before.
|
||||||
if c.needsDestroyPass:
|
#if c.needsDestroyPass:
|
||||||
result = injectDestructorCalls(g, module, result)
|
# result = injectDestructorCalls(g, module, result)
|
||||||
incl(result.flags, nfTransf)
|
incl(result.flags, nfTransf)
|
||||||
|
|
|
||||||
|
|
@ -14,28 +14,15 @@ when false:
|
||||||
|
|
||||||
#proc rawNewStringNoInit(space: int): NimString {.compilerProc.}
|
#proc rawNewStringNoInit(space: int): NimString {.compilerProc.}
|
||||||
# seems to be unused.
|
# seems to be unused.
|
||||||
proc rawNewString(space: int): NimString {.compilerProc.}
|
|
||||||
proc mnewString(len: int): NimString {.compilerProc.}
|
|
||||||
proc copyStrLast(s: NimString, start, last: int): NimString {.compilerProc.}
|
|
||||||
proc nimToCStringConv(s: NimString): cstring {.compilerProc, inline.}
|
|
||||||
proc copyStr(s: NimString, start: int): NimString {.compilerProc.}
|
|
||||||
proc toNimStr(str: cstring, len: int): NimString {.compilerProc.}
|
|
||||||
proc cstrToNimstr(str: cstring): NimString {.compilerRtl.}
|
|
||||||
proc copyString(src: NimString): NimString {.compilerRtl.}
|
|
||||||
proc copyStringRC1(src: NimString): NimString {.compilerRtl.}
|
|
||||||
proc copyDeepString(src: NimString): NimString {.inline.}
|
proc copyDeepString(src: NimString): NimString {.inline.}
|
||||||
proc addChar(s: NimString, c: char): NimString
|
|
||||||
proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.}
|
|
||||||
proc appendString(dest, src: NimString) {.compilerproc, inline.}
|
|
||||||
proc appendChar(dest: NimString, c: char) {.compilerproc, inline.}
|
|
||||||
proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.}
|
proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.}
|
||||||
# ----------------- sequences ----------------------------------------------
|
# ----------------- sequences ----------------------------------------------
|
||||||
|
|
||||||
proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerProc.} =
|
proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerProc.}
|
||||||
proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
|
proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
|
||||||
compilerRtl.}
|
compilerRtl.}
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.}
|
||||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.}
|
||||||
|
|
||||||
import allocators
|
import allocators
|
||||||
|
|
||||||
|
|
@ -45,35 +32,36 @@ type
|
||||||
region: Allocator
|
region: Allocator
|
||||||
data: UncheckedArray[char]
|
data: UncheckedArray[char]
|
||||||
|
|
||||||
NimString {.core.} = object
|
NimStringV2 {.core.} = object
|
||||||
len: int
|
len: int
|
||||||
p: ptr StrContent ## invariant. Never nil
|
p: ptr StrContent ## can be nil if len == 0.
|
||||||
|
|
||||||
const nimStrVersion {.core.} = 2
|
const nimStrVersion {.core.} = 2
|
||||||
|
|
||||||
template isLiteral(s): bool = s.len == 0 or s.p.region == nil
|
template isLiteral(s): bool = s.p == nil or s.p.region == nil
|
||||||
|
|
||||||
template contentSize(cap): int = cap + 1 + sizeof(int) + sizeof(Allocator)
|
template contentSize(cap): int = cap + 1 + sizeof(int) + sizeof(Allocator)
|
||||||
|
|
||||||
template frees(s) =
|
template frees(s) =
|
||||||
if not isLiteral(s):
|
if not isLiteral(s):
|
||||||
s.p.region.dealloc(s.p, contentSize(s.p.cap))
|
s.p.region.dealloc(s.p.region, s.p, contentSize(s.p.cap))
|
||||||
|
|
||||||
proc `=destroy`(s: var NimString) =
|
proc `=destroy`(s: var NimStringV2) =
|
||||||
frees(s)
|
frees(s)
|
||||||
s.len = 0
|
s.len = 0
|
||||||
|
s.p = nil
|
||||||
|
|
||||||
template lose(a) =
|
template lose(a) =
|
||||||
frees(a)
|
frees(a)
|
||||||
|
|
||||||
proc `=sink`(a: var NimString, b: NimString) =
|
proc `=sink`(a: var NimStringV2, b: NimStringV2) =
|
||||||
# we hope this is optimized away for not yet alive objects:
|
# we hope this is optimized away for not yet alive objects:
|
||||||
if unlikely(a.p == b.p): return
|
if unlikely(a.p == b.p): return
|
||||||
lose(a)
|
lose(a)
|
||||||
a.len = b.len
|
a.len = b.len
|
||||||
a.p = b.p
|
a.p = b.p
|
||||||
|
|
||||||
proc `=`(a: var NimString; b: NimString) =
|
proc `=`(a: var NimStringV2; b: NimStringV2) =
|
||||||
if unlikely(a.p == b.p): return
|
if unlikely(a.p == b.p): return
|
||||||
lose(a)
|
lose(a)
|
||||||
a.len = b.len
|
a.len = b.len
|
||||||
|
|
@ -85,7 +73,7 @@ proc `=`(a: var NimString; b: NimString) =
|
||||||
# we have to allocate the 'cap' here, consider
|
# we have to allocate the 'cap' here, consider
|
||||||
# 'let y = newStringOfCap(); var x = y'
|
# 'let y = newStringOfCap(); var x = y'
|
||||||
# on the other hand... These get turned into moves now.
|
# on the other hand... These get turned into moves now.
|
||||||
a.p = cast[ptr StrContent](region.alloc(contentSize(b.len)))
|
a.p = cast[ptr StrContent](region.alloc(region, contentSize(b.len)))
|
||||||
a.p.region = region
|
a.p.region = region
|
||||||
a.p.cap = b.len
|
a.p.cap = b.len
|
||||||
copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
|
copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
|
||||||
|
|
@ -95,12 +83,12 @@ proc resize(old: int): int {.inline.} =
|
||||||
elif old < 65536: result = old * 2
|
elif old < 65536: result = old * 2
|
||||||
else: result = old * 3 div 2 # for large arrays * 3/2 is better
|
else: result = old * 3 div 2 # for large arrays * 3/2 is better
|
||||||
|
|
||||||
proc prepareAdd(s: var NimString; addlen: int) =
|
proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} =
|
||||||
if isLiteral(s):
|
if isLiteral(s):
|
||||||
let oldP = s.p
|
let oldP = s.p
|
||||||
# can't mutate a literal, so we need a fresh copy here:
|
# can't mutate a literal, so we need a fresh copy here:
|
||||||
let region = getLocalAllocator()
|
let region = getLocalAllocator()
|
||||||
s.p = cast[ptr StrContent](region.alloc(contentSize(s.len + addlen)))
|
s.p = cast[ptr StrContent](region.alloc(region, contentSize(s.len + addlen)))
|
||||||
s.p.region = region
|
s.p.region = region
|
||||||
s.p.cap = s.len + addlen
|
s.p.cap = s.len + addlen
|
||||||
if s.len > 0:
|
if s.len > 0:
|
||||||
|
|
@ -108,61 +96,65 @@ proc prepareAdd(s: var NimString; addlen: int) =
|
||||||
copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], s.len)
|
copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], s.len)
|
||||||
elif s.len + addlen > s.p.cap:
|
elif s.len + addlen > s.p.cap:
|
||||||
let cap = max(s.len + addlen, resize(s.p.cap))
|
let cap = max(s.len + addlen, resize(s.p.cap))
|
||||||
s.p = s.p.region.realloc(s.p, oldSize = contentSize(s.p.cap), newSize = contentSize(cap))
|
s.p = cast[ptr StrContent](s.p.region.realloc(s.p.region, s.p,
|
||||||
|
oldSize = contentSize(s.p.cap),
|
||||||
|
newSize = contentSize(cap)))
|
||||||
s.p.cap = cap
|
s.p.cap = cap
|
||||||
|
|
||||||
proc nimAddCharV1(s: var NimString; c: char) {.compilerRtl.} =
|
proc nimAddCharV1(s: var NimStringV2; c: char) {.compilerRtl.} =
|
||||||
prepareAdd(s, 1)
|
prepareAdd(s, 1)
|
||||||
s.p.data[s.len] = c
|
s.p.data[s.len] = c
|
||||||
s.p.data[s.len+1] = '\0'
|
s.p.data[s.len+1] = '\0'
|
||||||
inc s.len
|
inc s.len
|
||||||
|
|
||||||
proc ensure(s: var string; newLen: int) =
|
proc toNimStr(str: cstring, len: int): NimStringV2 {.compilerProc.} =
|
||||||
let old = s.cap
|
if len <= 0:
|
||||||
if newLen >= old:
|
result = NimStringV2(len: 0, p: nil)
|
||||||
s.cap = max((old * 3) shr 1, newLen)
|
else:
|
||||||
if s.cap > 0:
|
let region = getLocalAllocator()
|
||||||
s.data = cast[type(s.data)](realloc(s.data, old + 1, s.cap + 1))
|
var p = cast[ptr StrContent](region.alloc(region, contentSize(len)))
|
||||||
|
p.region = region
|
||||||
proc add*(s: var string; y: string) =
|
p.cap = len
|
||||||
if y.len != 0:
|
|
||||||
let newLen = s.len + y.len
|
|
||||||
ensure(s, newLen)
|
|
||||||
copyMem(addr s.data[len], y.data, y.data.len + 1)
|
|
||||||
s.len = newLen
|
|
||||||
|
|
||||||
proc newString*(len: int): string =
|
|
||||||
result.len = len
|
|
||||||
result.cap = len
|
|
||||||
if len > 0:
|
if len > 0:
|
||||||
result.data = alloc0(len+1)
|
# we are about to append, so there is no need to copy the \0 terminator:
|
||||||
|
copyMem(unsafeAddr p.data[0], str, len)
|
||||||
|
result = NimStringV2(len: 0, p: p)
|
||||||
|
|
||||||
converter toCString(x: string): cstring {.core, inline.} =
|
proc cstrToNimstr(str: cstring): NimStringV2 {.compilerRtl.} =
|
||||||
if x.len == 0: cstring"" else: cast[cstring](x.data)
|
if str == nil: toNimStr(str, 0)
|
||||||
|
else: toNimStr(str, str.len)
|
||||||
|
|
||||||
proc newStringOfCap*(cap: int): string =
|
proc nimToCStringConv(s: NimStringV2): cstring {.compilerProc, inline.} =
|
||||||
result.len = 0
|
if s.len == 0: result = cstring""
|
||||||
result.cap = cap
|
else: result = cstring(unsafeAddr s.p.data)
|
||||||
if cap > 0:
|
|
||||||
result.data = alloc(cap+1)
|
|
||||||
|
|
||||||
proc `&`*(a, b: string): string =
|
proc appendString(dest: var NimStringV2; src: NimStringV2) {.compilerproc, inline.} =
|
||||||
let sum = a.len + b.len
|
if src.len > 0:
|
||||||
result = newStringOfCap(sum)
|
# also copy the \0 terminator:
|
||||||
result.len = sum
|
copyMem(unsafeAddr dest.p.data[dest.len], unsafeAddr src.p.data[0], src.len+1)
|
||||||
copyMem(addr result.data[0], a.data, a.len)
|
|
||||||
copyMem(addr result.data[a.len], b.data, b.len)
|
|
||||||
if sum > 0:
|
|
||||||
result.data[sum] = '\0'
|
|
||||||
|
|
||||||
proc concat(x: openArray[string]): string {.core.} =
|
proc appendChar(dest: var NimStringV2; c: char) {.compilerproc, inline.} =
|
||||||
## used be the code generator to optimize 'x & y & z ...'
|
dest.p.data[dest.len] = c
|
||||||
var sum = 0
|
dest.p.data[dest.len+1] = '\0'
|
||||||
for i in 0 ..< x.len: inc(sum, x[i].len)
|
inc dest.len
|
||||||
result = newStringOfCap(sum)
|
|
||||||
sum = 0
|
|
||||||
for i in 0 ..< x.len:
|
|
||||||
let L = x[i].len
|
|
||||||
copyMem(addr result.data[sum], x[i].data, L)
|
|
||||||
inc(sum, L)
|
|
||||||
|
|
||||||
|
proc rawNewString(space: int): NimStringV2 {.compilerProc.} =
|
||||||
|
# this is also 'system.newStringOfCap'.
|
||||||
|
if space <= 0:
|
||||||
|
result = NimStringV2(len: 0, p: nil)
|
||||||
|
else:
|
||||||
|
let region = getLocalAllocator()
|
||||||
|
var p = cast[ptr StrContent](region.alloc(region, contentSize(space)))
|
||||||
|
p.region = region
|
||||||
|
p.cap = space
|
||||||
|
result = NimStringV2(len: 0, p: p)
|
||||||
|
|
||||||
|
proc mnewString(len: int): NimStringV2 {.compilerProc.} =
|
||||||
|
if len <= 0:
|
||||||
|
result = NimStringV2(len: 0, p: nil)
|
||||||
|
else:
|
||||||
|
let region = getLocalAllocator()
|
||||||
|
var p = cast[ptr StrContent](region.alloc(region, contentSize(len)))
|
||||||
|
p.region = region
|
||||||
|
p.cap = len
|
||||||
|
result = NimStringV2(len: len, p: p)
|
||||||
|
|
|
||||||
147
lib/system.nim
147
lib/system.nim
|
|
@ -211,6 +211,7 @@ proc new*(T: typedesc): auto =
|
||||||
new(r)
|
new(r)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
const ThisIsSystem = true
|
||||||
|
|
||||||
proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.}
|
proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.}
|
||||||
## leaked implementation detail. Do not use.
|
## leaked implementation detail. Do not use.
|
||||||
|
|
@ -426,6 +427,7 @@ when not defined(JS) and not defined(gcDestructors):
|
||||||
NimString = ptr NimStringDesc
|
NimString = ptr NimStringDesc
|
||||||
|
|
||||||
when not defined(JS) and not defined(nimscript):
|
when not defined(JS) and not defined(nimscript):
|
||||||
|
when not defined(gcDestructors):
|
||||||
template space(s: PGenericSeq): int {.dirty.} =
|
template space(s: PGenericSeq): int {.dirty.} =
|
||||||
s.reserved and not (seqShallowFlag or strlitFlag)
|
s.reserved and not (seqShallowFlag or strlitFlag)
|
||||||
include "system/hti"
|
include "system/hti"
|
||||||
|
|
@ -730,7 +732,8 @@ proc newSeqOfCap*[T](cap: Natural): seq[T] {.
|
||||||
## ``cap``.
|
## ``cap``.
|
||||||
discard
|
discard
|
||||||
|
|
||||||
when not defined(JS):
|
when not defined(JS) and not defined(gcDestructors):
|
||||||
|
# XXX enable this for --gc:destructors
|
||||||
proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] =
|
proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] =
|
||||||
## creates a new sequence of type ``seq[T]`` with length ``len``.
|
## creates a new sequence of type ``seq[T]`` with length ``len``.
|
||||||
##
|
##
|
||||||
|
|
@ -1502,11 +1505,11 @@ const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(n
|
||||||
|
|
||||||
when not defined(JS) and not defined(nimscript) and hostOS != "standalone":
|
when not defined(JS) and not defined(nimscript) and hostOS != "standalone":
|
||||||
include "system/cgprocs"
|
include "system/cgprocs"
|
||||||
when not defined(JS) and not defined(nimscript) and hasAlloc:
|
when not defined(JS) and not defined(nimscript) and hasAlloc and not defined(gcDestructors):
|
||||||
proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.}
|
proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.}
|
||||||
|
|
||||||
proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.}
|
proc add*[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.}
|
||||||
proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} =
|
proc add*[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} =
|
||||||
## Generic proc for adding a data item `y` to a container `x`.
|
## Generic proc for adding a data item `y` to a container `x`.
|
||||||
## For containers that have an order, `add` means *append*. New generic
|
## For containers that have an order, `add` means *append*. New generic
|
||||||
## containers should also call their adding proc `add` for consistency.
|
## containers should also call their adding proc `add` for consistency.
|
||||||
|
|
@ -2829,6 +2832,58 @@ else:
|
||||||
if x < 0: -x else: x
|
if x < 0: -x else: x
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
|
when not defined(JS):
|
||||||
|
proc likely_proc(val: bool): bool {.importc: "likely", nodecl, nosideeffect.}
|
||||||
|
proc unlikely_proc(val: bool): bool {.importc: "unlikely", nodecl, nosideeffect.}
|
||||||
|
|
||||||
|
template likely*(val: bool): bool =
|
||||||
|
## Hints the optimizer that `val` is likely going to be true.
|
||||||
|
##
|
||||||
|
## You can use this template to decorate a branch condition. On certain
|
||||||
|
## platforms this can help the processor predict better which branch is
|
||||||
|
## going to be run. Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## for value in inputValues:
|
||||||
|
## if likely(value <= 100):
|
||||||
|
## process(value)
|
||||||
|
## else:
|
||||||
|
## echo "Value too big!"
|
||||||
|
##
|
||||||
|
## On backends without branch prediction (JS and the nimscript VM), this
|
||||||
|
## template will not affect code execution.
|
||||||
|
when nimvm:
|
||||||
|
val
|
||||||
|
else:
|
||||||
|
when defined(JS):
|
||||||
|
val
|
||||||
|
else:
|
||||||
|
likely_proc(val)
|
||||||
|
|
||||||
|
template unlikely*(val: bool): bool =
|
||||||
|
## Hints the optimizer that `val` is likely going to be false.
|
||||||
|
##
|
||||||
|
## You can use this proc to decorate a branch condition. On certain
|
||||||
|
## platforms this can help the processor predict better which branch is
|
||||||
|
## going to be run. Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## for value in inputValues:
|
||||||
|
## if unlikely(value > 100):
|
||||||
|
## echo "Value too big!"
|
||||||
|
## else:
|
||||||
|
## process(value)
|
||||||
|
##
|
||||||
|
## On backends without branch prediction (JS and the nimscript VM), this
|
||||||
|
## template will not affect code execution.
|
||||||
|
when nimvm:
|
||||||
|
val
|
||||||
|
else:
|
||||||
|
when defined(JS):
|
||||||
|
val
|
||||||
|
else:
|
||||||
|
unlikely_proc(val)
|
||||||
|
|
||||||
type
|
type
|
||||||
FileSeekPos* = enum ## Position relative to which seek should happen
|
FileSeekPos* = enum ## Position relative to which seek should happen
|
||||||
# The values are ordered so that they match with stdio
|
# The values are ordered so that they match with stdio
|
||||||
|
|
@ -2862,6 +2917,7 @@ when not defined(JS): #and not defined(nimscript):
|
||||||
when declared(nimGC_setStackBottom):
|
when declared(nimGC_setStackBottom):
|
||||||
nimGC_setStackBottom(locals)
|
nimGC_setStackBottom(locals)
|
||||||
|
|
||||||
|
when not defined(gcDestructors):
|
||||||
{.push profiler: off.}
|
{.push profiler: off.}
|
||||||
var
|
var
|
||||||
strDesc = TNimType(size: sizeof(string), kind: tyString, flags: {ntfAcyclic})
|
strDesc = TNimType(size: sizeof(string), kind: tyString, flags: {ntfAcyclic})
|
||||||
|
|
@ -3302,6 +3358,7 @@ when not defined(JS): #and not defined(nimscript):
|
||||||
while f.readLine(res): yield res
|
while f.readLine(res): yield res
|
||||||
|
|
||||||
when not defined(nimscript) and hasAlloc:
|
when not defined(nimscript) and hasAlloc:
|
||||||
|
when not defined(gcDestructors):
|
||||||
include "system/assign"
|
include "system/assign"
|
||||||
include "system/repr"
|
include "system/repr"
|
||||||
|
|
||||||
|
|
@ -3410,58 +3467,6 @@ proc quit*(errormsg: string, errorcode = QuitFailure) {.noReturn.} =
|
||||||
{.pop.} # checks
|
{.pop.} # checks
|
||||||
{.pop.} # hints
|
{.pop.} # hints
|
||||||
|
|
||||||
when not defined(JS):
|
|
||||||
proc likely_proc(val: bool): bool {.importc: "likely", nodecl, nosideeffect.}
|
|
||||||
proc unlikely_proc(val: bool): bool {.importc: "unlikely", nodecl, nosideeffect.}
|
|
||||||
|
|
||||||
template likely*(val: bool): bool =
|
|
||||||
## Hints the optimizer that `val` is likely going to be true.
|
|
||||||
##
|
|
||||||
## You can use this template to decorate a branch condition. On certain
|
|
||||||
## platforms this can help the processor predict better which branch is
|
|
||||||
## going to be run. Example:
|
|
||||||
##
|
|
||||||
## .. code-block:: nim
|
|
||||||
## for value in inputValues:
|
|
||||||
## if likely(value <= 100):
|
|
||||||
## process(value)
|
|
||||||
## else:
|
|
||||||
## echo "Value too big!"
|
|
||||||
##
|
|
||||||
## On backends without branch prediction (JS and the nimscript VM), this
|
|
||||||
## template will not affect code execution.
|
|
||||||
when nimvm:
|
|
||||||
val
|
|
||||||
else:
|
|
||||||
when defined(JS):
|
|
||||||
val
|
|
||||||
else:
|
|
||||||
likely_proc(val)
|
|
||||||
|
|
||||||
template unlikely*(val: bool): bool =
|
|
||||||
## Hints the optimizer that `val` is likely going to be false.
|
|
||||||
##
|
|
||||||
## You can use this proc to decorate a branch condition. On certain
|
|
||||||
## platforms this can help the processor predict better which branch is
|
|
||||||
## going to be run. Example:
|
|
||||||
##
|
|
||||||
## .. code-block:: nim
|
|
||||||
## for value in inputValues:
|
|
||||||
## if unlikely(value > 100):
|
|
||||||
## echo "Value too big!"
|
|
||||||
## else:
|
|
||||||
## process(value)
|
|
||||||
##
|
|
||||||
## On backends without branch prediction (JS and the nimscript VM), this
|
|
||||||
## template will not affect code execution.
|
|
||||||
when nimvm:
|
|
||||||
val
|
|
||||||
else:
|
|
||||||
when defined(JS):
|
|
||||||
val
|
|
||||||
else:
|
|
||||||
unlikely_proc(val)
|
|
||||||
|
|
||||||
proc `/`*(x, y: int): float {.inline, noSideEffect.} =
|
proc `/`*(x, y: int): float {.inline, noSideEffect.} =
|
||||||
## integer division that results in a float.
|
## integer division that results in a float.
|
||||||
result = toFloat(x) / toFloat(y)
|
result = toFloat(x) / toFloat(y)
|
||||||
|
|
@ -4090,6 +4095,21 @@ template once*(body: untyped): untyped =
|
||||||
|
|
||||||
{.pop.} #{.push warning[GcMem]: off, warning[Uninit]: off.}
|
{.pop.} #{.push warning[GcMem]: off, warning[Uninit]: off.}
|
||||||
|
|
||||||
|
proc substr*(s: string, first, last: int): string =
|
||||||
|
let L = max(min(last, high(s)) - first + 1, 0)
|
||||||
|
result = newString(L)
|
||||||
|
for i in 0 .. L-1:
|
||||||
|
result[i] = s[i+first]
|
||||||
|
|
||||||
|
proc substr*(s: string, first = 0): string =
|
||||||
|
## copies a slice of `s` into a new string and returns this new
|
||||||
|
## string. The bounds `first` and `last` denote the indices of
|
||||||
|
## the first and last characters that shall be copied. If ``last``
|
||||||
|
## is omitted, it is treated as ``high(s)``. If ``last >= s.len``, ``s.len``
|
||||||
|
## is used instead: This means ``substr`` can also be used to `cut`:idx:
|
||||||
|
## or `limit`:idx: a string's length.
|
||||||
|
result = substr(s, first, high(s))
|
||||||
|
|
||||||
when defined(nimconfig):
|
when defined(nimconfig):
|
||||||
include "system/nimscript"
|
include "system/nimscript"
|
||||||
|
|
||||||
|
|
@ -4164,21 +4184,6 @@ when not defined(js):
|
||||||
proc toOpenArrayByte*(x: string; first, last: int): openarray[byte] {.
|
proc toOpenArrayByte*(x: string; first, last: int): openarray[byte] {.
|
||||||
magic: "Slice".}
|
magic: "Slice".}
|
||||||
|
|
||||||
proc substr*(s: string, first, last: int): string =
|
|
||||||
let L = max(min(last, high(s)) - first + 1, 0)
|
|
||||||
result = newString(L)
|
|
||||||
for i in 0 .. L-1:
|
|
||||||
result[i] = s[i+first]
|
|
||||||
|
|
||||||
proc substr*(s: string, first = 0): string =
|
|
||||||
## copies a slice of `s` into a new string and returns this new
|
|
||||||
## string. The bounds `first` and `last` denote the indices of
|
|
||||||
## the first and last characters that shall be copied. If ``last``
|
|
||||||
## is omitted, it is treated as ``high(s)``. If ``last >= s.len``, ``s.len``
|
|
||||||
## is used instead: This means ``substr`` can also be used to `cut`:idx:
|
|
||||||
## or `limit`:idx: a string's length.
|
|
||||||
result = substr(s, first, high(s))
|
|
||||||
|
|
||||||
type
|
type
|
||||||
ForLoopStmt* {.compilerProc.} = object ## special type that marks a macro
|
ForLoopStmt* {.compilerProc.} = object ## special type that marks a macro
|
||||||
## as a `for-loop macro`:idx:
|
## as a `for-loop macro`:idx:
|
||||||
|
|
|
||||||
|
|
@ -202,11 +202,6 @@ proc objectInit(dest: pointer, typ: PNimType) =
|
||||||
|
|
||||||
# ---------------------- assign zero -----------------------------------------
|
# ---------------------- assign zero -----------------------------------------
|
||||||
|
|
||||||
proc nimDestroyRange[T](r: T) {.compilerProc.} =
|
|
||||||
# internal proc used for destroying sequences and arrays
|
|
||||||
mixin `=destroy`
|
|
||||||
for i in countup(0, r.len - 1): `=destroy`(r[i])
|
|
||||||
|
|
||||||
proc genericReset(dest: pointer, mt: PNimType) {.compilerProc, benign.}
|
proc genericReset(dest: pointer, mt: PNimType) {.compilerProc, benign.}
|
||||||
proc genericResetAux(dest: pointer, n: ptr TNimNode) =
|
proc genericResetAux(dest: pointer, n: ptr TNimNode) =
|
||||||
var d = cast[ByteAddress](dest)
|
var d = cast[ByteAddress](dest)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
type
|
type
|
||||||
LibHandle = pointer # private type
|
LibHandle = pointer # private type
|
||||||
ProcAddr = pointer # library loading and loading of procs:
|
ProcAddr = pointer # library loading and loading of procs:
|
||||||
{.deprecated: [TLibHandle: LibHandle, TProcAddr: ProcAddr].}
|
|
||||||
|
|
||||||
proc nimLoadLibrary(path: string): LibHandle {.compilerproc.}
|
proc nimLoadLibrary(path: string): LibHandle {.compilerproc.}
|
||||||
proc nimUnloadLibrary(lib: LibHandle) {.compilerproc.}
|
proc nimUnloadLibrary(lib: LibHandle) {.compilerproc.}
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,7 @@ proc forAllChildren(cell: PCell, op: WalkOp) =
|
||||||
of tyRef, tyOptAsRef: # common case
|
of tyRef, tyOptAsRef: # common case
|
||||||
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
|
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
|
when not defined(gcDestructors):
|
||||||
var d = cast[ByteAddress](cellToUsr(cell))
|
var d = cast[ByteAddress](cellToUsr(cell))
|
||||||
var s = cast[PGenericSeq](d)
|
var s = cast[PGenericSeq](d)
|
||||||
if s != nil:
|
if s != nil:
|
||||||
|
|
@ -310,7 +311,13 @@ proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||||
result = rawNewObj(typ, size, gch)
|
result = rawNewObj(typ, size, gch)
|
||||||
when defined(memProfiler): nimProfile(size)
|
when defined(memProfiler): nimProfile(size)
|
||||||
|
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||||
|
result = rawNewObj(typ, size, gch)
|
||||||
|
zeroMem(result, size)
|
||||||
|
when defined(memProfiler): nimProfile(size)
|
||||||
|
|
||||||
|
when not defined(gcDestructors):
|
||||||
|
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||||
# `newObj` already uses locks, so no need for them here.
|
# `newObj` already uses locks, so no need for them here.
|
||||||
let size = addInt(mulInt(len, typ.base.size), GenericSeqSize)
|
let size = addInt(mulInt(len, typ.base.size), GenericSeqSize)
|
||||||
result = newObj(typ, size)
|
result = newObj(typ, size)
|
||||||
|
|
@ -318,19 +325,14 @@ proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||||
cast[PGenericSeq](result).reserved = len
|
cast[PGenericSeq](result).reserved = len
|
||||||
when defined(memProfiler): nimProfile(size)
|
when defined(memProfiler): nimProfile(size)
|
||||||
|
|
||||||
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||||
result = rawNewObj(typ, size, gch)
|
|
||||||
zeroMem(result, size)
|
|
||||||
when defined(memProfiler): nimProfile(size)
|
|
||||||
|
|
||||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
|
||||||
let size = addInt(mulInt(len, typ.base.size), GenericSeqSize)
|
let size = addInt(mulInt(len, typ.base.size), GenericSeqSize)
|
||||||
result = newObj(typ, size)
|
result = newObj(typ, size)
|
||||||
cast[PGenericSeq](result).len = len
|
cast[PGenericSeq](result).len = len
|
||||||
cast[PGenericSeq](result).reserved = len
|
cast[PGenericSeq](result).reserved = len
|
||||||
when defined(memProfiler): nimProfile(size)
|
when defined(memProfiler): nimProfile(size)
|
||||||
|
|
||||||
proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
|
proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
|
||||||
acquire(gch)
|
acquire(gch)
|
||||||
collectCT(gch, newsize + sizeof(Cell))
|
collectCT(gch, newsize + sizeof(Cell))
|
||||||
var ol = usrToCell(old)
|
var ol = usrToCell(old)
|
||||||
|
|
@ -355,7 +357,7 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
|
||||||
result = cellToUsr(res)
|
result = cellToUsr(res)
|
||||||
when defined(memProfiler): nimProfile(newsize-oldsize)
|
when defined(memProfiler): nimProfile(newsize-oldsize)
|
||||||
|
|
||||||
proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
|
proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
|
||||||
result = growObj(old, newsize, gch)
|
result = growObj(old, newsize, gch)
|
||||||
|
|
||||||
{.push profiler:off.}
|
{.push profiler:off.}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
when declared(NimString):
|
when declared(ThisIsSystem):
|
||||||
# we are in system module:
|
# we are in system module:
|
||||||
{.pragma: codegenType, compilerproc.}
|
{.pragma: codegenType, compilerproc.}
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,6 @@ type
|
||||||
|
|
||||||
JSRef = ref RootObj # Fake type.
|
JSRef = ref RootObj # Fake type.
|
||||||
|
|
||||||
{.deprecated: [TSafePoint: SafePoint, TCallFrame: CallFrame].}
|
|
||||||
|
|
||||||
var
|
var
|
||||||
framePtr {.importc, nodecl, volatile.}: PCallFrame
|
framePtr {.importc, nodecl, volatile.}: PCallFrame
|
||||||
excHandler {.importc, nodecl, volatile.}: int = 0
|
excHandler {.importc, nodecl, volatile.}: int = 0
|
||||||
|
|
@ -506,7 +504,7 @@ proc chckNilDisp(p: pointer) {.compilerproc.} =
|
||||||
if p == nil:
|
if p == nil:
|
||||||
sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil")
|
sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil")
|
||||||
|
|
||||||
type NimString = string # hack for hti.nim
|
const ThisIsSystem = true # for hti.nim
|
||||||
include "system/hti"
|
include "system/hti"
|
||||||
|
|
||||||
proc isFatPointer(ti: PNimType): bool =
|
proc isFatPointer(ti: PNimType): bool =
|
||||||
|
|
|
||||||
|
|
@ -554,7 +554,7 @@ else:
|
||||||
else:
|
else:
|
||||||
include "system/gc"
|
include "system/gc"
|
||||||
|
|
||||||
when not declared(nimNewSeqOfCap):
|
when not declared(nimNewSeqOfCap) and not defined(gcDestructors):
|
||||||
proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
|
proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
|
||||||
when defined(gcRegions):
|
when defined(gcRegions):
|
||||||
let s = mulInt(cap, typ.base.size) # newStr already adds GenericSeqSize
|
let s = mulInt(cap, typ.base.size) # newStr already adds GenericSeqSize
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ proc readLine(f: File, line: var TaintedString): bool =
|
||||||
if line.string.isNil:
|
if line.string.isNil:
|
||||||
line = TaintedString(newStringOfCap(80))
|
line = TaintedString(newStringOfCap(80))
|
||||||
else:
|
else:
|
||||||
when not defined(nimscript):
|
when not defined(nimscript) and not defined(gcDestructors):
|
||||||
sp = cint(cast[PGenericSeq](line.string).space)
|
sp = cint(cast[PGenericSeq](line.string).space)
|
||||||
line.string.setLen(sp)
|
line.string.setLen(sp)
|
||||||
while true:
|
while true:
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,12 @@
|
||||||
# Nim support for C/C++'s `wide strings`:idx:. This is part of the system
|
# Nim support for C/C++'s `wide strings`:idx:. This is part of the system
|
||||||
# module! Do not import it directly!
|
# module! Do not import it directly!
|
||||||
|
|
||||||
when not declared(NimString):
|
when not declared(ThisIsSystem):
|
||||||
{.error: "You must not import this module explicitly".}
|
{.error: "You must not import this module explicitly".}
|
||||||
|
|
||||||
type
|
type
|
||||||
Utf16Char* = distinct int16
|
Utf16Char* = distinct int16
|
||||||
WideCString* = ref UncheckedArray[Utf16Char]
|
WideCString* = ref UncheckedArray[Utf16Char]
|
||||||
{.deprecated: [TUtf16Char: Utf16Char].}
|
|
||||||
|
|
||||||
proc len*(w: WideCString): int =
|
proc len*(w: WideCString): int =
|
||||||
## returns the length of a widestring. This traverses the whole string to
|
## returns the length of a widestring. This traverses the whole string to
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue