[Subversion] / BytecodeAssembler / peak / util / assembler.txt  

Diff of /BytecodeAssembler/peak/util/assembler.txt

Parent Directory | Revision Log

version 2139, Tue May 23 05:28:31 2006 UTC version 2160, Sun May 28 22:38:22 2006 UTC
Line 2 
Line 2 
 Generating Python Bytecode with ``peak.util.assembler``  Generating Python Bytecode with ``peak.util.assembler``
 =======================================================  =======================================================
   
   --------------
   Programmer API
   --------------
   
   Opcode API
   ==========
   
   
 Simple usage::  Simple usage::
   
     >>> from peak.util.assembler import Code      >>> from peak.util.assembler import Code
     >>> c = Code()      >>> c = Code()
       >>> c.set_lineno(15)   # set the current line number (optional)
     >>> c.LOAD_CONST(42)      >>> c.LOAD_CONST(42)
       >>> c.set_lineno(16)   # set it as many times as you like
     >>> c.RETURN_VALUE()      >>> c.RETURN_VALUE()
   
     >>> eval(c.code())      >>> eval(c.code())
Line 14 
Line 24 
   
     >>> from dis import dis      >>> from dis import dis
     >>> dis(c.code())      >>> dis(c.code())
       0           0 LOAD_CONST               0 (42)        15          0 LOAD_CONST               1 (42)
                   3 RETURN_VALUE        16          3 RETURN_VALUE
   
   Labels and backpatching forward references::
   
       >>> c = Code()
       >>> ref = c.JUMP_ABSOLUTE()     # jump w/unspecified target
       >>> c.LOAD_CONST(1)
       >>> ref()                       # resolve the forward reference
       >>> c.RETURN_VALUE()
       >>> dis(c.code())
         0           0 JUMP_ABSOLUTE            6
                     3 LOAD_CONST               1 (1)
               >>    6 RETURN_VALUE
   
   
       >>> c = Code()
       >>> lbl = c.label()     # create a label at this point in the code
       >>> c.LOAD_CONST(1)
       >>> ref = c.JUMP_ABSOLUTE(lbl)  # and jump to it
       >>> dis(c.code())
         0     >>    0 LOAD_CONST               1 (1)
                     3 JUMP_ABSOLUTE            0
   
   
   Code Generation API
   ===================
   
   Code generation from tuples, lists, dicts, and local variable names::
   
       >>> c = Code()
       >>> c( ['x', ('y','z')] )   # push a value on the stack
       >>> dis(c.code())
         0           0 LOAD_FAST                0 (x)
                     3 LOAD_FAST                1 (y)
                     6 LOAD_FAST                2 (z)
                     9 BUILD_TUPLE              2
                    12 BUILD_LIST               2
   
   And with constants, dictionaries, globals, and calls::
   
       >>> from peak.util.assembler import Const, Call, Global
   
       >>> c = Code()
       >>> c.Return( [Global('type'), Const(27)] )     # push and RETURN_VALUE
       >>> dis(c.code())
         0           0 LOAD_GLOBAL              0 (type)
                     3 LOAD_CONST               1 (27)
                     6 BUILD_LIST               2
                     9 RETURN_VALUE
   
       >>> c = Code()
       >>> c( {Const('x'): Const(123)} )
       >>> dis(c.code())
         0           0 BUILD_MAP                0
                     3 DUP_TOP
                     4 LOAD_CONST               1 ('x')
                     7 LOAD_CONST               2 (123)
                    10 ROT_THREE
                    11 STORE_SUBSCR
   
       >>> c = Code()
       >>> c(Call(Global('type'), (Const(1),)))
       >>> dis(c.code())
         0           0 LOAD_GLOBAL              0 (type)
                     3 LOAD_CONST               1 (1)
                     6 CALL_FUNCTION            1
   
       >>> c = Code()
       >>> c(Call(Global('getattr'), (Const(1), Const('__class__'))))
       >>> dis(c.code())
         0           0 LOAD_GLOBAL              0 (getattr)
                     3 LOAD_CONST               1 (1)
                     6 LOAD_CONST               2 ('__class__')
                     9 CALL_FUNCTION            2
   
   ``Call`` objects take 1-4 arguments: the expression to be called, a sequence
   of positional arguments, a sequence of keyword/value pairs for explicit keyword
   arguments, an "*" argument, and a "**" argument.  To omit any of the optional
   arguments, just pass in an empty sequence in its place::
   
       >>> c = Code()
       >>> c.Return(
       ...     Call(Global('foo'), ['q'], [('x',Const(1))], 'starargs', 'kwargs')
       ... )
       >>> dis(c.code())
         0           0 LOAD_GLOBAL              0 (foo)
                     3 LOAD_FAST                0 (q)
                     6 LOAD_CONST               1 ('x')
                     9 LOAD_CONST               2 (1)
                    12 LOAD_FAST                1 (starargs)
                    15 LOAD_FAST                2 (kwargs)
                    18 CALL_FUNCTION_VAR_KW   257
                    21 RETURN_VALUE
   
   Code generation is extensible: any 1-argument callables passed in will
   be passed the code object during generation.  (The return value, if any, is
   ignored.)  You can even use ``Code`` methods, if they don't have any required
   arguments::
   
       >>> c = Code()
       >>> c.LOAD_GLOBAL('foo')
       >>> c(Call(Code.DUP_TOP, ()))
       >>> dis(c.code())
         0           0 LOAD_GLOBAL              0 (foo)
                     3 DUP_TOP
                     4 CALL_FUNCTION            0
   
   This basically means you can create an AST of callable objects to drive code
   generation, with a lot of the grunt work automatically handled for you.
   
   
   ---------
   Internals
   ---------
   
 Line number tracking::  Line number tracking::
   
