bugfixes for closures

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

View file

@ -124,8 +124,18 @@ proc GetUniqueType*(key: PType): PType =
result = key result = key
of tyProc: of tyProc:
# tyVar is not 100% correct, but would speeds things up a little: # 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 = proc TableGetType*(tab: TIdTable, key: PType): PObject =
# returns nil if we need to declare this type # returns nil if we need to declare this type
result = IdTableGet(tab, key) result = IdTableGet(tab, key)

View file

@ -366,14 +366,17 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
var it = n.sons[i] var it = n.sons[i]
if it.kind == nkCommentStmt: nil if it.kind == nkCommentStmt: nil
elif it.kind == nkIdentDefs: elif it.kind == nkIdentDefs:
var L = sonsLen(it)
if it.sons[0].kind != nkSym: InternalError(it.info, "transformOuter") if it.sons[0].kind != nkSym: InternalError(it.info, "transformOuter")
#echo "set: ", it.sons[0].sym.name.s, " ", o.currentBlock == nil #echo "set: ", it.sons[0].sym.name.s, " ", o.currentBlock == nil
IdTablePut(o.localsToEnv, it.sons[0].sym, o.currentEnv) IdTablePut(o.localsToEnv, it.sons[0].sym, o.currentEnv)
searchForInnerProcs(o, it.sons[L-1])
elif it.kind == nkVarTuple: elif it.kind == nkVarTuple:
var L = sonsLen(it) var L = sonsLen(it)
for j in countup(0, L-3): for j in countup(0, L-3):
#echo "set: ", it.sons[j].sym.name.s, " ", o.currentBlock == nil #echo "set: ", it.sons[j].sym.name.s, " ", o.currentBlock == nil
IdTablePut(o.localsToEnv, it.sons[j].sym, o.currentEnv) IdTablePut(o.localsToEnv, it.sons[j].sym, o.currentEnv)
searchForInnerProcs(o, it.sons[L-1])
else: else:
InternalError(it.info, "transformOuter") InternalError(it.info, "transformOuter")
of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
@ -493,7 +496,6 @@ proc liftLambdas(fn: PSym, body: PNode): PNode =
searchForInnerProcs(o, body) searchForInnerProcs(o, body)
let a = transformOuterProc(o, body) let a = transformOuterProc(o, body)
result = ex result = ex
#echo renderTree(result)
# XXX should 's' be replaced by a tuple ('s', env)? # 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()) writeContext(unknownLineInfo())
frmt = rawErrorFormat frmt = rawErrorFormat
of warnMin..warnMax: of warnMin..warnMax:
if not (optWarns in gOptions): return if optWarns notin gOptions: return
if not (msg in gNotes): return if msg notin gNotes: return
writeContext(unknownLineInfo()) writeContext(unknownLineInfo())
frmt = rawWarningFormat frmt = rawWarningFormat
inc(gWarnCounter) inc(gWarnCounter)
of hintMin..hintMax: of hintMin..hintMax:
if not (optHints in gOptions): return if optHints notin gOptions: return
if not (msg in gNotes): return if msg notin gNotes: return
frmt = rawHintFormat frmt = rawHintFormat
inc(gHintCounter) inc(gHintCounter)
let s = `%`(frmt, `%`(msgKindToString(msg), args)) 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} IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
if sameType(castDest, src) and castDest.sym == src.sym: if sameType(castDest, src) and castDest.sym == src.sym:
# don't annoy conversions that may be needed on another processor: # 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)) Message(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
return return
var d = skipTypes(castDest, abstractVar) var d = skipTypes(castDest, abstractVar)
var s = skipTypes(src, abstractVar) var s = skipTypes(src, abstractVar)
while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind): 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}) result = semOverloadedCall(c, n, nOrig, {skIterator})
elif efInTypeOf in flags: elif efInTypeOf in flags:
# for ``type(countup(1,3))``, see ``tests/ttoseq``. # 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: 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 != nil:
if result.sons[0].kind != nkSym: if result.sons[0].kind != nkSym:
InternalError("semDirectCallAnalyseEffects") InternalError("semDirectCallAnalyseEffects")
@ -838,7 +840,7 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
# if f != nil and f.kind == skStub: loadStub(f) # if f != nil and f.kind == skStub: loadStub(f)
# ``loadStub`` is not correct here as we don't care for ``f`` really # ``loadStub`` is not correct here as we don't care for ``f`` really
if f != nil: 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`. # This special node kind is to merge with the call handler in `semExpr`.
result = newNodeI(nkDotCall, n.info) result = newNodeI(nkDotCall, n.info)
addSon(result, newIdentNode(i, 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) pushProcCon(c, s)
if s.typ.sons[0] != nil and kind != skIterator: if s.typ.sons[0] != nil and kind != skIterator:
addResult(c, s.typ.sons[0], n.info, kind) addResult(c, s.typ.sons[0], n.info, kind)
if sfImportc notin s.flags: if sfImportc notin s.flags:
# no semantic checking for importc: # no semantic checking for importc:
n.sons[bodyPos] = semStmtScope(c, n.sons[bodyPos]) n.sons[bodyPos] = semStmtScope(c, n.sons[bodyPos])
if s.typ.sons[0] != nil and kind != skIterator: addResultNode(c, n) 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"(`result`)
:"a"(`a`), "c"(`b`) :"a"(`a`), "c"(`b`)
""" """
#".intel_syntax noprefix"
#/* Intel syntax here */
#".att_syntax"
proc subInt(a, b: int): int {.compilerProc, inline.} = proc subInt(a, b: int): int {.compilerProc, inline.} =
asm """ "subl %%ecx,%%eax\n" 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()