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