Line 124 
Line 247 
                   3 CALL_FUNCTION            0                    3 CALL_FUNCTION            0
                   6 POP_TOP                    6 POP_TOP
                   7 LOAD_GLOBAL              1 (foo)                    7 LOAD_GLOBAL              1 (foo)
                  10 LOAD_CONST               0 (1)                   10 LOAD_CONST               1 (1)
                  13 LOAD_CONST               1 ('x')                   13 LOAD_CONST               2 ('x')
                  16 LOAD_CONST               2 (2)                   16 LOAD_CONST               3 (2)
                  19 CALL_FUNCTION          257                   19 CALL_FUNCTION          257
                  22 POP_TOP                   22 POP_TOP
   
Line 177 
Line 300 
   
     >>> dis(c.code())      >>> dis(c.code())
       0           0 RAISE_VARARGS            0        0           0 RAISE_VARARGS            0
                   3 LOAD_CONST               0 (1)                    3 LOAD_CONST               1 (1)
                   6 RAISE_VARARGS            1                    6 RAISE_VARARGS            1
   
 Sequence building, unpacking, dup'ing::  Sequence building, unpacking, dup'ing::
Line 227 
Line 350 
     AssertionError: Stack underflow      AssertionError: Stack underflow
   
     >>> dis(c.code())      >>> dis(c.code())
       0           0 LOAD_CONST               0 (1)        0           0 LOAD_CONST               1 (1)
                   3 LOAD_CONST               1 (2)                    3 LOAD_CONST               2 (2)
                   6 BUILD_TUPLE              2                    6 BUILD_TUPLE              2
                   9 UNPACK_SEQUENCE          2                    9 UNPACK_SEQUENCE          2
                  12 DUP_TOPX                 2                   12 DUP_TOPX                 2
                  15 LOAD_CONST               2 (3)                   15 LOAD_CONST               3 (3)
                  18 BUILD_LIST               5                   18 BUILD_LIST               5
                  21 UNPACK_SEQUENCE          5                   21 UNPACK_SEQUENCE          5
                  24 BUILD_SLICE              3                   24 BUILD_SLICE              3
