[Subversion] / BytecodeAssembler / README.txt  

Diff of /BytecodeAssembler/README.txt

Parent Directory | Revision Log

version 2631, Mon Aug 2 19:34:21 2010 UTC version 2768, Thu Apr 9 17:40:32 2015 UTC
Line 19 
Line 19 
 .. _BytecodeAssembler reference manual: http://peak.telecommunity.com/DevCenter/BytecodeAssembler#toc  .. _BytecodeAssembler reference manual: http://peak.telecommunity.com/DevCenter/BytecodeAssembler#toc
   
   
   Changes since version 0.6:
   
   * Experimental Python 3 support, including emulation of restored
     ``BINARY_DIVIDE``, ``UNARY_CONVERT``, and ``SLICE_#`` opcodes.
   
 Changes since version 0.5.2:  Changes since version 0.5.2:
   
 * Symbolic disassembly with full emulation of backward-compatible  * Symbolic disassembly with full emulation of backward-compatible
Line 210 
Line 215 
 that maps each ``set_lineno()`` to the corresponding position in the bytecode.  that maps each ``set_lineno()`` to the corresponding position in the bytecode.
   
 And of course, the resulting code objects can be run with ``eval()`` or  And of course, the resulting code objects can be run with ``eval()`` or
 ``exec``, or used with ``new.function`` to create a function::  ``exec``, or used with ``new.function``/``types.FunctionType`` to create a
   function::
   
     >>> eval(c.code())      >>> eval(c.code())
     42      42
   
     >>> exec c.code()   # exec discards the return value, so no output here      >>> exec(c.code())   # exec discards the return value, so no output here
   
       >>> try:
       ...     from new import function
       ... except ImportError:  # Python 3 workarounds
       ...     from types import FunctionType as function
       ...     long = int
       ...     unicode = str
   
     >>> import new      >>> f = function(c.code(), globals())
     >>> f = new.function(c.code(), globals())  
     >>> f()      >>> f()
     42      42
   
Line 339 
Line 351 
     >>> c.RETURN_VALUE()      >>> c.RETURN_VALUE()
   
     >>> eval(c.code())          # computes type(27)      >>> eval(c.code())          # computes type(27)
     <type 'int'>      <... 'int'>
   
     >>> c = Code()      >>> c = Code()
     >>> c.LOAD_CONST(dict)      >>> c.LOAD_CONST(dict)
Line 475 
Line 487 
 ``None``, or Python code object, it is treated as though it was passed to  ``None``, or Python code object, it is treated as though it was passed to
 the ``LOAD_CONST`` method directly::  the ``LOAD_CONST`` method directly::
   
   
   
     >>> c = Code()      >>> c = Code()
     >>> c(1, 2L, 3.0, 4j+5, "6", u"7", False, None, c.code())      >>> c(1, long(2), 3.0, 4j+5, "6", unicode("7"), False, None, c.code())
     >>> dis(c.code())      >>> dis(c.code())
       0           0 LOAD_CONST               1 (1)        0           0 LOAD_CONST               1 (1)
                   3 LOAD_CONST               2 (2L)                    3 LOAD_CONST               2 (2...)
                   6 LOAD_CONST               3 (3.0)                    6 LOAD_CONST               3 (3.0)
                   9 LOAD_CONST               4 ((5+4j))                    9 LOAD_CONST               4 ((5+4j))
                  12 LOAD_CONST               5 ('6')                   12 LOAD_CONST               5 ('6')
                  15 LOAD_CONST               6 (u'7')                   15 LOAD_CONST               6 (...'7')
                  18 LOAD_CONST               7 (False)                   18 LOAD_CONST               7 (False)
                  21 LOAD_CONST               0 (None)                   21 LOAD_CONST               0 (None)
                  24 LOAD_CONST               8 (<code object <lambda> at ...>)                   24 LOAD_CONST               8 (<code object <lambda>...>)
   
 Note that although some values of different types may compare equal to each  Note that although some values of different types may compare equal to each
 other, ``Code`` objects will not substitute a value of a different type than  other, ``Code`` objects will not substitute a value of a different type than
 the one you requested::  the one you requested::
   
     >>> c = Code()      >>> c = Code()
     >>> c(1, True, 1.0, 1L)     # equal, but different types      >>> c(1, True, 1.0)     # equal, but different types
     >>> dis(c.code())      >>> dis(c.code())
       0           0 LOAD_CONST               1 (1)        0           0 LOAD_CONST               1 (1)
                   3 LOAD_CONST               2 (True)                    3 LOAD_CONST               2 (True)
                   6 LOAD_CONST               3 (1.0)                    6 LOAD_CONST               3 (1.0)
                   9 LOAD_CONST               4 (1L)  
   
 Simple Containers  Simple Containers
 -----------------  -----------------
