Stefan Behnel wrote:
> Hi,
> 
> Dag Sverre Seljebotn wrote:
>> In making it possible to have runnable code in pxds, I need to make a 
>> choice. The problem is that interned strings, objects etc. live in 
>> seperate scopes and you get double copies, basically now I get the 
>> following code twice in my c-file:
>>
>> static char __pyx_k___getbuffer__[] = "__getbuffer__";
>> static PyObject *__pyx_kp___getbuffer__;
>>
>> which gcc isn't too thrilled about.
>> [...]
>> 2) Move these things from the scopes to code.global (a global context of 
>> the CCodeWriter). This fits nicely with utility_code going over as well. 
>> This means that for now each scope simply pipe their things into code 
>> where they are merged, while in time then e.g. StringNode could intern a 
>> string during code generation rather than bothering with it during 
>> analysis. (I think this is a viable way forward, but may take an hour or 
>> three longer for me to do.)
> 
> Since I previously worked a bit on the string interning code, I think it would
> really benefit from such a change. Please go ahead.

1) OK I've made some changes in this direction:

- BlockNode now forwards the entries it deals with to Code.GlobalState, 
which tries to do the same thing but filters out duplicates (which comes 
from pxds and pyxes doing the same thing). In time, I expect all of 
BlockNode to  vanish.

- Also, the code dealing with interned strings/ints and cached builtins 
from ModuleNode is moved to Code.GlobalState; which uses a different 
strategy: Rather than iterating over the contents of a scope, it simply 
allocates many CodeWriter instances/buffers and outputs initialiazation 
code at the same time as the declaration code, though to a seperate 
buffer. (One can like or not like this I suppose -- only argument I have 
is it tends to keep code more "together" in one location, but the real 
reason is that it was easier this way.)

- Because one cannot have insertion points within functions (would 
create h). Therefore I extracted some things from the module 
initialization function into two more functions, __Pyx_InitGlobals and 
__Pyx_InitCachedBuiltins. I could potentially get rid of this with a 
special "I promise not to use temps or modify labels"-insertion-point, 
but this was easier. (Also, one could argue for it from a design 
viewpoint: c-file globals are more tied to the c-file as such than 
necesarrily the module -- if a single C file were to implement both a 
module and some of its submodules [1], then cached builtins could be 
shared but the module init func would not be!)

This all runs the test cases etc. and I consider it "done" in some 
sense, but I want to have some feedback before I consider it ready for 
merging.

Of course, it represents a transitional solution. In the end, I expect 
one would add something like this:

self.result_code = code.globalcode.py_string_literal("abc")

and so on (details must be discussed when the day comes), but that, as 
my new mantra has become, "is pending a result_code refactoring". But 
the design now allows for creating such a thing, it would all happen 
within Code.py. (I'll get to that some day of course, especially as Greg 
has a lot of it done, but I have my GSoC priorities to worry about).

[1] (Is this possible in Python? What I've done now opens up for Cython 
supporting this (think compiling a dir tree to a single .so) and get 
some degree of sharing constant literals etc., but that's hardly a 
priority.)

2) During writing this, I realized that some code could be written in a 
shorter fashion:

         (self.initwriter
            .putln("return 0;")
          .put_label(self.initwriter.error_label)
            .putln("return -1;")
          .putln("}")
          .exit_cfunc_scope()
          )

...where I've changed some functions to return "self" (much like C++ 
iostreams). Do you like or dislike this? Consider both with and without 
the indendation-matching-the-C-code. It does create some dissymetry 
(see the put_label where you need a new reference to the writer), this 
could be fixed by adding put_error_label, or by going back

The counterargument is that I could say "c = self.initwriter" first 
instead to get almost the same brevity.

Of course, this is only an added option for new code. So inconsistency 
would be added. Still I'm +1/2 because of when doing all the C code I've 
written in Buffer.py I always thought that it tended to become quite 
long-winded to express what I wanted...

(Some code is using this in my branch which I'll redo if the vote is not 
positive.)

3) For buffers, this means that I've manged to strip all NumPy specific 
code from Buffer.py, instead you currently can define __getbuffer__ and 
__releasebuffer__ in numpy.pxd

I have not introduced a generic "final" mechanism or similar; rather an 
exception is introduced specifically for __getbuffer__ and 
__releasebuffer__ and specifically for the purpose of 
Py2.5-GetBuffer-faking. I'd like to leave it like this for now, but it 
will be a "hidden" feature and I will warn people not to rely on it.

In time I see it like this: A "final" language feature is added, and 
anything declared "final" can reside in pxds. But that is not done now, 
hence the special cases for these two functions.

-- 
Dag Sverre
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to