Stefan Behnel wrote: > Hi, > > to fix ticket 124, I tried migrating the for-in loop to new-style temps. > The problem I ran into is that the current support for temp (de-)allocation > in NewTempExprNode during code generation is not enough to get this to > work. Some temps are used longer, some are used shorter than the current > automatic granularity at a node boundary. > > Example: > > for a,b in some_list: > pass > > needs a temp for retrieving the next item, unpacks it into two target > temps, frees the item temp and then assigns them to a and b. The problem is > that we a) pass temps across multiple nodes here, and b) currently generate > separate code paths for the tuple unpacking, so that the item temp disposal > code is also generated twice. That prevents the rhs from just releasing the > temp on a call to generate_disposal_code().
I must admit I need a little help here. At what point is it the new temps differ from the old temps? I'd prefer, if possible, to stay as close as possible to the old scheme when it comes to flow, so that one doesn't have to break everything and build it up again. I.e. try to make NewTempExprNode emulate "whatever it is" pure ExprNode with is_temp==True does. > I think it would be best to keep temp allocation in the code where it needs > to happen, but to make the deallocation explicit and callable from outside. > This means that all nodes would need to call a "free_temps()" method on > their subexpressions when they are done generating code for them. If one decides to change the temp allocation flow altogether, I have another proposal: Get rid of the idea of a "temporary expression node" altogether. The fact that an expression node must itself free its temp (which it cannot possibly itself know how long should be held on to) always struck me as messy. So: - Each node still flags whether it needs a result variable (i.e. the is_temp of today, or rather needs_target as I'll call it from here on). - Before the parent calls subexpr.generate_result_code, it has to check subexpr.needs_target. If True, the parent must call subexpr.set_target(some_cname) - If the parent doesn't have a variable handy to put the result in, it needs to allocate a temp, hand it to the child for it to store its result in, and finally release the temp when the result is no longer needed. If I'm not totally mistaken, this will both be clearer and might have the potential to remove some unecesarry INCREFs/DECREFs that's there today. Example code: a = g(f(), a) would then have this flow: - The NameNode is a lhs, so generate_assignment_code is changed so that its target cname is returned to the SimpleAssignmentNode. - The SimpleAssignmentNode notes that self.rhs.needs_target==True, and so it calls "self.rhs.set_target(lhs_cname)", and recurses into rhs. (where lhs_cname is the variable name of a in C source). - "g", in turn, notices that the call to f() as needs_target. As g's purposes for f() isn't to store it in a variable, but just use the result, g needs to allocate a temporary and call set_target on f. However, for "a" (a NameNode) the needs_target is set to False, so g simply uses the result_code directly. -- Dag Sverre _______________________________________________ Cython-dev mailing list [email protected] http://codespeak.net/mailman/listinfo/cython-dev
