Stefan Behnel wrote:
> Dag Sverre Seljebotn wrote:
>> A way to get around this would be to split generate_result_code. So 
>> mainly my proposal, but with this modification:
>>
>> self.subexpr.preparation_code(code)
>> tmp = code.funcstate.allocate_temp(...)
>> self.subexpr.store_result_code(tmp, code)
> 
> That's something I thought about, too. Most of the time, within an
> expression, all you really want is to say "do whatever it takes to
> calculate the result, and then put it *here*", where 'here' may be a temp
> or a name.
> 
> How would the DECREF handling work for the target in that case? If it's a
> temp, I'd expect it to be empty in any case, but if it's a variable name,
> it needs a DECREF-after-INCREF. Or would the parent always hand in a temp
> and always handle variables itself?
> 
> If we call this directly, we could also pass keyword arguments like
> "target_needs_decref" and "make_owned_reference".

I don't like those keywords as such, responsibility should be in parent. 
I think a can_raise_exception flag on the node gets us a long way.

I'll have to give another example to explain what I'm thinking. Let the 
code be:

a = b + (c + d)

(Currently SingleAssignmentNode evaluates rhs and then calls 
lhs.generate_assignment_code, I'd change that so that 
lhs.generate_assignment_code is responsible for evaluating the rhs.)

Then, when assigning to the lhs NameNode:

def generate_assignment_code(self, rhs, code):
     if not rhs.can_raise_exception:
         # No temp needed
         if self.type.is_pyobject:
             code.put_decref(self.cname, self.type)
         rhs.preparation_code(code)
         rhs.store_result_code(self.cname, code)
         # CONTRACT: store_result_code gives away reference on "result"
     else:
         # If exception is raised, value shouldn't be overwritten

         rhs.preparation_code(code)
         # Above causes rhs to allocate a tmp for the second operand
         # and fully evaluate "tmp1 = c + d". I.e both preparation_code
         # and store_result_code of "c+d" is done now, allowing
         # temps of nested expressions to be reused below.

         tmp = code.funcstate.allocate_temp(...) # returns "tmp2"
         rhs.store_result_code(tmp, code)
         # Above causes rhs to first calculate "tmp2 = b + tmp1",
         # then decref the tmp1 claimed during preparation_code

         code.put_decref(self.cname, self.type)
         code.putln("%s = %s; %s = 0" % (self.cname, tmp, tmp))
         code.funcstate.release_temp(...)


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

Reply via email to