Announcing bytecodehacks 0.10

Christian Tismer tismer at appliedbiometrics.com
Thu May 13 12:01:43 EDT 1999


Great work!

Michael Hudson wrote:

> bytecodehacks.setq - this one should interest people!
> 
> You want assignment expressions? Have them!
> 
> def f(x):
>     while setq(x,x-1):
>         print x
> from bytecodehacks import setq
> g=setq.setqize(f)
> g(4)
> 3
> 2
> 1

I've modified setq a little, since I think setq'ers
always know what they do, I added code to support
setq being the first appearance of the variable.
This means, setq always makes a variable local.

Example:

>>> def f(x):
... 	for i in range(len(x)):
... 	  if setq(c, x[i]) == 3:
... 	    print c, 42
... 	
>>> x=setq2.setqize(f)
load found at index 13
found call
turned first arg c into a local
>>> x(range(10))
3 42

cheers - chris    (setq2.py attached)

-- 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home
-------------- next part --------------
"""
Original version from Michael Hudson.
Modified to turn a setq'd global into a local
by C. Tismer 990513
"""
from bytecodehacks.find_function_call import find_function_call
from bytecodehacks.code_editor import Function
from bytecodehacks.ops import LOAD_FAST, DUP_TOP, STORE_FAST, LOAD_GLOBAL, STORE_GLOBAL

def setqize(func):
    func = Function(func)

    while 1:
        stack = find_function_call(func,"setq")
        
        if stack is None:
            return func.make_function()

        if len(stack) <> 4:
            raise TypeError, "Wrong number of args"

        load_func, load_name, value_load, function_call = stack

        cs = func.func_code.co_code

        cs.remove(load_func)

        var = load_name.arg

        cs.remove(load_name)

        if load_name.__class__ is LOAD_GLOBAL:
            # CT we make this into a local
            name = func.func_code.co_names[var]
            var = global_to_local(func.func_code, name)
            print "turned first arg %s into a local" % name
        elif load_name.__class__ is not LOAD_FAST:
            raise TypeError, "first arg must be a variable!"

        call_index = cs.index(function_call)

        cs[call_index:call_index + 1] = [DUP_TOP(), STORE_FAST(var)]

        return func.make_function()

def global_to_local(code, name):
    """\
internal function to make a global variable into
a local one, for the case that setq is the first
reference to a variable.
Modifies a code object in-place. 
Return value is index into variable table
    """
    cs   = code.co_code

    index = len(code.co_varnames)
    code.co_varnames.append(name)

    for i in range(len(cs)):
        op = cs[i]
        if op.__class__ not in [LOAD_GLOBAL,STORE_GLOBAL]:
            continue
        thisname = code.co_names[op.arg]
        if thisname <> name:
            continue
        if op.__class__ is LOAD_GLOBAL:
            cs[i] = LOAD_FAST(index)
        else:
            cs[i] = STORE_FAST(index)
    return index
    


More information about the Python-list mailing list