added system.default in order to prevent the abstraction inversion that 'template default(T): untyped = (var x: T; x)' causes

This commit is contained in:
Andreas Rumpf
2019-03-05 09:54:59 +01:00
parent 2dc8a32324
commit 142a2d3551
7 changed files with 50 additions and 11 deletions

View File

@@ -130,6 +130,7 @@ proc enumToString*(enums: openArray[enum]): string =
- Added the `posix_utils` module.
- Added `system.default`.
### Library changes

View File

@@ -635,7 +635,7 @@ type
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
mNewString, mNewStringOfCap, mParseBiggestFloat,
mMove, mWasMoved, mDestroy,
mReset,
mDefault, mReset,
mArray, mOpenArray, mRange, mSet, mSeq, mOpt, mVarargs,
mRef, mPtr, mVar, mDistinct, mVoid, mTuple,
mOrdinal,

View File

@@ -1153,6 +1153,9 @@ proc genReset(p: BProc, n: PNode) =
addrLoc(p.config, a),
genTypeInfo(p.module, skipTypes(a.t, {tyVar}), n.info))
proc genDefault(p: BProc; n: PNode; d: var TLoc) =
resetLoc(p, d)
proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
var sizeExpr = sizeExpr
let typ = a.t
@@ -2063,6 +2066,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
addf(p.module.s[cfsDynLibInit], "\t$1 = ($2) hcrGetProc($3, \"$1\");$n",
[mangleDynLibProc(prc), getTypeDesc(p.module, prc.loc.t), getModuleDllPath(p.module, prc)])
genCall(p, e, d)
of mDefault: genDefault(p, e, d)
of mReset: genReset(p, e)
of mEcho: genEcho(p, e[1].skipConv)
of mArrToSeq: genArrToSeq(p, e, d)

View File

@@ -85,6 +85,7 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasHotCodeReloading")
defineSymbol("nimHasNilSeqs")
defineSymbol("nimHasSignatureHashInMacro")
defineSymbol("nimHasDefault")
for f in low(Feature)..high(Feature):
defineSymbol("nimHas" & $f)

View File

@@ -910,6 +910,15 @@ proc genBindSym(c: PCtx; n: PNode; dest: var TDest) =
c.gABC(n, opcNDynBindSym, dest, x, n.len)
c.freeTempRange(x, n.len)
proc fitsRegister*(t: PType): bool =
assert t != nil
t.skipTypes(abstractInst-{tyTypeDesc}).kind in {
tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar}
proc ldNullOpcode(t: PType): TOpcode =
assert t != nil
if fitsRegister(t): opcLdNullReg else: opcLdNull
proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
case m
of mAnd: c.genAndOr(n, opcFJmp, dest)
@@ -1129,9 +1138,13 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mReset:
unused(c, n, dest)
var d = c.genx(n.sons[1])
# XXX use ldNullOpcode() here?
c.gABx(n, opcLdNull, d, c.genType(n.sons[1].typ))
c.gABx(n, opcNodeToReg, d, d)
c.genAsgnPatch(n.sons[1], d)
of mDefault:
if dest < 0: dest = c.getTemp(n.typ)
c.gABx(n, ldNullOpcode(n.typ), dest, c.genType(n.typ))
of mOf, mIs:
if dest < 0: dest = c.getTemp(n.typ)
var tmp = c.genx(n.sons[1])
@@ -1332,11 +1345,6 @@ const
tyFloat, tyFloat32, tyFloat64, tyFloat128,
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64}
proc fitsRegister*(t: PType): bool =
assert t != nil
t.skipTypes(abstractInst-{tyTypeDesc}).kind in {
tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar}
proc unneededIndirection(n: PNode): bool =
n.typ.skipTypes(abstractInstOwned-{tyTypeDesc}).kind == tyRef
@@ -1766,10 +1774,6 @@ proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode =
globalError(conf, info, "cannot create null element for: " & $t.kind)
result = newNodeI(nkEmpty, info)
proc ldNullOpcode(t: PType): TOpcode =
assert t != nil
if fitsRegister(t): opcLdNullReg else: opcLdNull
proc genVarSection(c: PCtx; n: PNode) =
for a in n:
if a.kind == nkCommentStmt: continue

View File

@@ -4278,6 +4278,10 @@ proc `$`*(t: typedesc): string {.magic: "TypeTrait".} =
doAssert $(type("Foo")) == "string"
static: doAssert $(type(@['A', 'B'])) == "seq[char]"
when defined(nimHasDefault):
proc default*(T: typedesc): T {.magic: "Default", noSideEffect.}
## returns the default value of the type ``T``.
import system/widestrs
export widestrs

View File

@@ -1,3 +1,6 @@
discard """
output: '''0'''
"""
static:
type Obj = object
field: int
@@ -5,6 +8,17 @@ static:
reset(o)
doAssert o.field == 0
var x = 4
reset(x)
doAssert x == 0
static:
type ObjB = object
field: int
var o = ObjB(field: 1)
o = default(ObjB)
doAssert o.field == 0
static:
var i = 2
reset(i)
@@ -25,4 +39,15 @@ static:
var i = 2
reset(i)
doAssert i == 0
f()
f()
proc main =
var y = [1, 2, 3, 4]
y = default(array[4, int])
for a in y: doAssert(a == 0)
var x = 4
x = default(int)
echo x
main()