mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-16 01:35:35 +00:00
bugfixes for closures
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)?
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
28
tests/run/tfilter.nim
Normal 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()
|
||||
Reference in New Issue
Block a user