fewer ropes (#11037)
This commit is contained in:
parent
a55817f9ac
commit
abb05ab645
8 changed files with 380 additions and 213 deletions
|
|
@ -218,10 +218,12 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
genParamLoop(pl)
|
genParamLoop(pl)
|
||||||
|
|
||||||
template genCallPattern {.dirty.} =
|
template genCallPattern {.dirty.} =
|
||||||
lineF(p, cpsStmts, callPattern & ";$n", [rdLoc(op), pl, pl.addComma, rawProc])
|
if tfIterator in typ.flags:
|
||||||
|
lineF(p, cpsStmts, PatIter & ";$n", [rdLoc(op), pl, pl.addComma, rawProc])
|
||||||
|
else:
|
||||||
|
lineF(p, cpsStmts, PatProc & ";$n", [rdLoc(op), pl, pl.addComma, rawProc])
|
||||||
|
|
||||||
let rawProc = getRawProcType(p, typ)
|
let rawProc = getRawProcType(p, typ)
|
||||||
let callPattern = if tfIterator in typ.flags: PatIter else: PatProc
|
|
||||||
if typ.sons[0] != nil:
|
if typ.sons[0] != nil:
|
||||||
if isInvalidReturnType(p.config, typ.sons[0]):
|
if isInvalidReturnType(p.config, typ.sons[0]):
|
||||||
if sonsLen(ri) > 1: add(pl, ~", ")
|
if sonsLen(ri) > 1: add(pl, ~", ")
|
||||||
|
|
@ -246,7 +248,11 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
assert(d.t != nil) # generate an assignment to d:
|
assert(d.t != nil) # generate an assignment to d:
|
||||||
var list: TLoc
|
var list: TLoc
|
||||||
initLoc(list, locCall, d.lode, OnUnknown)
|
initLoc(list, locCall, d.lode, OnUnknown)
|
||||||
list.r = callPattern % [rdLoc(op), pl, pl.addComma, rawProc]
|
if tfIterator in typ.flags:
|
||||||
|
list.r = PatIter % [rdLoc(op), pl, pl.addComma, rawProc]
|
||||||
|
else:
|
||||||
|
list.r = PatProc % [rdLoc(op), pl, pl.addComma, rawProc]
|
||||||
|
|
||||||
genAssignment(p, d, list, {}) # no need for deep copying
|
genAssignment(p, d, list, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
genCallPattern()
|
genCallPattern()
|
||||||
|
|
|
||||||
|
|
@ -99,17 +99,17 @@ proc bitSetToWord(s: TBitSet, size: int): BiggestInt =
|
||||||
if j < len(s): result = result or (ze64(s[j]) shl (j * 8))
|
if j < len(s): result = result or (ze64(s[j]) shl (j * 8))
|
||||||
|
|
||||||
proc genRawSetData(cs: TBitSet, size: int): Rope =
|
proc genRawSetData(cs: TBitSet, size: int): Rope =
|
||||||
var frmt: FormatStr
|
|
||||||
if size > 8:
|
if size > 8:
|
||||||
result = "{$n" % []
|
result = "{$n" % []
|
||||||
for i in countup(0, size - 1):
|
for i in countup(0, size - 1):
|
||||||
if i < size - 1:
|
if i < size - 1:
|
||||||
# not last iteration?
|
# not last iteration?
|
||||||
if (i + 1) mod 8 == 0: frmt = "0x$1,$n"
|
if (i + 1) mod 8 == 0:
|
||||||
else: frmt = "0x$1, "
|
addf(result, "0x$1,$n", [rope(toHex(ze64(cs[i]), 2))])
|
||||||
|
else:
|
||||||
|
addf(result, "0x$1, ", [rope(toHex(ze64(cs[i]), 2))])
|
||||||
else:
|
else:
|
||||||
frmt = "0x$1}$n"
|
addf(result, "0x$1}$n", [rope(toHex(ze64(cs[i]), 2))])
|
||||||
addf(result, frmt, [rope(toHex(ze64(cs[i]), 2))])
|
|
||||||
else:
|
else:
|
||||||
result = intLiteral(bitSetToWord(cs, size))
|
result = intLiteral(bitSetToWord(cs, size))
|
||||||
# result := rope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
|
# result := rope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
|
||||||
|
|
@ -510,10 +510,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
"mulInt64", "divInt64", "modInt64",
|
"mulInt64", "divInt64", "modInt64",
|
||||||
"addInt64", "subInt64"
|
"addInt64", "subInt64"
|
||||||
]
|
]
|
||||||
opr: array[mAddI..mPred, string] = [
|
opr: array[mAddI..mPred, string] = ["+", "-", "*", "/", "%", "+", "-"]
|
||||||
"($#)($# + $#)", "($#)($# - $#)", "($#)($# * $#)",
|
|
||||||
"($#)($# / $#)", "($#)($# % $#)",
|
|
||||||
"($#)($# + $#)", "($#)($# - $#)"]
|
|
||||||
var a, b: TLoc
|
var a, b: TLoc
|
||||||
assert(e.sons[1].typ != nil)
|
assert(e.sons[1].typ != nil)
|
||||||
assert(e.sons[2].typ != nil)
|
assert(e.sons[2].typ != nil)
|
||||||
|
|
@ -523,7 +520,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
# later via 'chckRange'
|
# later via 'chckRange'
|
||||||
let t = e.typ.skipTypes(abstractRange)
|
let t = e.typ.skipTypes(abstractRange)
|
||||||
if optOverflowCheck notin p.options:
|
if optOverflowCheck notin p.options:
|
||||||
let res = opr[m] % [getTypeDesc(p.module, e.typ), rdLoc(a), rdLoc(b)]
|
let res = "($1)($2 $3 $4)" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
|
||||||
putIntoDest(p, d, e, res)
|
putIntoDest(p, d, e, res)
|
||||||
else:
|
else:
|
||||||
let res = binaryArithOverflowRaw(p, t, a, b,
|
let res = binaryArithOverflowRaw(p, t, a, b,
|
||||||
|
|
@ -531,11 +528,6 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res])
|
putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res])
|
||||||
|
|
||||||
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
const
|
|
||||||
opr: array[mUnaryMinusI..mAbsI, string] = [
|
|
||||||
mUnaryMinusI: "((NI$2)-($1))",
|
|
||||||
mUnaryMinusI64: "-($1)",
|
|
||||||
mAbsI: "($1 > 0? ($1) : -($1))"]
|
|
||||||
var
|
var
|
||||||
a: TLoc
|
a: TLoc
|
||||||
t: PType
|
t: PType
|
||||||
|
|
@ -545,54 +537,17 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
if optOverflowCheck in p.options:
|
if optOverflowCheck in p.options:
|
||||||
linefmt(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
|
linefmt(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
|
||||||
[rdLoc(a), intLiteral(firstOrd(p.config, t))])
|
[rdLoc(a), intLiteral(firstOrd(p.config, t))])
|
||||||
putIntoDest(p, d, e, opr[m] % [rdLoc(a), rope(getSize(p.config, t) * 8)])
|
case m
|
||||||
|
of mUnaryMinusI:
|
||||||
|
putIntoDest(p, d, e, "((NI$2)-($1))" % [rdLoc(a), rope(getSize(p.config, t) * 8)])
|
||||||
|
of mUnaryMinusI64:
|
||||||
|
putIntoDest(p, d, e, "-($1)" % [rdLoc(a)])
|
||||||
|
of mAbsI:
|
||||||
|
putIntoDest(p, d, e, "($1 > 0? ($1) : -($1))" % [rdLoc(a)])
|
||||||
|
else:
|
||||||
|
assert(false, $m)
|
||||||
|
|
||||||
proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
const
|
|
||||||
binArithTab: array[mAddF64..mXor, string] = [
|
|
||||||
"(($4)($1) + ($4)($2))", # AddF64
|
|
||||||
"(($4)($1) - ($4)($2))", # SubF64
|
|
||||||
"(($4)($1) * ($4)($2))", # MulF64
|
|
||||||
"(($4)($1) / ($4)($2))", # DivF64
|
|
||||||
"($4)((NU$5)($1) >> (NU$3)($2))", # ShrI
|
|
||||||
"($4)((NU$3)($1) << (NU$3)($2))", # ShlI
|
|
||||||
"($4)((NI$3)($1) >> (NU$3)($2))", # AshrI
|
|
||||||
"($4)($1 & $2)", # BitandI
|
|
||||||
"($4)($1 | $2)", # BitorI
|
|
||||||
"($4)($1 ^ $2)", # BitxorI
|
|
||||||
"(($1 <= $2) ? $1 : $2)", # MinI
|
|
||||||
"(($1 >= $2) ? $1 : $2)", # MaxI
|
|
||||||
"(($1 <= $2) ? $1 : $2)", # MinF64
|
|
||||||
"(($1 >= $2) ? $1 : $2)", # MaxF64
|
|
||||||
"($4)((NU$3)($1) + (NU$3)($2))", # AddU
|
|
||||||
"($4)((NU$3)($1) - (NU$3)($2))", # SubU
|
|
||||||
"($4)((NU$3)($1) * (NU$3)($2))", # MulU
|
|
||||||
"($4)((NU$3)($1) / (NU$3)($2))", # DivU
|
|
||||||
"($4)((NU$3)($1) % (NU$3)($2))", # ModU
|
|
||||||
"($1 == $2)", # EqI
|
|
||||||
"($1 <= $2)", # LeI
|
|
||||||
"($1 < $2)", # LtI
|
|
||||||
"($1 == $2)", # EqF64
|
|
||||||
"($1 <= $2)", # LeF64
|
|
||||||
"($1 < $2)", # LtF64
|
|
||||||
"((NU$3)($1) <= (NU$3)($2))", # LeU
|
|
||||||
"((NU$3)($1) < (NU$3)($2))", # LtU
|
|
||||||
"((NU64)($1) <= (NU64)($2))", # LeU64
|
|
||||||
"((NU64)($1) < (NU64)($2))", # LtU64
|
|
||||||
"($1 == $2)", # EqEnum
|
|
||||||
"($1 <= $2)", # LeEnum
|
|
||||||
"($1 < $2)", # LtEnum
|
|
||||||
"((NU8)($1) == (NU8)($2))", # EqCh
|
|
||||||
"((NU8)($1) <= (NU8)($2))", # LeCh
|
|
||||||
"((NU8)($1) < (NU8)($2))", # LtCh
|
|
||||||
"($1 == $2)", # EqB
|
|
||||||
"($1 <= $2)", # LeB
|
|
||||||
"($1 < $2)", # LtB
|
|
||||||
"($1 == $2)", # EqRef
|
|
||||||
"($1 == $2)", # EqPtr
|
|
||||||
"($1 <= $2)", # LePtr
|
|
||||||
"($1 < $2)", # LtPtr
|
|
||||||
"($1 != $2)"] # Xor
|
|
||||||
var
|
var
|
||||||
a, b: TLoc
|
a, b: TLoc
|
||||||
s, k: BiggestInt
|
s, k: BiggestInt
|
||||||
|
|
@ -603,9 +558,59 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
# BUGFIX: cannot use result-type here, as it may be a boolean
|
# BUGFIX: cannot use result-type here, as it may be a boolean
|
||||||
s = max(getSize(p.config, a.t), getSize(p.config, b.t)) * 8
|
s = max(getSize(p.config, a.t), getSize(p.config, b.t)) * 8
|
||||||
k = getSize(p.config, a.t) * 8
|
k = getSize(p.config, a.t) * 8
|
||||||
putIntoDest(p, d, e,
|
|
||||||
binArithTab[op] % [rdLoc(a), rdLoc(b), rope(s),
|
template applyFormat(frmt: untyped) =
|
||||||
getSimpleTypeDesc(p.module, e.typ), rope(k)])
|
putIntoDest(p, d, e, frmt % [
|
||||||
|
rdLoc(a), rdLoc(b), rope(s),
|
||||||
|
getSimpleTypeDesc(p.module, e.typ), rope(k)]
|
||||||
|
)
|
||||||
|
|
||||||
|
case op
|
||||||
|
of mAddF64: applyFormat("(($4)($1) + ($4)($2))")
|
||||||
|
of mSubF64: applyFormat("(($4)($1) - ($4)($2))")
|
||||||
|
of mMulF64: applyFormat("(($4)($1) * ($4)($2))")
|
||||||
|
of mDivF64: applyFormat("(($4)($1) / ($4)($2))")
|
||||||
|
of mShrI: applyFormat("($4)((NU$5)($1) >> (NU$3)($2))")
|
||||||
|
of mShlI: applyFormat("($4)((NU$3)($1) << (NU$3)($2))")
|
||||||
|
of mAshrI: applyFormat("($4)((NI$3)($1) >> (NU$3)($2))")
|
||||||
|
of mBitandI: applyFormat("($4)($1 & $2)")
|
||||||
|
of mBitorI: applyFormat("($4)($1 | $2)")
|
||||||
|
of mBitxorI: applyFormat("($4)($1 ^ $2)")
|
||||||
|
of mMinI: applyFormat("(($1 <= $2) ? $1 : $2)")
|
||||||
|
of mMaxI: applyFormat("(($1 >= $2) ? $1 : $2)")
|
||||||
|
of mMinF64: applyFormat("(($1 <= $2) ? $1 : $2)")
|
||||||
|
of mMaxF64: applyFormat("(($1 >= $2) ? $1 : $2)")
|
||||||
|
of mAddU: applyFormat("($4)((NU$3)($1) + (NU$3)($2))")
|
||||||
|
of mSubU: applyFormat("($4)((NU$3)($1) - (NU$3)($2))")
|
||||||
|
of mMulU: applyFormat("($4)((NU$3)($1) * (NU$3)($2))")
|
||||||
|
of mDivU: applyFormat("($4)((NU$3)($1) / (NU$3)($2))")
|
||||||
|
of mModU: applyFormat("($4)((NU$3)($1) % (NU$3)($2))")
|
||||||
|
of mEqI: applyFormat("($1 == $2)")
|
||||||
|
of mLeI: applyFormat("($1 <= $2)")
|
||||||
|
of mLtI: applyFormat("($1 < $2)")
|
||||||
|
of mEqF64: applyFormat("($1 == $2)")
|
||||||
|
of mLeF64: applyFormat("($1 <= $2)")
|
||||||
|
of mLtF64: applyFormat("($1 < $2)")
|
||||||
|
of mLeU: applyFormat("((NU$3)($1) <= (NU$3)($2))")
|
||||||
|
of mLtU: applyFormat("((NU$3)($1) < (NU$3)($2))")
|
||||||
|
of mLeU64: applyFormat("((NU64)($1) <= (NU64)($2))")
|
||||||
|
of mLtU64: applyFormat("((NU64)($1) < (NU64)($2))")
|
||||||
|
of mEqEnum: applyFormat("($1 == $2)")
|
||||||
|
of mLeEnum: applyFormat("($1 <= $2)")
|
||||||
|
of mLtEnum: applyFormat("($1 < $2)")
|
||||||
|
of mEqCh: applyFormat("((NU8)($1) == (NU8)($2))")
|
||||||
|
of mLeCh: applyFormat("((NU8)($1) <= (NU8)($2))")
|
||||||
|
of mLtCh: applyFormat("((NU8)($1) < (NU8)($2))")
|
||||||
|
of mEqB: applyFormat("($1 == $2)")
|
||||||
|
of mLeB: applyFormat("($1 <= $2)")
|
||||||
|
of mLtB: applyFormat("($1 < $2)")
|
||||||
|
of mEqRef: applyFormat("($1 == $2)")
|
||||||
|
of mEqUntracedRef: applyFormat("($1 == $2)")
|
||||||
|
of mLePtr: applyFormat("($1 <= $2)")
|
||||||
|
of mLtPtr: applyFormat("($1 < $2)")
|
||||||
|
of mXor: applyFormat("($1 != $2)")
|
||||||
|
else:
|
||||||
|
assert(false, $op)
|
||||||
|
|
||||||
proc genEqProc(p: BProc, e: PNode, d: var TLoc) =
|
proc genEqProc(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var a, b: TLoc
|
var a, b: TLoc
|
||||||
|
|
@ -628,7 +633,8 @@ proc genIsNil(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
|
||||||
proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
const
|
const
|
||||||
unArithTab: array[mNot..mToBiggestInt, string] = ["!($1)", # Not
|
unArithTab: array[mNot..mToBiggestInt, string] = [
|
||||||
|
"!($1)", # Not
|
||||||
"$1", # UnaryPlusI
|
"$1", # UnaryPlusI
|
||||||
"($3)((NU$2) ~($1))", # BitnotI
|
"($3)((NU$2) ~($1))", # BitnotI
|
||||||
"$1", # UnaryPlusF64
|
"$1", # UnaryPlusF64
|
||||||
|
|
@ -654,10 +660,58 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
assert(e.sons[1].typ != nil)
|
assert(e.sons[1].typ != nil)
|
||||||
initLocExpr(p, e.sons[1], a)
|
initLocExpr(p, e.sons[1], a)
|
||||||
t = skipTypes(e.typ, abstractRange)
|
t = skipTypes(e.typ, abstractRange)
|
||||||
putIntoDest(p, d, e,
|
|
||||||
unArithTab[op] % [rdLoc(a), rope(getSize(p.config, t) * 8),
|
|
||||||
|
template applyFormat(frmt: untyped) =
|
||||||
|
putIntoDest(p, d, e, frmt % [rdLoc(a), rope(getSize(p.config, t) * 8),
|
||||||
getSimpleTypeDesc(p.module, e.typ)])
|
getSimpleTypeDesc(p.module, e.typ)])
|
||||||
|
|
||||||
|
|
||||||
|
case op
|
||||||
|
of mNot:
|
||||||
|
applyFormat("!($1)")
|
||||||
|
of mUnaryPlusI:
|
||||||
|
applyFormat("$1")
|
||||||
|
of mBitnotI:
|
||||||
|
applyFormat("($3)((NU$2) ~($1))")
|
||||||
|
of mUnaryPlusF64:
|
||||||
|
applyFormat("$1")
|
||||||
|
of mUnaryMinusF64:
|
||||||
|
applyFormat("-($1)")
|
||||||
|
of mAbsF64:
|
||||||
|
applyFormat("($1 < 0? -($1) : ($1))")
|
||||||
|
# BUGFIX: fabs() makes problems for Tiny C
|
||||||
|
of mZe8ToI:
|
||||||
|
applyFormat("(($3)(NU)(NU8)($1))")
|
||||||
|
of mZe8ToI64:
|
||||||
|
applyFormat("(($3)(NU64)(NU8)($1))")
|
||||||
|
of mZe16ToI:
|
||||||
|
applyFormat("(($3)(NU)(NU16)($1))")
|
||||||
|
of mZe16ToI64:
|
||||||
|
applyFormat("(($3)(NU64)(NU16)($1))")
|
||||||
|
of mZe32ToI64:
|
||||||
|
applyFormat("(($3)(NU64)(NU32)($1))")
|
||||||
|
of mZeIToI64:
|
||||||
|
applyFormat("(($3)(NU64)(NU)($1))")
|
||||||
|
of mToU8:
|
||||||
|
applyFormat("(($3)(NU8)(NU)($1))")
|
||||||
|
of mToU16:
|
||||||
|
applyFormat("(($3)(NU16)(NU)($1))")
|
||||||
|
of mToU32:
|
||||||
|
applyFormat("(($3)(NU32)(NU64)($1))")
|
||||||
|
of mToFloat:
|
||||||
|
applyFormat("((double) ($1))")
|
||||||
|
of mToBiggestFloat:
|
||||||
|
applyFormat("((double) ($1))")
|
||||||
|
of mToInt:
|
||||||
|
applyFormat("float64ToInt32($1)")
|
||||||
|
of mToBiggestInt:
|
||||||
|
applyFormat("float64ToInt64($1)")
|
||||||
|
else:
|
||||||
|
assert false, $op
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc isCppRef(p: BProc; typ: PType): bool {.inline.} =
|
proc isCppRef(p: BProc; typ: PType): bool {.inline.} =
|
||||||
result = p.module.compileToCpp and
|
result = p.module.compileToCpp and
|
||||||
skipTypes(typ, abstractInstOwned).kind == tyVar and
|
skipTypes(typ, abstractInstOwned).kind == tyVar and
|
||||||
|
|
@ -1675,7 +1729,7 @@ proc fewCmps(conf: ConfigRef; s: PNode): bool =
|
||||||
else:
|
else:
|
||||||
result = sonsLen(s) <= 8 # 8 seems to be a good value
|
result = sonsLen(s) <= 8 # 8 seems to be a good value
|
||||||
|
|
||||||
proc binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) =
|
template binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) =
|
||||||
putIntoDest(p, d, e, frmt % [rdLoc(a), rdSetElemLoc(p.config, b, a.t)])
|
putIntoDest(p, d, e, frmt % [rdLoc(a), rdSetElemLoc(p.config, b, a.t)])
|
||||||
|
|
||||||
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) =
|
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) =
|
||||||
|
|
@ -1686,7 +1740,7 @@ proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) =
|
||||||
of 8: binaryExprIn(p, e, a, b, d, "(($1 &((NU64)1<<((NU)($2)&63U)))!=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)")
|
else: binaryExprIn(p, e, a, b, d, "(($1[(NU)($2)>>3] &(1U<<((NU)($2)&7U)))!=0)")
|
||||||
|
|
||||||
proc binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
template binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) =
|
||||||
var a, b: TLoc
|
var a, b: TLoc
|
||||||
assert(d.k == locNone)
|
assert(d.k == locNone)
|
||||||
initLocExpr(p, e.sons[1], a)
|
initLocExpr(p, e.sons[1], a)
|
||||||
|
|
@ -1753,13 +1807,19 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
of 1, 2, 4, 8:
|
of 1, 2, 4, 8:
|
||||||
case op
|
case op
|
||||||
of mIncl:
|
of mIncl:
|
||||||
var ts = "NU" & $(size * 8)
|
case size
|
||||||
binaryStmtInExcl(p, e, d,
|
of 1: binaryStmtInExcl(p, e, d, "$1 |= ((NU8)1)<<(($2) & 7);$n")
|
||||||
"$1 |= ((" & ts & ")1)<<(($2)%(sizeof(" & ts & ")*8));$n")
|
of 2: binaryStmtInExcl(p, e, d, "$1 |= ((NU16)1)<<(($2) & 15);$n")
|
||||||
|
of 4: binaryStmtInExcl(p, e, d, "$1 |= ((NU32)1)<<(($2) & 31);$n")
|
||||||
|
of 8: binaryStmtInExcl(p, e, d, "$1 |= ((NU64)1)<<(($2) & 63);$n")
|
||||||
|
else: assert(false, $size)
|
||||||
of mExcl:
|
of mExcl:
|
||||||
var ts = "NU" & $(size * 8)
|
case size
|
||||||
binaryStmtInExcl(p, e, d, "$1 &= ~(((" & ts & ")1) << (($2) % (sizeof(" &
|
of 1: binaryStmtInExcl(p, e, d, "$1 &= ~(((NU8)1) << (($2) & 7));$n")
|
||||||
ts & ")*8)));$n")
|
of 2: binaryStmtInExcl(p, e, d, "$1 &= ~(((NU16)1) << (($2) & 15));$n")
|
||||||
|
of 4: binaryStmtInExcl(p, e, d, "$1 &= ~(((NU32)1) << (($2) & 31));$n")
|
||||||
|
of 8: binaryStmtInExcl(p, e, d, "$1 &= ~(((NU64)1) << (($2) & 63));$n")
|
||||||
|
else: assert(false, $size)
|
||||||
of mCard:
|
of mCard:
|
||||||
if size <= 4: unaryExprChar(p, e, d, "#countBits32($1)")
|
if size <= 4: unaryExprChar(p, e, d, "#countBits32($1)")
|
||||||
else: unaryExprChar(p, e, d, "#countBits64($1)")
|
else: unaryExprChar(p, e, d, "#countBits64($1)")
|
||||||
|
|
@ -2228,14 +2288,14 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, it.sons[0], a)
|
initLocExpr(p, it.sons[0], a)
|
||||||
initLocExpr(p, it.sons[1], b)
|
initLocExpr(p, it.sons[1], b)
|
||||||
lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" &
|
lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" &
|
||||||
"$2 |=((" & ts & ")(1)<<(($1)%(sizeof(" & ts & ")*8)));$n", [
|
"$2 |=(($5)(1)<<(($1)%(sizeof($5)*8)));$n", [
|
||||||
rdLoc(idx), rdLoc(d), rdSetElemLoc(p.config, a, e.typ),
|
rdLoc(idx), rdLoc(d), rdSetElemLoc(p.config, a, e.typ),
|
||||||
rdSetElemLoc(p.config, b, e.typ)])
|
rdSetElemLoc(p.config, b, e.typ), rope(ts)])
|
||||||
else:
|
else:
|
||||||
initLocExpr(p, it, a)
|
initLocExpr(p, it, a)
|
||||||
lineF(p, cpsStmts,
|
lineF(p, cpsStmts,
|
||||||
"$1 |=((" & ts & ")(1)<<(($2)%(sizeof(" & ts & ")*8)));$n",
|
"$1 |=(($3)(1)<<(($2)%(sizeof($3)*8)));$n",
|
||||||
[rdLoc(d), rdSetElemLoc(p.config, a, e.typ)])
|
[rdLoc(d), rdSetElemLoc(p.config, a, e.typ), rope(ts)])
|
||||||
|
|
||||||
proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
var rec: TLoc
|
var rec: TLoc
|
||||||
|
|
|
||||||
|
|
@ -1135,9 +1135,9 @@ proc genAsmStmt(p: BProc, t: PNode) =
|
||||||
# work:
|
# work:
|
||||||
if p.prc == nil:
|
if p.prc == nil:
|
||||||
# top level asm statement?
|
# top level asm statement?
|
||||||
addf(p.module.s[cfsProcHeaders], CC[p.config.cCompiler].asmStmtFrmt, [s])
|
add(p.module.s[cfsProcHeaders], runtimeFormat(CC[p.config.cCompiler].asmStmtFrmt, [s]))
|
||||||
else:
|
else:
|
||||||
lineF(p, cpsStmts, CC[p.config.cCompiler].asmStmtFrmt, [s])
|
add(p.s(cpsStmts), indentLine(p, runtimeFormat(CC[p.config.cCompiler].asmStmtFrmt, [s])))
|
||||||
|
|
||||||
proc determineSection(n: PNode): TCFileSection =
|
proc determineSection(n: PNode): TCFileSection =
|
||||||
result = cfsProcHeaders
|
result = cfsProcHeaders
|
||||||
|
|
|
||||||
|
|
@ -338,12 +338,17 @@ proc getTypePre(m: BModule, typ: PType; sig: SigHash): Rope =
|
||||||
if result == nil: result = cacheGetType(m.typeCache, sig)
|
if result == nil: result = cacheGetType(m.typeCache, sig)
|
||||||
|
|
||||||
proc structOrUnion(t: PType): Rope =
|
proc structOrUnion(t: PType): Rope =
|
||||||
|
let cachedUnion {.global.} = rope("union")
|
||||||
|
let cachedStruct {.global.} = rope("struct")
|
||||||
let t = t.skipTypes({tyAlias, tySink})
|
let t = t.skipTypes({tyAlias, tySink})
|
||||||
(if tfUnion in t.flags: rope("union") else: rope("struct"))
|
if tfUnion in t.flags: cachedUnion
|
||||||
|
else: cachedStruct
|
||||||
|
|
||||||
proc getForwardStructFormat(m: BModule): string =
|
proc addForwardStructFormat(m: BModule, structOrUnion: Rope, typename: Rope) =
|
||||||
if m.compileToCpp: result = "$1 $2;$n"
|
if m.compileToCpp:
|
||||||
else: result = "typedef $1 $2 $2;$n"
|
m.s[cfsForwardTypes].addf "$1 $2;$n", [structOrUnion, typename]
|
||||||
|
else:
|
||||||
|
m.s[cfsForwardTypes].addf "typedef $1 $2 $2;$n", [structOrUnion, typename]
|
||||||
|
|
||||||
proc seqStar(m: BModule): string =
|
proc seqStar(m: BModule): string =
|
||||||
if m.config.selectedGC == gcDestructors: result = ""
|
if m.config.selectedGC == gcDestructors: result = ""
|
||||||
|
|
@ -360,8 +365,7 @@ proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope =
|
||||||
result = getTypeName(m, typ, sig)
|
result = getTypeName(m, typ, sig)
|
||||||
m.forwTypeCache[sig] = result
|
m.forwTypeCache[sig] = result
|
||||||
if not isImportedType(concrete):
|
if not isImportedType(concrete):
|
||||||
addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
|
addForwardStructFormat(m, structOrUnion(typ), result)
|
||||||
[structOrUnion(typ), result])
|
|
||||||
else:
|
else:
|
||||||
pushType(m, concrete)
|
pushType(m, concrete)
|
||||||
doAssert m.forwTypeCache[sig] == result
|
doAssert m.forwTypeCache[sig] == result
|
||||||
|
|
@ -733,8 +737,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = getTypeName(m, origTyp, sig)
|
result = getTypeName(m, origTyp, sig)
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
|
addForwardStructFormat(m, structOrUnion(t), result)
|
||||||
[structOrUnion(t), result])
|
|
||||||
m.forwTypeCache[sig] = result
|
m.forwTypeCache[sig] = result
|
||||||
assert(cacheGetType(m.typeCache, sig) == nil)
|
assert(cacheGetType(m.typeCache, sig) == nil)
|
||||||
m.typeCache[sig] = result & seqStar(m)
|
m.typeCache[sig] = result & seqStar(m)
|
||||||
|
|
@ -845,8 +848,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
|
||||||
result = getTypeName(m, origTyp, sig)
|
result = getTypeName(m, origTyp, sig)
|
||||||
m.forwTypeCache[sig] = result
|
m.forwTypeCache[sig] = result
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
|
addForwardStructFormat(m, structOrUnion(t), result)
|
||||||
[structOrUnion(t), result])
|
|
||||||
assert m.forwTypeCache[sig] == result
|
assert m.forwTypeCache[sig] == result
|
||||||
m.typeCache[sig] = result # always call for sideeffects:
|
m.typeCache[sig] = result # always call for sideeffects:
|
||||||
if not incompleteType(t):
|
if not incompleteType(t):
|
||||||
|
|
@ -905,7 +907,8 @@ proc finishTypeDescriptions(m: BModule) =
|
||||||
discard getTypeDesc(m, m.typeStack[i])
|
discard getTypeDesc(m, m.typeStack[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
template cgDeclFrmt*(s: PSym): string = s.constraint.strVal
|
template cgDeclFrmt*(s: PSym): string =
|
||||||
|
s.constraint.strVal
|
||||||
|
|
||||||
proc isReloadable(m: BModule, prc: PSym): bool =
|
proc isReloadable(m: BModule, prc: PSym): bool =
|
||||||
return m.hcrOn and sfNonReloadable notin prc.flags
|
return m.hcrOn and sfNonReloadable notin prc.flags
|
||||||
|
|
@ -943,7 +946,7 @@ proc genProcHeader(m: BModule, prc: PSym, asPtr: bool = false): Rope =
|
||||||
params])
|
params])
|
||||||
else:
|
else:
|
||||||
let asPtrStr = if asPtr: (rope("(*") & name & ")") else: name
|
let asPtrStr = if asPtr: (rope("(*") & name & ")") else: name
|
||||||
result = prc.cgDeclFrmt % [rettype, asPtrStr, params]
|
result = runtimeFormat(prc.cgDeclFrmt, [rettype, asPtrStr, params])
|
||||||
|
|
||||||
# ------------------ type info generation -------------------------------------
|
# ------------------ type info generation -------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,15 +206,15 @@ proc indentLine(p: BProc, r: Rope): Rope =
|
||||||
prepend(result, "\t".rope)
|
prepend(result, "\t".rope)
|
||||||
|
|
||||||
template appcg(m: BModule, c: var Rope, frmt: FormatStr,
|
template appcg(m: BModule, c: var Rope, frmt: FormatStr,
|
||||||
args: varargs[untyped]) =
|
args: untyped) =
|
||||||
add(c, ropecg(m, frmt, args))
|
add(c, ropecg(m, frmt, args))
|
||||||
|
|
||||||
template appcg(m: BModule, sec: TCFileSection, frmt: FormatStr,
|
template appcg(m: BModule, sec: TCFileSection, frmt: FormatStr,
|
||||||
args: varargs[untyped]) =
|
args: untyped) =
|
||||||
add(m.s[sec], ropecg(m, frmt, args))
|
add(m.s[sec], ropecg(m, frmt, args))
|
||||||
|
|
||||||
template appcg(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
template appcg(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
||||||
args: varargs[untyped]) =
|
args: untyped) =
|
||||||
add(p.s(sec), ropecg(p.module, frmt, args))
|
add(p.s(sec), ropecg(p.module, frmt, args))
|
||||||
|
|
||||||
template line(p: BProc, sec: TCProcSection, r: Rope) =
|
template line(p: BProc, sec: TCProcSection, r: Rope) =
|
||||||
|
|
@ -224,7 +224,7 @@ template line(p: BProc, sec: TCProcSection, r: string) =
|
||||||
add(p.s(sec), indentLine(p, r.rope))
|
add(p.s(sec), indentLine(p, r.rope))
|
||||||
|
|
||||||
template lineF(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
template lineF(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
||||||
args: openarray[Rope]) =
|
args: untyped) =
|
||||||
add(p.s(sec), indentLine(p, frmt % args))
|
add(p.s(sec), indentLine(p, frmt % args))
|
||||||
|
|
||||||
template lineCg(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
template lineCg(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
||||||
|
|
@ -484,7 +484,7 @@ proc localVarDecl(p: BProc; n: PNode): Rope =
|
||||||
add(result, " ")
|
add(result, " ")
|
||||||
add(result, s.loc.r)
|
add(result, s.loc.r)
|
||||||
else:
|
else:
|
||||||
result = s.cgDeclFrmt % [result, s.loc.r]
|
result = runtimeFormat(s.cgDeclFrmt, [result, s.loc.r])
|
||||||
|
|
||||||
proc assignLocalVar(p: BProc, n: PNode) =
|
proc assignLocalVar(p: BProc, n: PNode) =
|
||||||
#assert(s.loc.k == locNone) # not yet assigned
|
#assert(s.loc.k == locNone) # not yet assigned
|
||||||
|
|
@ -535,7 +535,7 @@ proc assignGlobalVar(p: BProc, n: PNode) =
|
||||||
if sfVolatile in s.flags: add(decl, " volatile")
|
if sfVolatile in s.flags: add(decl, " volatile")
|
||||||
addf(decl, " $1;$n", [s.loc.r])
|
addf(decl, " $1;$n", [s.loc.r])
|
||||||
else:
|
else:
|
||||||
decl = (s.cgDeclFrmt & ";$n") % [td, s.loc.r]
|
decl = runtimeFormat(s.cgDeclFrmt & ";$n", [td, s.loc.r])
|
||||||
add(p.module.s[cfsVars], decl)
|
add(p.module.s[cfsVars], decl)
|
||||||
if p.withinLoop > 0:
|
if p.withinLoop > 0:
|
||||||
# fixes tests/run/tzeroarray:
|
# fixes tests/run/tzeroarray:
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
|
||||||
outExt, RelativeDir"htmldocs", false)
|
outExt, RelativeDir"htmldocs", false)
|
||||||
result.thisDir = result.destFile.splitFile.dir
|
result.thisDir = result.destFile.splitFile.dir
|
||||||
|
|
||||||
proc dispA(conf: ConfigRef; dest: var Rope, xml, tex: string, args: openArray[Rope]) =
|
template dispA(conf: ConfigRef; dest: var Rope, xml, tex: string, args: openArray[Rope]) =
|
||||||
if conf.cmd != cmdRst2tex: addf(dest, xml, args)
|
if conf.cmd != cmdRst2tex: addf(dest, xml, args)
|
||||||
else: addf(dest, tex, args)
|
else: addf(dest, tex, args)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -365,92 +365,92 @@ proc genOr(p: PProc, a, b: PNode, r: var TCompRes) =
|
||||||
line(p, "}")
|
line(p, "}")
|
||||||
|
|
||||||
type
|
type
|
||||||
TMagicFrmt = array[0..3, string]
|
TMagicFrmt = array[0..1, string]
|
||||||
TMagicOps = array[mAddI..mStrToStr, TMagicFrmt]
|
TMagicOps = array[mAddI..mStrToStr, TMagicFrmt]
|
||||||
|
|
||||||
const # magic checked op; magic unchecked op; checked op; unchecked op
|
const # magic checked op; magic unchecked op;
|
||||||
jsOps: TMagicOps = [
|
jsMagics: TMagicOps = [
|
||||||
["addInt", "", "addInt($1, $2)", "($1 + $2)"], # AddI
|
["addInt", ""], # AddI
|
||||||
["subInt", "", "subInt($1, $2)", "($1 - $2)"], # SubI
|
["subInt", ""], # SubI
|
||||||
["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI
|
["mulInt", ""], # MulI
|
||||||
["divInt", "", "divInt($1, $2)", "Math.trunc($1 / $2)"], # DivI
|
["divInt", ""], # DivI
|
||||||
["modInt", "", "modInt($1, $2)", "Math.trunc($1 % $2)"], # ModI
|
["modInt", ""], # ModI
|
||||||
["addInt", "", "addInt($1, $2)", "($1 + $2)"], # Succ
|
["addInt", ""], # Succ
|
||||||
["subInt", "", "subInt($1, $2)", "($1 - $2)"], # Pred
|
["subInt", ""], # Pred
|
||||||
["", "", "($1 + $2)", "($1 + $2)"], # AddF64
|
["", ""], # AddF64
|
||||||
["", "", "($1 - $2)", "($1 - $2)"], # SubF64
|
["", ""], # SubF64
|
||||||
["", "", "($1 * $2)", "($1 * $2)"], # MulF64
|
["", ""], # MulF64
|
||||||
["", "", "($1 / $2)", "($1 / $2)"], # DivF64
|
["", ""], # DivF64
|
||||||
["", "", "", ""], # ShrI
|
["", ""], # ShrI
|
||||||
["", "", "($1 << $2)", "($1 << $2)"], # ShlI
|
["", ""], # ShlI
|
||||||
["", "", "($1 >> $2)", "($1 >> $2)"], # AshrI
|
["", ""], # AshrI
|
||||||
["", "", "($1 & $2)", "($1 & $2)"], # BitandI
|
["", ""], # BitandI
|
||||||
["", "", "($1 | $2)", "($1 | $2)"], # BitorI
|
["", ""], # BitorI
|
||||||
["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI
|
["", ""], # BitxorI
|
||||||
["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinI
|
["nimMin", "nimMin"], # MinI
|
||||||
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI
|
["nimMax", "nimMax"], # MaxI
|
||||||
["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64
|
["nimMin", "nimMin"], # MinF64
|
||||||
["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64
|
["nimMax", "nimMax"], # MaxF64
|
||||||
["", "", "", ""], # addU
|
["", ""], # addU
|
||||||
["", "", "", ""], # subU
|
["", ""], # subU
|
||||||
["", "", "", ""], # mulU
|
["", ""], # mulU
|
||||||
["", "", "", ""], # divU
|
["", ""], # divU
|
||||||
["", "", "($1 % $2)", "($1 % $2)"], # modU
|
["", ""], # modU
|
||||||
["", "", "($1 == $2)", "($1 == $2)"], # EqI
|
["", ""], # EqI
|
||||||
["", "", "($1 <= $2)", "($1 <= $2)"], # LeI
|
["", ""], # LeI
|
||||||
["", "", "($1 < $2)", "($1 < $2)"], # LtI
|
["", ""], # LtI
|
||||||
["", "", "($1 == $2)", "($1 == $2)"], # EqF64
|
["", ""], # EqF64
|
||||||
["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64
|
["", ""], # LeF64
|
||||||
["", "", "($1 < $2)", "($1 < $2)"], # LtF64
|
["", ""], # LtF64
|
||||||
["", "", "($1 <= $2)", "($1 <= $2)"], # leU
|
["", ""], # leU
|
||||||
["", "", "($1 < $2)", "($1 < $2)"], # ltU
|
["", ""], # ltU
|
||||||
["", "", "($1 <= $2)", "($1 <= $2)"], # leU64
|
["", ""], # leU64
|
||||||
["", "", "($1 < $2)", "($1 < $2)"], # ltU64
|
["", ""], # ltU64
|
||||||
["", "", "($1 == $2)", "($1 == $2)"], # EqEnum
|
["", ""], # EqEnum
|
||||||
["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum
|
["", ""], # LeEnum
|
||||||
["", "", "($1 < $2)", "($1 < $2)"], # LtEnum
|
["", ""], # LtEnum
|
||||||
["", "", "($1 == $2)", "($1 == $2)"], # EqCh
|
["", ""], # EqCh
|
||||||
["", "", "($1 <= $2)", "($1 <= $2)"], # LeCh
|
["", ""], # LeCh
|
||||||
["", "", "($1 < $2)", "($1 < $2)"], # LtCh
|
["", ""], # LtCh
|
||||||
["", "", "($1 == $2)", "($1 == $2)"], # EqB
|
["", ""], # EqB
|
||||||
["", "", "($1 <= $2)", "($1 <= $2)"], # LeB
|
["", ""], # LeB
|
||||||
["", "", "($1 < $2)", "($1 < $2)"], # LtB
|
["", ""], # LtB
|
||||||
["", "", "($1 == $2)", "($1 == $2)"], # EqRef
|
["", ""], # EqRef
|
||||||
["", "", "($1 == $2)", "($1 == $2)"], # EqUntracedRef
|
["", ""], # EqUntracedRef
|
||||||
["", "", "($1 <= $2)", "($1 <= $2)"], # LePtr
|
["", ""], # LePtr
|
||||||
["", "", "($1 < $2)", "($1 < $2)"], # LtPtr
|
["", ""], # LtPtr
|
||||||
["", "", "($1 != $2)", "($1 != $2)"], # Xor
|
["", ""], # Xor
|
||||||
["", "", "($1 == $2)", "($1 == $2)"], # EqCString
|
["", ""], # EqCString
|
||||||
["", "", "($1 == $2)", "($1 == $2)"], # EqProc
|
["", ""], # EqProc
|
||||||
["negInt", "", "negInt($1)", "-($1)"], # UnaryMinusI
|
["negInt", ""], # UnaryMinusI
|
||||||
["negInt64", "", "negInt64($1)", "-($1)"], # UnaryMinusI64
|
["negInt64", ""], # UnaryMinusI64
|
||||||
["absInt", "", "absInt($1)", "Math.abs($1)"], # AbsI
|
["absInt", ""], # AbsI
|
||||||
["", "", "!($1)", "!($1)"], # Not
|
["", ""], # Not
|
||||||
["", "", "+($1)", "+($1)"], # UnaryPlusI
|
["", ""], # UnaryPlusI
|
||||||
["", "", "~($1)", "~($1)"], # BitnotI
|
["", ""], # BitnotI
|
||||||
["", "", "+($1)", "+($1)"], # UnaryPlusF64
|
["", ""], # UnaryPlusF64
|
||||||
["", "", "-($1)", "-($1)"], # UnaryMinusF64
|
["", ""], # UnaryMinusF64
|
||||||
["", "", "Math.abs($1)", "Math.abs($1)"], # AbsF64
|
["", ""], # AbsF64
|
||||||
["Ze8ToI", "Ze8ToI", "Ze8ToI($1)", "Ze8ToI($1)"], # mZe8ToI
|
["Ze8ToI", "Ze8ToI"], # mZe8ToI
|
||||||
["Ze8ToI64", "Ze8ToI64", "Ze8ToI64($1)", "Ze8ToI64($1)"], # mZe8ToI64
|
["Ze8ToI64", "Ze8ToI64"], # mZe8ToI64
|
||||||
["Ze16ToI", "Ze16ToI", "Ze16ToI($1)", "Ze16ToI($1)"], # mZe16ToI
|
["Ze16ToI", "Ze16ToI"], # mZe16ToI
|
||||||
["Ze16ToI64", "Ze16ToI64", "Ze16ToI64($1)", "Ze16ToI64($1)"], # mZe16ToI64
|
["Ze16ToI64", "Ze16ToI64"], # mZe16ToI64
|
||||||
["Ze32ToI64", "Ze32ToI64", "Ze32ToI64($1)", "Ze32ToI64($1)"], # mZe32ToI64
|
["Ze32ToI64", "Ze32ToI64"], # mZe32ToI64
|
||||||
["ZeIToI64", "ZeIToI64", "ZeIToI64($1)", "ZeIToI64($1)"], # mZeIToI64
|
["ZeIToI64", "ZeIToI64"], # mZeIToI64
|
||||||
["toU8", "toU8", "toU8($1)", "toU8($1)"], # toU8
|
["toU8", "toU8"], # toU8
|
||||||
["toU16", "toU16", "toU16($1)", "toU16($1)"], # toU16
|
["toU16", "toU16"], # toU16
|
||||||
["toU32", "toU32", "toU32($1)", "toU32($1)"], # toU32
|
["toU32", "toU32"], # toU32
|
||||||
["", "", "$1", "$1"], # ToFloat
|
["", ""], # ToFloat
|
||||||
["", "", "$1", "$1"], # ToBiggestFloat
|
["", ""], # ToBiggestFloat
|
||||||
["", "", "Math.trunc($1)", "Math.trunc($1)"], # ToInt
|
["", ""], # ToInt
|
||||||
["", "", "Math.trunc($1)", "Math.trunc($1)"], # ToBiggestInt
|
["", ""], # ToBiggestInt
|
||||||
["nimCharToStr", "nimCharToStr", "nimCharToStr($1)", "nimCharToStr($1)"],
|
["nimCharToStr", "nimCharToStr"],
|
||||||
["nimBoolToStr", "nimBoolToStr", "nimBoolToStr($1)", "nimBoolToStr($1)"],
|
["nimBoolToStr", "nimBoolToStr"],
|
||||||
["cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"],
|
["cstrToNimstr", "cstrToNimstr"],
|
||||||
["cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"],
|
["cstrToNimstr", "cstrToNimstr"],
|
||||||
["cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"],
|
["cstrToNimstr", "cstrToNimstr"],
|
||||||
["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"],
|
["cstrToNimstr", "cstrToNimstr"],
|
||||||
["", "", "$1", "$1"]]
|
["", ""]]
|
||||||
|
|
||||||
proc needsTemp(p: PProc; n: PNode): bool =
|
proc needsTemp(p: PProc; n: PNode): bool =
|
||||||
# check if n contains a call to determine
|
# check if n contains a call to determine
|
||||||
|
|
@ -478,7 +478,7 @@ proc maybeMakeTemp(p: PProc, n: PNode; x: TCompRes): tuple[a, tmp: Rope] =
|
||||||
else:
|
else:
|
||||||
(a: a, tmp: b)
|
(a: a, tmp: b)
|
||||||
|
|
||||||
proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
template binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
||||||
# $1 and $2 in the `frmt` string bind to lhs and rhs of the expr,
|
# $1 and $2 in the `frmt` string bind to lhs and rhs of the expr,
|
||||||
# if $3 or $4 are present they will be substituted with temps for
|
# if $3 or $4 are present they will be substituted with temps for
|
||||||
# lhs and rhs respectively
|
# lhs and rhs respectively
|
||||||
|
|
@ -490,8 +490,8 @@ proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
||||||
var
|
var
|
||||||
a, tmp = x.rdLoc
|
a, tmp = x.rdLoc
|
||||||
b, tmp2 = y.rdLoc
|
b, tmp2 = y.rdLoc
|
||||||
if "$3" in frmt: (a, tmp) = maybeMakeTemp(p, n[1], x)
|
when "$3" in frmt: (a, tmp) = maybeMakeTemp(p, n[1], x)
|
||||||
if "$4" in frmt: (a, tmp) = maybeMakeTemp(p, n[1], x)
|
when "$4" in frmt: (a, tmp) = maybeMakeTemp(p, n[1], x)
|
||||||
|
|
||||||
r.res = frmt % [a, b, tmp, tmp2]
|
r.res = frmt % [a, b, tmp, tmp2]
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
@ -520,7 +520,7 @@ proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string,
|
||||||
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
|
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
||||||
proc ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
template ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
||||||
var x, y, z: TCompRes
|
var x, y, z: TCompRes
|
||||||
useMagic(p, magic)
|
useMagic(p, magic)
|
||||||
gen(p, n.sons[1], x)
|
gen(p, n.sons[1], x)
|
||||||
|
|
@ -529,7 +529,7 @@ proc ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
||||||
r.res = frmt % [x.rdLoc, y.rdLoc, z.rdLoc]
|
r.res = frmt % [x.rdLoc, y.rdLoc, z.rdLoc]
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
||||||
proc unaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
template unaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
||||||
# $1 binds to n[1], if $2 is present it will be substituted to a tmp of $1
|
# $1 binds to n[1], if $2 is present it will be substituted to a tmp of $1
|
||||||
useMagic(p, magic)
|
useMagic(p, magic)
|
||||||
gen(p, n.sons[1], r)
|
gen(p, n.sons[1], r)
|
||||||
|
|
@ -541,15 +541,108 @@ proc unaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
||||||
proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||||
var
|
var
|
||||||
x, y: TCompRes
|
x, y: TCompRes
|
||||||
|
xLoc,yLoc: Rope
|
||||||
let i = ord(optOverflowCheck notin p.options)
|
let i = ord(optOverflowCheck notin p.options)
|
||||||
useMagic(p, jsOps[op][i])
|
useMagic(p, jsMagics[op][i])
|
||||||
if sonsLen(n) > 2:
|
if sonsLen(n) > 2:
|
||||||
gen(p, n.sons[1], x)
|
gen(p, n.sons[1], x)
|
||||||
gen(p, n.sons[2], y)
|
gen(p, n.sons[2], y)
|
||||||
r.res = jsOps[op][i + 2] % [x.rdLoc, y.rdLoc]
|
xLoc = x.rdLoc
|
||||||
|
yLoc = y.rdLoc
|
||||||
else:
|
else:
|
||||||
gen(p, n.sons[1], r)
|
gen(p, n.sons[1], r)
|
||||||
r.res = jsOps[op][i + 2] % [r.rdLoc]
|
xLoc = r.rdLoc
|
||||||
|
|
||||||
|
template applyFormat(frmtA, frmtB: string) =
|
||||||
|
if i == 0:
|
||||||
|
r.res = frmtA % [xLoc, yLoc]
|
||||||
|
else:
|
||||||
|
r.res = frmtB % [xLoc, yLoc]
|
||||||
|
|
||||||
|
case op:
|
||||||
|
of mAddI: applyFormat("addInt($1, $2)", "($1 + $2)")
|
||||||
|
of mSubI: applyFormat("subInt($1, $2)", "($1 - $2)")
|
||||||
|
of mMulI: applyFormat("mulInt($1, $2)", "($1 * $2)")
|
||||||
|
of mDivI: applyFormat("divInt($1, $2)", "Math.trunc($1 / $2)")
|
||||||
|
of mModI: applyFormat("modInt($1, $2)", "Math.trunc($1 % $2)")
|
||||||
|
of mSucc: applyFormat("addInt($1, $2)", "($1 + $2)")
|
||||||
|
of mPred: applyFormat("subInt($1, $2)", "($1 - $2)")
|
||||||
|
of mAddF64: applyFormat("($1 + $2)", "($1 + $2)")
|
||||||
|
of mSubF64: applyFormat("($1 - $2)", "($1 - $2)")
|
||||||
|
of mMulF64: applyFormat("($1 * $2)", "($1 * $2)")
|
||||||
|
of mDivF64: applyFormat("($1 / $2)", "($1 / $2)")
|
||||||
|
of mShrI: applyFormat("", "")
|
||||||
|
of mShlI: applyFormat("($1 << $2)", "($1 << $2)")
|
||||||
|
of mAshrI: applyFormat("($1 >> $2)", "($1 >> $2)")
|
||||||
|
of mBitandI: applyFormat("($1 & $2)", "($1 & $2)")
|
||||||
|
of mBitorI: applyFormat("($1 | $2)", "($1 | $2)")
|
||||||
|
of mBitxorI: applyFormat("($1 ^ $2)", "($1 ^ $2)")
|
||||||
|
of mMinI: applyFormat("nimMin($1, $2)", "nimMin($1, $2)")
|
||||||
|
of mMaxI: applyFormat("nimMax($1, $2)", "nimMax($1, $2)")
|
||||||
|
of mMinF64: applyFormat("nimMin($1, $2)", "nimMin($1, $2)")
|
||||||
|
of mMaxF64: applyFormat("nimMax($1, $2)", "nimMax($1, $2)")
|
||||||
|
of mAddU: applyFormat("", "")
|
||||||
|
of msubU: applyFormat("", "")
|
||||||
|
of mmulU: applyFormat("", "")
|
||||||
|
of mdivU: applyFormat("", "")
|
||||||
|
of mmodU: applyFormat("($1 % $2)", "($1 % $2)")
|
||||||
|
of mEqI: applyFormat("($1 == $2)", "($1 == $2)")
|
||||||
|
of mLeI: applyFormat("($1 <= $2)", "($1 <= $2)")
|
||||||
|
of mLtI: applyFormat("($1 < $2)", "($1 < $2)")
|
||||||
|
of mEqF64: applyFormat("($1 == $2)", "($1 == $2)")
|
||||||
|
of mLeF64: applyFormat("($1 <= $2)", "($1 <= $2)")
|
||||||
|
of mLtF64: applyFormat("($1 < $2)", "($1 < $2)")
|
||||||
|
of mleU: applyFormat("($1 <= $2)", "($1 <= $2)")
|
||||||
|
of mltU: applyFormat("($1 < $2)", "($1 < $2)")
|
||||||
|
of mleU64: applyFormat("($1 <= $2)", "($1 <= $2)")
|
||||||
|
of mltU64: applyFormat("($1 < $2)", "($1 < $2)")
|
||||||
|
of mEqEnum: applyFormat("($1 == $2)", "($1 == $2)")
|
||||||
|
of mLeEnum: applyFormat("($1 <= $2)", "($1 <= $2)")
|
||||||
|
of mLtEnum: applyFormat("($1 < $2)", "($1 < $2)")
|
||||||
|
of mEqCh: applyFormat("($1 == $2)", "($1 == $2)")
|
||||||
|
of mLeCh: applyFormat("($1 <= $2)", "($1 <= $2)")
|
||||||
|
of mLtCh: applyFormat("($1 < $2)", "($1 < $2)")
|
||||||
|
of mEqB: applyFormat("($1 == $2)", "($1 == $2)")
|
||||||
|
of mLeB: applyFormat("($1 <= $2)", "($1 <= $2)")
|
||||||
|
of mLtB: applyFormat("($1 < $2)", "($1 < $2)")
|
||||||
|
of mEqRef: applyFormat("($1 == $2)", "($1 == $2)")
|
||||||
|
of mEqUntracedRef: applyFormat("($1 == $2)", "($1 == $2)")
|
||||||
|
of mLePtr: applyFormat("($1 <= $2)", "($1 <= $2)")
|
||||||
|
of mLtPtr: applyFormat("($1 < $2)", "($1 < $2)")
|
||||||
|
of mXor: applyFormat("($1 != $2)", "($1 != $2)")
|
||||||
|
of mEqCString: applyFormat("($1 == $2)", "($1 == $2)")
|
||||||
|
of mEqProc: applyFormat("($1 == $2)", "($1 == $2)")
|
||||||
|
of mUnaryMinusI: applyFormat("negInt($1)", "-($1)")
|
||||||
|
of mUnaryMinusI64: applyFormat("negInt64($1)", "-($1)")
|
||||||
|
of mAbsI: applyFormat("absInt($1)", "Math.abs($1)")
|
||||||
|
of mNot: applyFormat("!($1)", "!($1)")
|
||||||
|
of mUnaryPlusI: applyFormat("+($1)", "+($1)")
|
||||||
|
of mBitnotI: applyFormat("~($1)", "~($1)")
|
||||||
|
of mUnaryPlusF64: applyFormat("+($1)", "+($1)")
|
||||||
|
of mUnaryMinusF64: applyFormat("-($1)", "-($1)")
|
||||||
|
of mAbsF64: applyFormat("Math.abs($1)", "Math.abs($1)")
|
||||||
|
of mZe8ToI: applyFormat("Ze8ToI($1)", "Ze8ToI($1)")
|
||||||
|
of mZe8ToI64: applyFormat("Ze8ToI64($1)", "Ze8ToI64($1)")
|
||||||
|
of mZe16ToI: applyFormat("Ze16ToI($1)", "Ze16ToI($1)")
|
||||||
|
of mZe16ToI64: applyFormat("Ze16ToI64($1)", "Ze16ToI64($1)")
|
||||||
|
of mZe32ToI64: applyFormat("Ze32ToI64($1)", "Ze32ToI64($1)")
|
||||||
|
of mZeIToI64: applyFormat("ZeIToI64($1)", "ZeIToI64($1)")
|
||||||
|
of mtoU8: applyFormat("toU8($1)", "toU8($1)")
|
||||||
|
of mtoU16: applyFormat("toU16($1)", "toU16($1)")
|
||||||
|
of mtoU32: applyFormat("toU32($1)", "toU32($1)")
|
||||||
|
of mToFloat: applyFormat("$1", "$1")
|
||||||
|
of mToBiggestFloat: applyFormat("$1", "$1")
|
||||||
|
of mToInt: applyFormat("Math.trunc($1)", "Math.trunc($1)")
|
||||||
|
of mToBiggestInt: applyFormat("Math.trunc($1)", "Math.trunc($1)")
|
||||||
|
of mCharToStr: applyFormat("nimCharToStr($1)", "nimCharToStr($1)")
|
||||||
|
of mBoolToStr: applyFormat("nimBoolToStr($1)", "nimBoolToStr($1)")
|
||||||
|
of mIntToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
|
||||||
|
of mInt64ToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
|
||||||
|
of mFloatToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
|
||||||
|
of mCStrToStr: applyFormat("cstrToNimstr($1)", "cstrToNimstr($1)")
|
||||||
|
of mStrToStr: applyFormat("$1", "$1")
|
||||||
|
else:
|
||||||
|
assert false, $op
|
||||||
|
|
||||||
proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||||
case op
|
case op
|
||||||
|
|
@ -1603,6 +1696,9 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||||
else:
|
else:
|
||||||
varCode = "var $2"
|
varCode = "var $2"
|
||||||
else:
|
else:
|
||||||
|
# Is this really a thought through feature? this basically unused
|
||||||
|
# feature makes it impossible for almost all format strings in
|
||||||
|
# this function to be checked at compile time.
|
||||||
varCode = v.constraint.strVal
|
varCode = v.constraint.strVal
|
||||||
|
|
||||||
if n.kind == nkEmpty:
|
if n.kind == nkEmpty:
|
||||||
|
|
@ -1611,8 +1707,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||||
lineF(p, "var $1 = null;$n", [varName])
|
lineF(p, "var $1 = null;$n", [varName])
|
||||||
lineF(p, "var $1_Idx = 0;$n", [varName])
|
lineF(p, "var $1_Idx = 0;$n", [varName])
|
||||||
else:
|
else:
|
||||||
lineF(p, varCode & " = $3;$n",
|
line(p, runtimeFormat(varCode & " = $3;$n", [returnType, varName, createVar(p, v.typ, isIndirect(v))]))
|
||||||
[returnType, varName, createVar(p, v.typ, isIndirect(v))])
|
|
||||||
else:
|
else:
|
||||||
gen(p, n, a)
|
gen(p, n, a)
|
||||||
case mapType(p, v.typ)
|
case mapType(p, v.typ)
|
||||||
|
|
@ -1626,29 +1721,29 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||||
let targetBaseIndex = {sfAddrTaken, sfGlobal} * v.flags == {}
|
let targetBaseIndex = {sfAddrTaken, sfGlobal} * v.flags == {}
|
||||||
if a.typ == etyBaseIndex:
|
if a.typ == etyBaseIndex:
|
||||||
if targetBaseIndex:
|
if targetBaseIndex:
|
||||||
lineF(p, varCode & " = $3, $2_Idx = $4;$n",
|
line(p, runtimeFormat(varCode & " = $3, $2_Idx = $4;$n",
|
||||||
[returnType, v.loc.r, a.address, a.res])
|
[returnType, v.loc.r, a.address, a.res]))
|
||||||
else:
|
else:
|
||||||
if isIndirect(v):
|
if isIndirect(v):
|
||||||
lineF(p, varCode & " = [[$3, $4]];$n",
|
line(p, runtimeFormat(varCode & " = [[$3, $4]];$n",
|
||||||
[returnType, v.loc.r, a.address, a.res])
|
[returnType, v.loc.r, a.address, a.res]))
|
||||||
else:
|
else:
|
||||||
lineF(p, varCode & " = [$3, $4];$n",
|
line(p, runtimeFormat(varCode & " = [$3, $4];$n",
|
||||||
[returnType, v.loc.r, a.address, a.res])
|
[returnType, v.loc.r, a.address, a.res]))
|
||||||
else:
|
else:
|
||||||
if targetBaseIndex:
|
if targetBaseIndex:
|
||||||
let tmp = p.getTemp
|
let tmp = p.getTemp
|
||||||
lineF(p, "var $1 = $2, $3 = $1[0], $3_Idx = $1[1];$n",
|
lineF(p, "var $1 = $2, $3 = $1[0], $3_Idx = $1[1];$n",
|
||||||
[tmp, a.res, v.loc.r])
|
[tmp, a.res, v.loc.r])
|
||||||
else:
|
else:
|
||||||
lineF(p, varCode & " = $3;$n", [returnType, v.loc.r, a.res])
|
line(p, runtimeFormat(varCode & " = $3;$n", [returnType, v.loc.r, a.res]))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
s = a.res
|
s = a.res
|
||||||
if isIndirect(v):
|
if isIndirect(v):
|
||||||
lineF(p, varCode & " = [$3];$n", [returnType, v.loc.r, s])
|
line(p, runtimeFormat(varCode & " = [$3];$n", [returnType, v.loc.r, s]))
|
||||||
else:
|
else:
|
||||||
lineF(p, varCode & " = $3;$n", [returnType, v.loc.r, s])
|
line(p, runtimeFormat(varCode & " = $3;$n", [returnType, v.loc.r, s]))
|
||||||
|
|
||||||
if useReloadingGuard:
|
if useReloadingGuard:
|
||||||
dec p.extraIndent
|
dec p.extraIndent
|
||||||
|
|
@ -2117,7 +2212,7 @@ proc genReturnStmt(p: PProc, n: PNode) =
|
||||||
lineF(p, "break BeforeRet;$n", [])
|
lineF(p, "break BeforeRet;$n", [])
|
||||||
|
|
||||||
proc frameCreate(p: PProc; procname, filename: Rope): Rope =
|
proc frameCreate(p: PProc; procname, filename: Rope): Rope =
|
||||||
let frameFmt =
|
const frameFmt =
|
||||||
"var F={procname:$1,prev:framePtr,filename:$2,line:0};$n"
|
"var F={procname:$1,prev:framePtr,filename:$2,line:0};$n"
|
||||||
|
|
||||||
result = p.indentLine(frameFmt % [procname, filename])
|
result = p.indentLine(frameFmt % [procname, filename])
|
||||||
|
|
@ -2185,7 +2280,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
|
||||||
|
|
||||||
var def: Rope
|
var def: Rope
|
||||||
if not prc.constraint.isNil:
|
if not prc.constraint.isNil:
|
||||||
def = (prc.constraint.strVal & " {$n$#$#$#$#$#") %
|
def = runtimeFormat(prc.constraint.strVal & " {$n$#$#$#$#$#",
|
||||||
[ returnType,
|
[ returnType,
|
||||||
name,
|
name,
|
||||||
header,
|
header,
|
||||||
|
|
@ -2193,7 +2288,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
|
||||||
optionalLine(p.locals),
|
optionalLine(p.locals),
|
||||||
optionalLine(resultAsgn),
|
optionalLine(resultAsgn),
|
||||||
optionalLine(genProcBody(p, prc)),
|
optionalLine(genProcBody(p, prc)),
|
||||||
optionalLine(p.indentLine(returnStmt))]
|
optionalLine(p.indentLine(returnStmt))])
|
||||||
else:
|
else:
|
||||||
result = ~"\L"
|
result = ~"\L"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ proc ropeConcat*(a: varargs[Rope]): Rope =
|
||||||
proc prepend*(a: var Rope, b: Rope) = a = b & a
|
proc prepend*(a: var Rope, b: Rope) = a = b & a
|
||||||
proc prepend*(a: var Rope, b: string) = a = b & a
|
proc prepend*(a: var Rope, b: string) = a = b & a
|
||||||
|
|
||||||
proc `%`*(frmt: FormatStr, args: openArray[Rope]): Rope =
|
proc runtimeFormat*(frmt: FormatStr, args: openArray[Rope]): Rope =
|
||||||
var i = 0
|
var i = 0
|
||||||
var length = len(frmt)
|
var length = len(frmt)
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -269,7 +269,10 @@ proc `%`*(frmt: FormatStr, args: openArray[Rope]): Rope =
|
||||||
add(result, substr(frmt, start, i - 1))
|
add(result, substr(frmt, start, i - 1))
|
||||||
assert(ropeInvariant(result))
|
assert(ropeInvariant(result))
|
||||||
|
|
||||||
proc addf*(c: var Rope, frmt: FormatStr, args: openArray[Rope]) =
|
proc `%`*(frmt: static[FormatStr], args: openArray[Rope]): Rope =
|
||||||
|
runtimeFormat(frmt, args)
|
||||||
|
|
||||||
|
template addf*(c: var Rope, frmt: FormatStr, args: openArray[Rope]) =
|
||||||
## shortcut for ``add(c, frmt % args)``.
|
## shortcut for ``add(c, frmt % args)``.
|
||||||
add(c, frmt % args)
|
add(c, frmt % args)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue