[Cython] Prototype patch for closures/inner functions
Dag Sverre Seljebotn
dagss at student.matnat.uio.no
Wed Apr 9 11:51:13 CEST 2008
Stefan wrote:
> I agree with Robert. As long as Cython does not support closures, for
> example, it cannot come close enough to being a real option for speeding
I couldn't resist the challenge :-)
Attached is a prototype using transforms to add closure support to Cython.
NB! It's not ready for prime-time yet. Unfortunately I must leave it for
some days now, so I post it it prototype state. Mainly so that others
don't start on the same thing (though feel free to take over this, just
give me a note).
I mainly write it to see how it would be like to write a "real"
transform. Which was not too bad...
It is a bit hacky but I think the approach should give correct results.
Known fatal bugs:
- I don't know the first thing about reference counting, CPython etc..
At least on one occasion I messed up GC-ing. This is probably something
that others will be much quicker at spotting.
- No name mangling, inner functions cannot collide in name with outer.
Quick fix but don't have time now; also one might want a more generic
"name mangler" support mechanism rather than just checking for
collisions, not sure about how to do this.
- No consideration for anything nontrivial: The global keyword and
accessing variables in modules comes to mind.
Conscious limitations:
- Only Python def's, not inner cdefs, and all bound vars are bound as
Python objects. This restriction can be removed later (for
optimization), but I think Python-only inner defs should work fine.
Strategy:
- First, run a transform that records used and assigned symbols within a
function (don't know if this is already done anywhere, probably this
might be redundant and done in the scope system? Suggestions?).
- Then, run a transform which lifts out inner functions, and replace
with assignment to a method bound to a tuple containing the variables
that should be bound (apparently this works. But one might create a
specific type containing a tuple as a field as well.)
- The lifted-out functions gets an instruction added first to unpack the
"self" tuple to the correct names (making the names shadowing the outer
scope).
How to run (if you want to help me out or have a look, otherwise don't
bother):
Apply patch.
$ cat <<END > test.pyx
def make_adder(n):
def adder(x):
return x + n
return adder
def timesthree(n):
def util(x):
return x * 2
return n + util(n)
END
$ cat <<END > test.sh
python cython.py \
-Tafter_parse:Cython.Compiler.Transforms.InnerFunctions.FunctionSymbols \
-Tafter_parse:Cython.Compiler.Transforms.InnerFunctions.InnerFunctions \
-Tafter_analyse_function:Cython.Compiler.Transforms.InnerFunctions.MethodTableIndex
\
test.pyx
gcc -Wall -shared -fPIC -I/usr/include/python2.5 -o test.so test.c
END
$ python
>>> import test
>>> a = test.make_adder(20)
>>> b = test.make_adder(10)
>>> a
<built-in method adder of tuple object at 0x2af646ca8910>
>>> a(13)
33
>>> b(13)
23
>>> test.timesthree(100)
300
--
Dag Sverre
-------------- next part --------------
A non-text attachment was scrubbed...
Name: innerfuncs.diff
Type: text/x-patch
Size: 14964 bytes
Desc: not available
Url : http://codespeak.net/pipermail/cython-dev/attachments/20080409/0d8e7126/attachment-0001.bin
More information about the Cython-dev
mailing list