Line 680 
Line 693 
   
   
     >>> Getattr(Const(object), '__class__') # const expression, const result      >>> Getattr(Const(object), '__class__') # const expression, const result
     Const(<type 'type'>)      Const(<... 'type'>)
   
 Or the attribute name can be an expression, in which case a ``getattr()`` call  Or the attribute name can be an expression, in which case a ``getattr()`` call
 is compiled instead::  is compiled instead::
Line 1029 
Line 1042 
   
     >>> from peak.util.assembler import const_value      >>> from peak.util.assembler import const_value
   
     >>> simple_values = [1, 2L, 3.0, 4j+5, "6", u"7", False, None, c.code()]      >>> simple_values = [1, long(2), 3.0, 4j+5, "6", unicode("7"), False, None, c.code()]
   
     >>> map(const_value, simple_values)      >>> list(map(const_value, simple_values))
     [1, 2L, 3.0, (5+4j), '6', u'7', False, None, <code object <lambda> ...>]      [1, 2..., 3.0, (5+4j), '6', ...'7', False, None, <code object <lambda>...>]
   
 Values wrapped in a ``Const()`` are also returned as-is::  Values wrapped in a ``Const()`` are also returned as-is::
   
     >>> map(const_value, map(Const, simple_values))      >>> list(map(const_value, map(Const, simple_values)))
     [1, 2L, 3.0, (5+4j), '6', u'7', False, None, <code object <lambda> ...>]      [1, 2..., 3.0, (5+4j), '6', ...'7', False, None, <code object <lambda>...>]
   
 But no other node types produce constant values; instead, ``NotAConstant`` is  But no other node types produce constant values; instead, ``NotAConstant`` is
 raised::  raised::
Line 1045 
Line 1058 
     >>> const_value(Local('x'))      >>> const_value(Local('x'))
     Traceback (most recent call last):      Traceback (most recent call last):
       ...        ...
     NotAConstant: Local('x')      peak.util.assembler.NotAConstant: Local('x')
   
 Tuples of constants are recursively replaced by constant tuples::  Tuples of constants are recursively replaced by constant tuples::
   
Line 1060 
Line 1073 
     >>> const_value( (1,Global('y')) )      >>> const_value( (1,Global('y')) )
     Traceback (most recent call last):      Traceback (most recent call last):
       ...        ...
     NotAConstant: Global('y')      peak.util.assembler.NotAConstant: Global('y')
   
 As do any types not previously described here::  As do any types not previously described here::
   
     >>> const_value([1,2])      >>> const_value([1,2])
     Traceback (most recent call last):      Traceback (most recent call last):
       ...        ...
     NotAConstant: [1, 2]      peak.util.assembler.NotAConstant: [1, 2]
   
 Unless of course they're wrapped with ``Const``::  Unless of course they're wrapped with ``Const``::
   
Line 1086 
Line 1099 
 ``Const`` node instead of a ``Call`` node::  ``Const`` node instead of a ``Call`` node::
   
     >>> Call( Const(type), [1] )      >>> Call( Const(type), [1] )
     Const(<type 'int'>)      Const(<... 'int'>)
   
 Thus, you can also take the ``const_value()`` of such calls::  Thus, you can also take the ``const_value()`` of such calls::
   
Line 1097 
Line 1110 
 passed in to another ``Call``::  passed in to another ``Call``::
   
     >>> Call(Const(type), [Call( Const(dict), [], [('x',27)] )])      >>> Call(Const(type), [Call( Const(dict), [], [('x',27)] )])
     Const(<type 'dict'>)      Const(<... 'dict'>)
   
 Notice that this folding takes place eagerly, during AST construction.  If you  Notice that this folding takes place eagerly, during AST construction.  If you
 want to implement delayed folding after constant propagation or variable  want to implement delayed folding after constant propagation or variable
Line 1111 
Line 1124 
     >>> c = Code()      >>> c = Code()
     >>> c( Call(Const(type), [1]) )      >>> c( Call(Const(type), [1]) )
     >>> dis(c.code())      >>> dis(c.code())
       0           0 LOAD_CONST               1 (<type 'int'>)        0           0 LOAD_CONST               1 (<... 'int'>)
   
     >>> c = Code()      >>> c = Code()
     >>> c( Call(Const(type), [1], fold=False) )      >>> c( Call(Const(type), [1], fold=False) )
     >>> dis(c.code())      >>> dis(c.code())
       0           0 LOAD_CONST               1 (<type 'type'>)        0           0 LOAD_CONST               1 (<... 'type'>)
                   3 LOAD_CONST               2 (1)                    3 LOAD_CONST               2 (1)
                   6 CALL_FUNCTION            1                    6 CALL_FUNCTION            1
   
Line 1387 
Line 1400 
     >>> Getattr = nodetype()(Getattr)      >>> Getattr = nodetype()(Getattr)
   
     >>> const_value(Getattr(1, '__class__'))      >>> const_value(Getattr(1, '__class__'))
     <type 'int'>      <... 'int'>
   
 The ``fold_args()`` function tries to evaluate the node immediately, if all of  The ``fold_args()`` function tries to evaluate the node immediately, if all of
 its arguments are constants, by creating a temporary ``Code`` object, and  its arguments are constants, by creating a temporary ``Code`` object, and
Line 1422 
Line 1435 
     ...     pass      ...     pass
   
     >>> c = Code.from_function(f1)      >>> c = Code.from_function(f1)
     >>> f2 = new.function(c.code(), globals())      >>> f2 = function(c.code(), globals())
   
     >>> import inspect      >>> import inspect
   
Line 1451 
Line 1464 
     >>> def f3(a, (b,c), (d,(e,f))):      >>> def f3(a, (b,c), (d,(e,f))):
     ...     pass      ...     pass
   
     >>> f4 = new.function(Code.from_function(f3).code(), globals())      >>> f4 = function(Code.from_function(f3).code(), globals())
     >>> dis(f4)      >>> dis(f4)
       0           0 LOAD_FAST                1 (.1)        0           0 LOAD_FAST                1 (.1)
                   3 UNPACK_SEQUENCE          2                    3 UNPACK_SEQUENCE          2
Line 1509 
Line 1522 
     >>> c.LOAD_CONST(42)      >>> c.LOAD_CONST(42)
     >>> c.RETURN_VALUE()      >>> c.RETURN_VALUE()
   
     >>> f = new.function(c.code(), globals())      >>> f = function(c.code(), globals())
     >>> f(1,2,3)      >>> f(1,2,3)
     42      42
   
Line 1645 
Line 1658 
   
     >>> c = Code()      >>> c = Code()
     >>> fwd = c.JUMP_FORWARD()      >>> fwd = c.JUMP_FORWARD()
     >>> print c.stack_size  # forward jump marks stack size as unknown      >>> print(c.stack_size)  # forward jump marks stack size as unknown
     None      None
   
     >>> c.LOAD_CONST(42)      >>> c.LOAD_CONST(42)
