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