The problem (see my post of the com_backpatch code) is writing a compound
statement (here a for loop) with a body so large as to require a jump of
more than 64K bytes in the compiled bytecode (ie, from the test at the top
of the loop to the code that follows after the loop). Until the jump limit
is raised (likely a long wait ;-), the OP must factor some of the code out
of the loop.
Easy example:
... while True:
... try: co = compile('if x:\n'+ n*' a=1\n','','exec')
... except Exception,e: break
... n += 1
... print 'Stopped at n=%s due to %s: %s'%(n, e.__class__.__name__,e)
...
get an idea of where to start that:
1 0 LOAD_NAME 0 (x)
3 JUMP_IF_FALSE 22 (to 28)
6 POP_TOP
2 7 LOAD_CONST 0 (1)
10 STORE_NAME 1 (a)
3 13 LOAD_CONST 0 (1)
16 STORE_NAME 1 (a)
4 19 LOAD_CONST 0 (1)
22 STORE_NAME 1 (a)
25 JUMP_FORWARD 1 (to 29) 10921
back off 1
Stopped at n=10922 due to SystemError: com_backpatch: offset too large
Decided to test the exact 65536 jump with code chunks of 16 byte-codes and one
chunk at the end to make 16 with the last JUMP_FORWARD.
Traceback (most recent call last):
1 0 LOAD_NAME 0 (x)
3 JUMP_IF_FALSE 65520 (to 65526)
6 POP_TOP
2 7 LOAD_CONST 0 (1)
10 LOAD_CONST 1 (2)
13 BINARY_ADD
14 LOAD_CONST 2 (4)
17 BUILD_TUPLE 2
20 STORE_NAME 1 (a)
3 23 LOAD_CONST 0 (1)
So the corner case of 2**16 is ok. Believe it or not, I once discovered a compiler
error based on optimizing a 2**16-involving loop condition as if it were 0 and the
loop didn't execute! IIRC, I bumped into it processing an array of records with a stride of
exactly 2**n and it thought it could calculate a 16-bit number of strides for end of loop.
No good for arraysize/stridesize==2**16 ;-)
If the OP really HAD to, he could always (untested) break
if cond:
too
large
else:
two
large,also
into
if cond:
too
else:
two
if cond:
large
else:
large,also
but that reads gawdawfully. (So, I imagine, does about any code hitting the offset limit ;-)
If it's a matter of too many elifs, the OP could break that more readably, e.g. (untested)
done=True
if cond:
bla
elif c2:
bla 2
...
elif c456:
bla456
else:
done=False
more, done = not done,True
if more and c457:
bla c457
elif c458:
bla458
...
elif c1012:
bla1012
else:
done = False
more, done = not done,True
... etc
But the OP should find another approach I think,
because this is still disgusting code ;-)
Regards,
Bengt Richter