[Python-ideas] Augment dis.dis to autocompile strings

Georg Brandl g.brandl at gmx.net
Sat Jul 18 12:01:12 CEST 2009


Nick Coghlan schrieb:
> Steven D'Aprano wrote:
>> On Fri, 17 Jul 2009 04:35:40 am Terry Reedy wrote:
>> 
>>> Proposal: if the input is a string, do the above (do what I mean)
>>> instead of raising
>>> TypeError: don't know how to disassemble str objects
>>>
>>> Any negatives before I submit a feature request?
>> 
>> +1 on the idea, but how do you determine which of the following are 
>> required?
>> 
>> compile('x+1', '', 'eval')
>> compile('x = x+1', '', 'single')
>> compile('while x < 42: x += 1', '', 'exec')
>> 
>> 
>> Or do you just assume 'exec'?
> 
> We could define it as trying the three in order (first 'eval', then
> 'single', then 'exec') moving on to the next option if it raises syntax
> error:
>
> from dis import dis
> def dis_str(source):
>   modes = ('eval', 'single', 'exec')
>   for mode in modes:
>     try:
>       c = compile(source, '', mode)
>       break
>     except SyntaxError:
>       if mode is modes[-1]:
>         raise
>   return dis(c)

Allowing 'single' has five unfortunate side effects: first, newlines at
the end make a difference; second, there will be PRINT_EXPRs sprinkled
in the disassembly seemingly coming from nowhere, third, statements after
the first will disappear:

>>> dis_str("for x in range(10): x\n")
  1           0 SETUP_LOOP              24 (to 27)
              3 LOAD_NAME                0 (range)
              6 LOAD_CONST               0 (10)
              9 CALL_FUNCTION            1
             12 GET_ITER
        >>   13 FOR_ITER                10 (to 26)
             16 STORE_NAME               1 (x)
             19 LOAD_NAME                1 (x)
             22 PRINT_EXPR
             23 JUMP_ABSOLUTE           13
        >>   26 POP_BLOCK
        >>   27 LOAD_CONST               1 (None)
             30 RETURN_VALUE

>>> dis_str("for x in range(10): x")
  1           0 SETUP_LOOP              24 (to 27)
              3 LOAD_NAME                0 (range)
              6 LOAD_CONST               0 (10)
              9 CALL_FUNCTION            1
             12 GET_ITER
        >>   13 FOR_ITER                10 (to 26)
             16 STORE_NAME               1 (x)
             19 LOAD_NAME                1 (x)
             22 POP_TOP
             23 JUMP_ABSOLUTE           13
        >>   26 POP_BLOCK
        >>   27 LOAD_CONST               1 (None)
             30 RETURN_VALUE

>>> dis_str("x=1\nx=2\n")
  1           0 LOAD_CONST               0 (1)
              3 STORE_NAME               0 (x)
              6 LOAD_CONST               1 (None)
              9 RETURN_VALUE

I don't think using "single" makes sense here; trying "eval" can't hurt,
though.

Georg


-- 
Thus spake the Lord: Thou shalt indent with four spaces. No more, no less.
Four shall be the number of spaces thou shalt indent, and the number of thy
indenting shall be four. Eight shalt thou not indent, nor either indent thou
two, excepting that thou then proceed to four. Tabs are right out.




More information about the Python-ideas mailing list