bugfix: invoking a generic iterator twice triggers a code gen bug (titer2)

This commit is contained in:
Araq 2011-06-20 01:28:41 +02:00
commit c3f11d1637
5 changed files with 24 additions and 19 deletions

View file

@ -14,7 +14,7 @@ import
wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math, wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
magicsys, parser, nversion, nimsets, semdata, evals, semfold, importer, magicsys, parser, nversion, nimsets, semdata, evals, semfold, importer,
procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest, procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest,
semthreads, intsets semthreads, intsets, transf
proc semPass*(): TPass proc semPass*(): TPass
# implementation # implementation
@ -138,8 +138,8 @@ proc addCodeForGenerics(c: PContext, n: PNode) =
var it = c.generics.sons[i].sons[1] var it = c.generics.sons[i].sons[1]
if it.kind != nkSym: InternalError("addCodeForGenerics") if it.kind != nkSym: InternalError("addCodeForGenerics")
var prc = it.sym var prc = it.sym
if (prc.kind in {skProc, skMethod, skConverter}) and (prc.magic == mNone): if prc.kind in {skProc, skMethod, skConverter} and prc.magic == mNone:
if (prc.ast == nil) or (prc.ast.sons[codePos] == nil): if prc.ast == nil or prc.ast.sons[codePos] == nil:
InternalError(prc.info, "no code for " & prc.name.s) InternalError(prc.info, "no code for " & prc.name.s)
addSon(n, prc.ast) addSon(n, prc.ast)
c.lastGenericIdx = sonsLen(c.generics) c.lastGenericIdx = sonsLen(c.generics)

View file

@ -105,6 +105,9 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
addResult(c, result.typ.sons[0], n.info) addResult(c, result.typ.sons[0], n.info)
addResultNode(c, n) addResultNode(c, n)
n.sons[codePos] = semStmtScope(c, n.sons[codePos]) n.sons[codePos] = semStmtScope(c, n.sons[codePos])
if fn.kind == skIterator:
# XXX Bad hack for tests/titer2:
n.sons[codePos] = transform(c.module, n.sons[codePos])
popProcCon(c) popProcCon(c)
#echo "code instantiated ", result.name.s #echo "code instantiated ", result.name.s
else: else:

View file

@ -472,6 +472,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
# generate access statements for the parameters (unless they are constant) # generate access statements for the parameters (unless they are constant)
# put mapping from formal parameters to actual parameters # put mapping from formal parameters to actual parameters
if n.kind != nkForStmt: InternalError(n.info, "transformFor") if n.kind != nkForStmt: InternalError(n.info, "transformFor")
#echo "transforming: ", renderTree(n)
result = newTransNode(nkStmtList, n.info, 0) result = newTransNode(nkStmtList, n.info, 0)
var length = sonsLen(n) var length = sonsLen(n)
var loopBody = transformLoopBody(c, n.sons[length-1]) var loopBody = transformLoopBody(c, n.sons[length-1])
@ -480,14 +481,13 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
addVar(v, copyTree(n.sons[i])) # declare new vars addVar(v, copyTree(n.sons[i])) # declare new vars
add(result, v.ptransNode) add(result, v.ptransNode)
var call = n.sons[length - 2] var call = n.sons[length - 2]
if (call.kind != nkCall) or (call.sons[0].kind != nkSym): if call.kind != nkCall or call.sons[0].kind != nkSym:
InternalError(call.info, "transformFor") InternalError(call.info, "transformFor")
var newC = newTransCon(call.sons[0].sym) var newC = newTransCon(call.sons[0].sym)
newC.forStmt = n newC.forStmt = n
newC.forLoopBody = loopBody newC.forLoopBody = loopBody
if (newC.owner.kind != skIterator): if newC.owner.kind != skIterator: InternalError(call.info, "transformFor")
InternalError(call.info, "transformFor")
# generate access statements for the parameters (unless they are constant) # generate access statements for the parameters (unless they are constant)
pushTransCon(c, newC) pushTransCon(c, newC)
for i in countup(1, sonsLen(call) - 1): for i in countup(1, sonsLen(call) - 1):
@ -512,6 +512,8 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
dec(c.inlining) dec(c.inlining)
popInfoContext() popInfoContext()
popTransCon(c) popTransCon(c)
#echo "transformed: ", renderTree(n)
proc getMagicOp(call: PNode): TMagic = proc getMagicOp(call: PNode): TMagic =
if call.sons[0].kind == nkSym and if call.sons[0].kind == nkSym and
@ -660,7 +662,7 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
inc(j) inc(j)
add(result, transform(c, a)) add(result, transform(c, a))
if len(result) == 2: result = result[1] if len(result) == 2: result = result[1]
elif (n.sons[0].kind == nkSym) and (n.sons[0].sym.kind == skMethod): elif n.sons[0].kind == nkSym and n.sons[0].sym.kind == skMethod:
# use the dispatcher for the call: # use the dispatcher for the call:
result = methodCall(transformSons(c, n).pnode).ptransNode result = methodCall(transformSons(c, n).pnode).ptransNode
else: else:

