equality and hashing for closures
This commit is contained in:
parent
19e57bf70d
commit
832da8a303
7 changed files with 31 additions and 11 deletions
|
|
@ -489,6 +489,13 @@ proc genEqProc(p: BProc, e: PNode, d: var TLoc) =
|
||||||
else:
|
else:
|
||||||
putIntoDest(p, d, e.typ, ropef("($1 == $2)", [rdLoc(a), rdLoc(b)]))
|
putIntoDest(p, d, e.typ, ropef("($1 == $2)", [rdLoc(a), rdLoc(b)]))
|
||||||
|
|
||||||
|
proc genIsNil(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
let t = skipTypes(e.sons[1].typ, abstractRange)
|
||||||
|
if t.kind == tyProc and t.callConv == ccClosure:
|
||||||
|
unaryExpr(p, e, d, "$1.ClPrc == 0")
|
||||||
|
else:
|
||||||
|
unaryExpr(p, e, d, "$1 == 0")
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -1419,7 +1426,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
of mEqStr: genStrEquals(p, e, d)
|
of mEqStr: genStrEquals(p, e, d)
|
||||||
of mLeStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) <= 0)")
|
of mLeStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) <= 0)")
|
||||||
of mLtStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) < 0)")
|
of mLtStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) < 0)")
|
||||||
of mIsNil: unaryExpr(p, e, d, "$1 == 0")
|
of mIsNil: genIsNil(p, e, d)
|
||||||
of mIntToStr: genDollar(p, e, d, "#nimIntToStr($1)")
|
of mIntToStr: genDollar(p, e, d, "#nimIntToStr($1)")
|
||||||
of mInt64ToStr: genDollar(p, e, d, "#nimInt64ToStr($1)")
|
of mInt64ToStr: genDollar(p, e, d, "#nimInt64ToStr($1)")
|
||||||
of mBoolToStr: genDollar(p, e, d, "#nimBoolToStr($1)")
|
of mBoolToStr: genDollar(p, e, d, "#nimBoolToStr($1)")
|
||||||
|
|
|
||||||
|
|
@ -900,16 +900,15 @@ proc evalTypeTrait*(n: PNode, context: PSym): PNode =
|
||||||
## XXX: This should be pretty much guaranteed to be true
|
## XXX: This should be pretty much guaranteed to be true
|
||||||
# by the type traits procs' signatures, but until the
|
# by the type traits procs' signatures, but until the
|
||||||
# code is more mature it doesn't hurt to be extra safe
|
# code is more mature it doesn't hurt to be extra safe
|
||||||
internalAssert n.sons.len >= 2 and
|
internalAssert n.sons.len >= 2 and n.sons[1].kind == nkSym and
|
||||||
n.sons[1].sym.typ.kind == tyTypeDesc
|
n.sons[1].sym.typ.kind == tyTypeDesc
|
||||||
|
|
||||||
let typ = n.sons[1].sym.typ.skipTypes({tyTypeDesc})
|
let typ = n.sons[1].sym.typ.skipTypes({tyTypeDesc})
|
||||||
case n.sons[0].sym.name.s
|
case n.sons[0].sym.name.s.normalize
|
||||||
of "name":
|
of "name":
|
||||||
result = newStrNode(nkStrLit, typ.typeToString(preferExported))
|
result = newStrNode(nkStrLit, typ.typeToString(preferExported))
|
||||||
result.typ = newType(tyString, context)
|
result.typ = newType(tyString, context)
|
||||||
result.info = n.info
|
result.info = n.info
|
||||||
|
|
||||||
else:
|
else:
|
||||||
internalAssert false
|
internalAssert false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -262,11 +262,12 @@ proc semOf(c: PContext, n: PNode): PNode =
|
||||||
|
|
||||||
proc semIs(c: PContext, n: PNode): PNode =
|
proc semIs(c: PContext, n: PNode): PNode =
|
||||||
if sonsLen(n) == 3:
|
if sonsLen(n) == 3:
|
||||||
var a = semTypeNode(c, n[1], nil)
|
|
||||||
var b = semTypeNode(c, n[2], nil)
|
|
||||||
n.typ = getSysType(tyBool)
|
n.typ = getSysType(tyBool)
|
||||||
|
let a = semTypeNode(c, n[1], nil)
|
||||||
n.sons[1] = newNodeIT(nkType, n[1].info, a)
|
n.sons[1] = newNodeIT(nkType, n[1].info, a)
|
||||||
n.sons[2] = newNodeIT(nkType, n[2].info, b)
|
if n[2].kind notin {nkStrLit..nkTripleStrLit}:
|
||||||
|
let b = semTypeNode(c, n[2], nil)
|
||||||
|
n.sons[2] = newNodeIT(nkType, n[2].info, b)
|
||||||
result = n
|
result = n
|
||||||
else:
|
else:
|
||||||
GlobalError(n.info, errXExpectsTwoArguments, "is")
|
GlobalError(n.info, errXExpectsTwoArguments, "is")
|
||||||
|
|
|
||||||
|
|
@ -604,9 +604,15 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
result = magicCall(m, n)
|
result = magicCall(m, n)
|
||||||
of mIs:
|
of mIs:
|
||||||
# BUGFIX: don't evaluate this too early: ``T is void``
|
# BUGFIX: don't evaluate this too early: ``T is void``
|
||||||
if not containsGenericType(n[1].typ) and
|
if not containsGenericType(n[1].typ):
|
||||||
not containsGenericType(n[2].typ):
|
if n[2].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
result = newIntNodeT(ord(sameType(n[1].typ, n[2].typ)), n)
|
case n[2].strVal.normalize
|
||||||
|
of "closure":
|
||||||
|
let t = skipTypes(n[1].typ, abstractRange)
|
||||||
|
result = newIntNodeT(ord(t.kind == tyProc and
|
||||||
|
t.callConv == ccClosure), n)
|
||||||
|
elif not containsGenericType(n[2].typ):
|
||||||
|
result = newIntNodeT(ord(sameType(n[1].typ, n[2].typ)), n)
|
||||||
of mAstToStr:
|
of mAstToStr:
|
||||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
|
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
|
||||||
of mConStrStr:
|
of mConStrStr:
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,13 @@ proc hash*(x: Pointer): THash {.inline.} =
|
||||||
else:
|
else:
|
||||||
result = (cast[THash](x)) shr 3 # skip the alignment
|
result = (cast[THash](x)) shr 3 # skip the alignment
|
||||||
|
|
||||||
|
proc hash*[T: proc](x: T): THash {.inline.} =
|
||||||
|
## efficient hashing of proc vars; closures are supported too.
|
||||||
|
when T is "closure":
|
||||||
|
result = hash(rawProc(x)) !& hash(rawEnv(x))
|
||||||
|
else:
|
||||||
|
result = hash(pointer(x))
|
||||||
|
|
||||||
proc hash*(x: int): THash {.inline.} =
|
proc hash*(x: int): THash {.inline.} =
|
||||||
## efficient hashing of integers
|
## efficient hashing of integers
|
||||||
result = x
|
result = x
|
||||||
|
|
|
||||||
|
|
@ -1348,6 +1348,7 @@ proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil".}
|
||||||
proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".}
|
proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".}
|
||||||
proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".}
|
proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".}
|
||||||
proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}
|
proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}
|
||||||
|
proc isNil*[T: proc](x: T): bool {.noSideEffect, magic: "IsNil".}
|
||||||
## Fast check whether `x` is nil. This is sometimes more efficient than
|
## Fast check whether `x` is nil. This is sometimes more efficient than
|
||||||
## ``== nil``.
|
## ``== nil``.
|
||||||
|
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -17,7 +17,6 @@ New pragmas:
|
||||||
- fix evals.nim with closures
|
- fix evals.nim with closures
|
||||||
- implement "closure tuple consists of a single 'ref'" optimization
|
- implement "closure tuple consists of a single 'ref'" optimization
|
||||||
- make closure default calling convention for proc types
|
- make closure default calling convention for proc types
|
||||||
- fix '==' for closures
|
|
||||||
|
|
||||||
- document 'do' notation
|
- document 'do' notation
|
||||||
- rethink the syntax: distinction between expr and stmt is unfortunate;
|
- rethink the syntax: distinction between expr and stmt is unfortunate;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue