bugfixes for closures

This commit is contained in:
Araq
2012-06-21 08:46:56 +02:00
parent 00feaa2530
commit 7b4560337b
7 changed files with 58 additions and 13 deletions

View File

@@ -124,8 +124,18 @@ proc GetUniqueType*(key: PType): PType =
result = key
of tyProc:
# tyVar is not 100% correct, but would speeds things up a little:
result = key
if key.callConv != ccClosure:
result = key
else:
# ugh, we need the canon here:
if IdTableHasObjectAsKey(gTypeTable[k], key): return key
for h in countup(0, high(gTypeTable[k].data)):
var t = PType(gTypeTable[k].data[h].key)
if t != nil and sameBackendType(t, key):
return t
IdTablePut(gTypeTable[k], key, key)
result = key
proc TableGetType*(tab: TIdTable, key: PType): PObject =
# returns nil if we need to declare this type
result = IdTableGet(tab, key)

View File

@@ -366,14 +366,17 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
var it = n.sons[i]
if it.kind == nkCommentStmt: nil
elif it.kind == nkIdentDefs:
var L = sonsLen(it)
if it.sons[0].kind != nkSym: InternalError(it.info, "transformOuter")
#echo "set: ", it.sons[0].sym.name.s, " ", o.currentBlock == nil
IdTablePut(o.localsToEnv, it.sons[0].sym, o.currentEnv)
searchForInnerProcs(o, it.sons[L-1])
elif it.kind == nkVarTuple:
var L = sonsLen(it)
for j in countup(0, L-3):
#echo "set: ", it.sons[j].sym.name.s, " ", o.currentBlock == nil
IdTablePut(o.localsToEnv, it.sons[j].sym, o.currentEnv)
searchForInnerProcs(o, it.sons[L-1])
else:
InternalError(it.info, "transformOuter")
of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
@@ -493,7 +496,6 @@ proc liftLambdas(fn: PSym, body: PNode): PNode =
searchForInnerProcs(o, body)
let a = transformOuterProc(o, body)
result = ex
#echo renderTree(result)
# XXX should 's' be replaced by a tuple ('s', env)?

View File

@@ -596,14 +596,14 @@ proc rawMessage*(msg: TMsgKind, args: openarray[string]) =
writeContext(unknownLineInfo())
frmt = rawErrorFormat
of warnMin..warnMax:
if not (optWarns in gOptions): return
if not (msg in gNotes): return
if optWarns notin gOptions: return
if msg notin gNotes: return
writeContext(unknownLineInfo())
frmt = rawWarningFormat
inc(gWarnCounter)
of hintMin..hintMax:
if not (optHints in gOptions): return
if not (msg in gNotes): return
if optHints notin gOptions: return
if msg notin gNotes: return
frmt = rawHintFormat
inc(gHintCounter)
let s = `%`(frmt, `%`(msgKindToString(msg), args))

View File

@@ -135,9 +135,9 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
if sameType(castDest, src) and castDest.sym == src.sym:
# don't annoy conversions that may be needed on another processor:
if not (castDest.kind in {tyInt..tyUInt64, tyNil}):
if castDest.kind notin {tyInt..tyUInt64, tyNil}:
Message(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
return
return
var d = skipTypes(castDest, abstractVar)
var s = skipTypes(src, abstractVar)
while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind):
@@ -538,9 +538,11 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
result = semOverloadedCall(c, n, nOrig, {skIterator})
elif efInTypeOf in flags:
# for ``type(countup(1,3))``, see ``tests/ttoseq``.
result = semOverloadedCall(c, n, nOrig, {skIterator, skProc, skMethod, skConverter, skMacro, skTemplate})
result = semOverloadedCall(c, n, nOrig,
{skProc, skMethod, skConverter, skMacro, skTemplate, skIterator})
else:
result = semOverloadedCall(c, n, nOrig, {skProc, skMethod, skConverter, skMacro, skTemplate})
result = semOverloadedCall(c, n, nOrig,
{skProc, skMethod, skConverter, skMacro, skTemplate})
if result != nil:
if result.sons[0].kind != nkSym:
InternalError("semDirectCallAnalyseEffects")
@@ -838,7 +840,7 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
# if f != nil and f.kind == skStub: loadStub(f)
# ``loadStub`` is not correct here as we don't care for ``f`` really
if f != nil:
# BUGFIX: do not check for (f.kind in [skProc, skMethod, skIterator]) here
# BUGFIX: do not check for (f.kind in {skProc, skMethod, skIterator}) here
# This special node kind is to merge with the call handler in `semExpr`.
result = newNodeI(nkDotCall, n.info)
addSon(result, newIdentNode(i, n.info))

View File

@@ -767,7 +767,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
pushProcCon(c, s)
if s.typ.sons[0] != nil and kind != skIterator:
addResult(c, s.typ.sons[0], n.info, kind)
if sfImportc notin s.flags:
if sfImportc notin s.flags:
# no semantic checking for importc:
n.sons[bodyPos] = semStmtScope(c, n.sons[bodyPos])
if s.typ.sons[0] != nil and kind != skIterator: addResultNode(c, n)

View File

@@ -184,6 +184,9 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
:"=a"(`result`)
:"a"(`a`), "c"(`b`)
"""
#".intel_syntax noprefix"
#/* Intel syntax here */
#".att_syntax"
proc subInt(a, b: int): int {.compilerProc, inline.} =
asm """ "subl %%ecx,%%eax\n"

28
tests/run/tfilter.nim Normal file
View File

@@ -0,0 +1,28 @@
discard """
output: "02468101214161820"
"""
proc filter[T](list: seq[T], f: proc (item: T): bool {.closure.}): seq[T] =
result = @[]
for i in items(list):
if f(i):
result.add(i)
let nums = @[0, 1, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
when true:
let nums2 = filter(nums,
(proc (item: int): bool =
result = (item mod 2) == 0)
)
proc outer =
# lets use a proper closure this time:
var modulo = 2
let nums2 = filter(nums,
(proc (item: int): bool = result = (item mod modulo) == 0)
)
for n in nums2: stdout.write(n)
outer()