Line 1871 
Line 1884 
                     POP_BLOCK                      POP_BLOCK
                     JUMP_FORWARD            L4                      JUMP_FORWARD            L4
             L1:     DUP_TOP              L1:     DUP_TOP
                     LOAD_CONST               2 (<...exceptions.KeyError...>)                      LOAD_CONST               2 (<...KeyError...>)
                     COMPARE_OP              10 (exception match)                      COMPARE_OP              10 (exception match)
                     JUMP_IF_FALSE           L2                      JUMP_IF_FALSE           L2
                     POP_TOP                      POP_TOP
                     POP_TOP                      POP_TOP
                     POP_TOP                      POP_TOP
                     POP_TOP                      POP_TOP...
                     LOAD_CONST               3 (2)                      LOAD_CONST               3 (2)
                     JUMP_FORWARD            L5                      JUMP_FORWARD            L5
             L2:     POP_TOP              L2:     POP_TOP
                     DUP_TOP                      DUP_TOP
                     LOAD_CONST               4 (<...exceptions.TypeError...>)                      LOAD_CONST               4 (<...TypeError...>)
                     COMPARE_OP              10 (exception match)                      COMPARE_OP              10 (exception match)
                     JUMP_IF_FALSE           L3                      JUMP_IF_FALSE           L3
                     POP_TOP                      POP_TOP
                     POP_TOP                      POP_TOP
                     POP_TOP                      POP_TOP
                     POP_TOP                      POP_TOP...
                     LOAD_CONST               5 (3)                      LOAD_CONST               5 (3)
                     JUMP_FORWARD            L5                      JUMP_FORWARD            L5
             L3:     POP_TOP              L3:     POP_TOP
Line 2067 
Line 2080 
 clause, and a loop body::  clause, and a loop body::
   
     >>> from peak.util.assembler import For      >>> from peak.util.assembler import For
     >>> y = Call(Const(range), (3,))      >>> y = Call(Const(list), (Call(Const(range), (3,)),))
     >>> x = LocalAssign('x')      >>> x = LocalAssign('x')
     >>> body = Suite([Local('x'), Code.PRINT_EXPR])      >>> body = Suite([Local('x'), Code.PRINT_EXPR])
   
Line 2283 
Line 2296 
     >>> c.return_(Function(Return(Local('a')), 'f', ['a'], defaults=[42]))      >>> c.return_(Function(Return(Local('a')), 'f', ['a'], defaults=[42]))
     >>> dis(c.code())      >>> dis(c.code())
       0           0 LOAD_CONST               1 (42)        0           0 LOAD_CONST               1 (42)
                   3 LOAD_CONST               2 (<... f ..., file "<string>", line -1>)                    3 LOAD_CONST               2 (<... f..., file ...<string>..., line ...>)
                   6 MAKE_FUNCTION            1                    6 MAKE_FUNCTION            1
                   9 RETURN_VALUE                    9 RETURN_VALUE
   
Line 2314 
Line 2327 
     >>> dis(c.code())      >>> dis(c.code())
       0           0 LOAD_CONST               1 (99)        0           0 LOAD_CONST               1 (99)
                   3 LOAD_CONST               2 (66)                    3 LOAD_CONST               2 (66)
                   6 LOAD_CONST               3 (<... f ..., file "<string>", line -1>)                    6 LOAD_CONST               3 (<... f..., file ...<string>..., line ...>)
                   9 MAKE_FUNCTION            2                    9 MAKE_FUNCTION            2
                  12 RETURN_VALUE                   12 RETURN_VALUE
   
Line 2327 
Line 2340 
   
     >>> dis(f)      >>> dis(f)
       0           0 LOAD_CLOSURE             0 (a)        0           0 LOAD_CLOSURE             0 (a)
                   ... LOAD_CONST               1 (<... <lambda> ..., file "<string>", line -1>)                    ... LOAD_CONST               1 (<... <lambda>..., file ...<string>..., line ...>)
                   ... MAKE_CLOSURE             0                    ... MAKE_CLOSURE             0
                   ... RETURN_VALUE                    ... RETURN_VALUE
   