View file

@ -19,15 +19,15 @@ iterator mycountup(a, b: int): int =
yield res yield res
inc(res) inc(res)
when true:
iterator pairs*[A, B](t: TTable[A, B]): tuple[key: A, val: B] = iterator pairs*[A, B](t: TTable[A, B]): tuple[key: A, val: B] =
## iterates over any (key, value) pair in the table `t`. ## iterates over any (key, value) pair in the table `t`.
var h = 0 for h in mycountup(0, high(t.data)):
while h <= high(t.data):
var k = t.data[h].key var k = t.data[h].key
if t.data[h].slot == seFilled: yield (k, t.data[h].val) if t.data[h].slot == seFilled: yield (k, t.data[h].val)
inc(h) else:
iterator pairs*(t: TTable[int, string]): tuple[key: int, val: string] =
when false: ## iterates over any (key, value) pair in the table `t`.
for h in mycountup(0, high(t.data)): for h in mycountup(0, high(t.data)):
var k = t.data[h].key var k = t.data[h].key
if t.data[h].slot == seFilled: yield (k, t.data[h].val) if t.data[h].slot == seFilled: yield (k, t.data[h].val)

View file

@ -1,10 +1,10 @@
High priority (version 0.8.12) High priority (version 0.8.12)
============================== ==============================
- bug: invoking a generic iterator twice triggers a code gen bug (titer2) * implement write access to ``s[i]`` for macros
* implement message passing built-ins * implement message passing built-ins
* add --deadlock_prevention:on|off switch? timeout for locks? * add --deadlock_prevention:on|off switch? timeout for locks?
* built-in serialization * built-in serialization
* test encodings.nim on windows
version 0.9.0 version 0.9.0
@ -43,7 +43,6 @@ version 0.9.XX
is hard because of partial evaluation --> symbol files will fix this as is hard because of partial evaluation --> symbol files will fix this as
a side effect a side effect
- EcmaScript needs a new and better code gen: simply adapt the C code gen to it - EcmaScript needs a new and better code gen: simply adapt the C code gen to it
- generalized case statement (requires better transf)
- tlastmod returns wrong results on BSD (Linux, MacOS X: works) - tlastmod returns wrong results on BSD (Linux, MacOS X: works)
- nested tuple unpacking - nested tuple unpacking
- 'nimrod def': does not always work? - 'nimrod def': does not always work?
@ -99,6 +98,7 @@ Version 2
var x = myProc() # checks myProc() initializes every pointer explicitely var x = myProc() # checks myProc() initializes every pointer explicitely
- the two other parsers - the two other parsers
- generalized case statement (requires better transf)
- rethink the syntax: distinction between expr and stmt is unfortunate; - rethink the syntax: distinction between expr and stmt is unfortunate;
indentation handling is quite complex too; problem with exception handling indentation handling is quite complex too; problem with exception handling
is that often the scope of ``try`` is wrong and apart from that ``try`` is is that often the scope of ``try`` is wrong and apart from that ``try`` is