On Sat, 11 Feb 2006 15:40:49 -0500, "Terry Reedy" <[EMAIL PROTECTED]> wrote:
> >"Steve Holden" <[EMAIL PROTECTED]> wrote in message >news:[EMAIL PROTECTED] >> Clearly it would be a good idea to remove whatever problem is causing >> the error, > >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: >>> def test(n): ... 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: >>> import dis >>> n=3 >>> dis.dis( compile('if x:\n'+ n*' a=1\n','','exec')) 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) >> 28 POP_TOP >> 29 LOAD_CONST 1 (None) 32 RETURN_VALUE >>> (2**16-7)/(13-7) 10921 back off 1 >>> test(10920) 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. >>> n=4095 >>> dis.dis( compile('if x:\n'+ n*' a=1+2,4 \n'+' x=0,x','','exec')) Traceback (most recent call last): File "<stdin>", line 1, in ? SystemError: com_backpatch: offset too large >>> n=4094 >>> dis.dis( compile('if x:\n'+ n*' a=1+2,4 \n'+' x=0,x','','exec')) 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 -- http://mail.python.org/mailman/listinfo/python-list