Line 2669 
Line 2682 
     >>> c.stack_size      >>> c.stack_size
     0      0
     >>> if sys.version>='2.7':      >>> if sys.version>='2.7':
     ...     print c.stack_history == [0, 1, 1, 1,    0, 0, 0, None, None, 1]      ...     print(c.stack_history == [0, 1, 1, 1,    0, 0, 0, None, None, 1])
     ... else:      ... else:
     ...     print c.stack_history == [0, 1, 1, 1, 1, 1, 1, 0, None, None, 1]      ...     print(c.stack_history == [0, 1, 1, 1, 1, 1, 1, 0, None, None, 1])
     True      True
   
   
Line 2967 
Line 2980 
     >>> c = Code()      >>> c = Code()
     >>> c.return_(Call(Const(type), [], [], (1,)))      >>> c.return_(Call(Const(type), [], [], (1,)))
     >>> dis(c.code())      >>> dis(c.code())
       0           0 LOAD_CONST               1 (<type 'int'>)        0           0 LOAD_CONST               1 (<... 'int'>)
                   3 RETURN_VALUE                    3 RETURN_VALUE
   
   
Line 2997 
Line 3010 
                     POP_BLOCK                      POP_BLOCK
                     JUMP_FORWARD            L3                      JUMP_FORWARD            L3
             L1:     DUP_TOP              L1:     DUP_TOP
                     LOAD_CONST               1 (<...exceptions.AttributeError...>)                      LOAD_CONST               1 (<...AttributeError...>)
                     COMPARE_OP              10 (exception match)                      COMPARE_OP              10 (exception match)
                     JUMP_IF_FALSE           L2                      JUMP_IF_FALSE           L2
                     POP_TOP                      POP_TOP
                     POP_TOP                      POP_TOP
                     POP_TOP                      POP_TOP
                     POP_TOP                      POP_TOP...
                     LOAD_CONST               2 (<type 'type'>)                      LOAD_CONST               2 (<... 'type'>)
                     ROT_TWO                      ROT_TWO
                     CALL_FUNCTION            1                      CALL_FUNCTION            1
                     JUMP_FORWARD            L3                      JUMP_FORWARD            L3
Line 3012 
Line 3025 
                     END_FINALLY                      END_FINALLY
             L3:     RETURN_VALUE              L3:     RETURN_VALUE
   
     >>> type_or_class.func_code = c.code()      >>> type_or_class.__code__ = type_or_class.func_code = c.code()
     >>> type_or_class(23)      >>> type_or_class(23)
     <type 'int'>      <... 'int'>
   
   
   
Line 3069 
Line 3082 
     >>> c(Switch(Local('x'), [(1,Return(42)),(2,Return("foo"))], Return(27)))      >>> c(Switch(Local('x'), [(1,Return(42)),(2,Return("foo"))], Return(27)))
     >>> c.return_()      >>> c.return_()
   
     >>> f = new.function(c.code(), globals())      >>> f = function(c.code(), globals())
     >>> f(1)      >>> f(1)
     42      42
     >>> f(2)      >>> f(2)
Line 3079 
Line 3092 
   
     >>> dump(c.code())      >>> dump(c.code())
                     SETUP_LOOP              L2                      SETUP_LOOP              L2
                     LOAD_CONST               1 (<...method get of dict...>)                      LOAD_CONST               1 (<...method ...get of ...>)
                     LOAD_FAST                0 (x)                      LOAD_FAST                0 (x)
                     CALL_FUNCTION            1                      CALL_FUNCTION            1
                     JUMP_IF_FALSE           L1                      JUMP_IF_FALSE           L1
Line 3107 
Line 3120 
 * Exhaustive tests of all opcodes' stack history effects  * Exhaustive tests of all opcodes' stack history effects
   
 * Test wide jumps and wide argument generation in general  * Test wide jumps and wide argument generation in general
   
   * Remove/renumber local variables when a local is converted to free/cell
   


Generate output suitable for use with a patch program
Legend:
Removed from v.2631  
changed lines
  Added in v.2768

cvs-admin@eby-sarna.com

Powered by ViewCVS 1.0-dev

ViewCVS and CVS Help