Line 250 
Line 373 
     >>> c.RETURN_VALUE()      >>> c.RETURN_VALUE()
     >>> dis(c.code())      >>> dis(c.code())
       0           0 JUMP_ABSOLUTE            6        0           0 JUMP_ABSOLUTE            6
                   3 LOAD_CONST               0 (1)                    3 LOAD_CONST               1 (1)
             >>    6 RETURN_VALUE              >>    6 RETURN_VALUE
   
     >>> c = Code()      >>> c = Code()
Line 260 
Line 383 
     >>> c.RETURN_VALUE()      >>> c.RETURN_VALUE()
     >>> dis(c.code())      >>> dis(c.code())
       0           0 JUMP_FORWARD             3 (to 6)        0           0 JUMP_FORWARD             3 (to 6)
                   3 LOAD_CONST               0 (1)                    3 LOAD_CONST               1 (1)
             >>    6 RETURN_VALUE              >>    6 RETURN_VALUE
   
     >>> c = Code()      >>> c = Code()
Line 276 
Line 399 
     >>> c.LOAD_CONST(1)      >>> c.LOAD_CONST(1)
     >>> ref = c.JUMP_ABSOLUTE(lbl)      >>> ref = c.JUMP_ABSOLUTE(lbl)
     >>> dis(c.code())      >>> dis(c.code())
       0     >>    0 LOAD_CONST               0 (1)        0     >>    0 LOAD_CONST               1 (1)
                   3 JUMP_ABSOLUTE            0                    3 JUMP_ABSOLUTE            0
   
   
   "Call" combinations::
   
   
       >>> c = Code()
       >>> c.set_lineno(1)
       >>> c(Call(Global('foo'), ['q'], [('x',Const(1))], 'starargs'))
       >>> c.RETURN_VALUE()
       >>> dis(c.code())
         1           0 LOAD_GLOBAL              0 (foo)
                     3 LOAD_FAST                0 (q)
                     6 LOAD_CONST               1 ('x')
                     9 LOAD_CONST               2 (1)
                    12 LOAD_FAST                1 (starargs)
                    15 CALL_FUNCTION_VAR      257
                    18 RETURN_VALUE
   
   
       >>> c = Code()
       >>> c.set_lineno(1)
       >>> c(Call(Global('foo'), ['q'], [('x',Const(1))], None, 'kwargs'))
       >>> c.RETURN_VALUE()
       >>> dis(c.code())
         1           0 LOAD_GLOBAL              0 (foo)
                     3 LOAD_FAST                0 (q)
                     6 LOAD_CONST               1 ('x')
                     9 LOAD_CONST               2 (1)
                    12 LOAD_FAST                1 (kwargs)
                    15 CALL_FUNCTION_KW       257
                    18 RETURN_VALUE
   
   
   Cloning::
   
       >>> c = Code.from_function(lambda (x,y):1, True)
       >>> dis(c.code())
         1           0 LOAD_FAST                0 (.0)
                     3 UNPACK_SEQUENCE          2
                     6 STORE_FAST               1 (x)
                     9 STORE_FAST               2 (y)
   
       >>> c = Code.from_function(lambda x,(y,(z,a,b)):1, True)
       >>> dis(c.code())
         1           0 LOAD_FAST                1 (.1)
                     3 UNPACK_SEQUENCE          2
                     6 STORE_FAST               2 (y)
                     9 UNPACK_SEQUENCE          3
                    12 STORE_FAST               3 (z)
                    15 STORE_FAST               4 (a)
                    18 STORE_FAST               5 (b)
   
   TODO
   ====
   
   * Test free/cell ops (LOAD_CLOSURE, LOAD_DEREF, STORE_DEREF)
   * Test MAKE_FUNCTION/MAKE_CLOSURE
   * Test code flags generation/cloning
   
   
   


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

cvs-admin@eby-sarna.com

Powered by ViewCVS 1.0-dev

ViewCVS and CVS Help