[RFC] [Vote] Short Ternary Assignment Operator

php.internals

Sara Golemon

10 years ago
Following on from Midori, I've moved the short-ternary assignment operator RFC into voting phase. The implementation for which will be her patch with appropriately different symbols and tests. https://wiki.php.net/rfc/short_ternary_equal_operator -Sara

Ryan Pallas

10 years ago
On Thu, Mar 24, 2016 at 9:51 AM, Sara Golemon <pollita@php.net> wrote:
> Following on from Midori, I've moved the short-ternary assignment > operator RFC into voting phase. > The implementation for which will be her patch with appropriately > different symbols and tests. > https://wiki.php.net/rfc/short_ternary_equal_operator
I like this as well, +1 for me :) Good luck, hope to see it in 7.1!

Nikita Popov

10 years ago
On Thu, Mar 24, 2016 at 4:51 PM, Sara Golemon <pollita@php.net> wrote:
> Following on from Midori, I've moved the short-ternary assignment > operator RFC into voting phase. > The implementation for which will be her patch with appropriately > different symbols and tests. > https://wiki.php.net/rfc/short_ternary_equal_operator >
To clarify, as the RFC only mentions this by implication: unset($x); // Assume $x is undefined $x ?:= $y; This will throw a notice, correct? Thanks, Nikita

Sara Golemon

10 years ago
On Thu, Mar 24, 2016 at 9:45 AM, Nikita Popov <nikita.ppv@gmail.com> wrote:
> To clarify, as the RFC only mentions this by implication: > > unset($x); // Assume $x is undefined > $x ?:= $y; > > This will throw a notice, correct? >
Yes. The equivalent short-ternary: $x = $x ?: $y; would throw a notice, so the assignment version should (and would) as well.

Sara Golemon

10 years ago
After some discussion (and realizing the referenced implementation needed more work that a simple replacement of tokens), I've decided the close this vote, work with Midori on both implementations some more, and reopen at a later time with a complete implementation (possibly combined with ??=) On Thu, Mar 24, 2016 at 8:51 AM, Sara Golemon <pollita@php.net> wrote:

Sara Golemon

10 years ago
On Thu, Mar 24, 2016 at 11:12 AM, Sara Golemon <pollita@php.net> wrote:
> After some discussion (and realizing the referenced implementation > needed more work that a simple replacement of tokens), I've decided > the close this vote, work with Midori on both implementations some > more, and reopen at a later time with a complete implementation > (possibly combined with ??=) >
https://github.com/php/php-src/compare/master...sgolemon:short-ternary.coalesce I've gone from scratch to implement this branch which doesn't introduce any new opcodes, but it does add a new AST kind which is compiled into something closely (but not quite) resembling a regular short ternary. It cheats slightly by assuming that since child[0] comes from a `variable` in the parser that zend_compile_var() on it will always yield IS_CV/IS_VAR, and I've got an assert in to guard on that, but a second set of eyes would be nice there. You'll notice there's a new runtime check in ZEND_JMP_SET to handle the IS_INDIRECT case (which I see resulting from the dim/obj paths. It's hidden behind an existing check for IS_VAR/IS_CV, so anything producing a TMP won't hit it. Hopefully it's not too harsh. Based on feedback, I hope to add the ??= version of this implementation as another commit and let Midori unify the two RFCs into one. (unless someone objects to that) -Sara

Nikita Popov

10 years ago
On Fri, Mar 25, 2016 at 4:25 AM, Sara Golemon <pollita@php.net> wrote:
> On Thu, Mar 24, 2016 at 11:12 AM, Sara Golemon <pollita@php.net> wrote: > > After some discussion (and realizing the referenced implementation > > needed more work that a simple replacement of tokens), I've decided > > the close this vote, work with Midori on both implementations some > > more, and reopen at a later time with a complete implementation > > (possibly combined with ??=) > > > > https://github.com/php/php-src/compare/master...sgolemon:short-ternary.coalesce > > I've gone from scratch to implement this branch which doesn't > introduce any new opcodes, but it does add a new AST kind which is > compiled into something closely (but not quite) resembling a regular > short ternary. > > It cheats slightly by assuming that since child[0] comes from a > `variable` in the parser that zend_compile_var() on it will always > yield IS_CV/IS_VAR, and I've got an assert in to guard on that, but a > second set of eyes would be nice there. > > You'll notice there's a new runtime check in ZEND_JMP_SET to handle > the IS_INDIRECT case (which I see resulting from the dim/obj paths. > It's hidden behind an existing check for IS_VAR/IS_CV, so anything > producing a TMP won't hit it. Hopefully it's not too harsh. > > Based on feedback, I hope to add the ??= version of this > implementation as another commit and let Midori unify the two RFCs > into one. (unless someone objects to that) >
I don't think the current implementation is entirely correct. In particular, it doesn't look memory-safe to me. You're doing an RW fetch on the LHS first, then evaluate the RHS expression and then ASSIGN to the result of the RW fetch. This means you're running user code between the RW fetch and the assignment to it. The code of the RHS expression may cause a reallocation of the buffer into which the INDIRECT points, making it a dangling pointer. Something like $a = [false]; $a[0] ?:= ($a[''] = 42); will probably result in valgrinds. Nikita

Sara Golemon

10 years ago
On Fri, Mar 25, 2016 at 6:44 AM, Nikita Popov <nikita.ppv@gmail.com> wrote:
> I don't think the current implementation is entirely correct. In particular, > it doesn't look memory-safe to me. You're doing an RW fetch on the LHS > first, then evaluate the RHS expression and then ASSIGN to the result of the > RW fetch. This means you're running user code between the RW fetch and the > assignment to it. The code of the RHS expression may cause a reallocation of > the buffer into which the INDIRECT points, making it a dangling pointer. > > Something like > > $a = [false]; > $a[0] ?:= ($a[''] = 42); > > will probably result in valgrinds. >
Ah, good call. Back to the drawing board. :) -Sara

Sara Golemon

10 years ago
Took me awhile to get back around to this problem, but this version feels okay. https://github.com/php/php-src/compare/master...sgolemon:short-ternary.coalesce It's less efficient than earlier versions, but no worse than the current `A = A ?: B` syntax (which is effectively what it does, with the twist of doing a RW fetch instead of an R fetch, and thus resolving the unwanted notices). -Sara