Advertisement
Guest User

the better tailcall-optimizer for python 2.7 by mokrates

a guest
Feb 22nd, 2012
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.06 KB | None | 0 0
  1. # tail-call-optimizer
  2. # the betterrerer version
  3.  
  4. # no tailcall-marker needed anymore. this finds the tailcall in the bytecode by itself
  5. # (in this example only CALL_FUNCTION, but this can easily extended to
  6. # CALL_FUNCTION_KW, CALL_FUNCTION_VAR and CALL_FUNCTION_KW_VAR
  7.  
  8. # written by mokrates
  9.  
  10. import dis
  11. import new
  12.  
  13. def modify_assembler(codestring):
  14.     codelist = [ord(c) for c in codestring]
  15.    
  16.     # filter CALL_FUNCTION
  17.     for i in xrange(0,len(codelist)-4):
  18.         if (codelist[i] == dis.opmap['CALL_FUNCTION'] and
  19.             codelist[i+3] == dis.opmap['RETURN_VALUE'] ):
  20.             codelist[i] = dis.opmap['BUILD_TUPLE']
  21.             codelist[i+1] = codelist[i+1] + 1
  22.            
  23.     return reduce(str.__add__, ( chr(x) for x in codelist ))
  24.  
  25. def recreate_modified_func(func):
  26.     code_cl = func.func_code.__class__
  27.     function_cl = func.__class__
  28.    
  29.     f=func.func_code
  30.  
  31.     codestring=modify_assembler(f.co_code)
  32.  
  33.     code = new.code(f.co_argcount, f.co_nlocals, f.co_stacksize, f.co_flags, codestring,
  34.         f.co_consts, f.co_names,
  35.             f.co_varnames, f.co_filename, f.co_name, f.co_firstlineno, f.co_lnotab)
  36.  
  37.     newfunc = new.function(code, func.func_globals, func.func_name, func.func_defaults, func.func_closure)
  38.  
  39.     return newfunc
  40.  
  41. def tailopt(f):
  42.     def taildecor(*args, **kwargs):
  43.         res = mod_f(*args, **kwargs)
  44.         while (isinstance(res, tuple) and
  45.             len(res) > 0 and
  46.             callable(res[0])):
  47.            
  48.             if ('_taildecor_mod_f' in dir(res[0])):
  49.                 res = res[0]._taildecor_mod_f(*res[1:])
  50.             else:
  51.                 return res[0](*res[1:])
  52.  
  53.         return res
  54.  
  55.     mod_f = recreate_modified_func(f)
  56.     taildecor._taildecor_mod_f = mod_f
  57.     return taildecor
  58.  
  59. if __name__ == '__main__':
  60.    
  61.     # example
  62.    
  63.     @tailopt
  64.     def fak(still, acc=1):
  65.         if (still==1): return str(acc)
  66.         else: return fak(still-1, acc * still)
  67.    
  68.     print fak(10000)
  69.  
  70.     # alternating tailcall
  71.  
  72.     @tailopt
  73.     def fak1(still, acc=1):
  74.         if (still==1): return str(acc)
  75.         else: return fak2(still-1, acc * still)
  76.  
  77.     @tailopt
  78.     def fak2(still, acc=1):
  79.         if (still==1): return str(acc)
  80.         else: return fak1(still-1, acc * still)
  81.    
  82.     print fak1(10000)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement