Keys are yielded using the
yield $key => $value
syntax. Currently this is implemented as a statement only and not as an
expression, because conflicts arise considering nesting and use in arrays:
yield yield $a => $b;
// could be either
yield (yield $a) => $b;
// or
yield (yield $a => $b);
Once I find some way to resolve these conflicts this should be available
as an expression too.
Also the key yielding code is rather copy-and-past-y for the value yielding
code, so that should be factored out.
If the generator is used as a coroutine it often doesn't make sense to yield
anything. In this case one can simply receive values using
$value = yield;
The yield here will simply yield NULL.
Yield now is an expression and the return value is the value passed to
$generator->send(). By default (i.e. if ->next() is called) the value is
NULL.
Unlike in Python ->send() can be run without priming the generator with a
->next() call first.
For generators ZEND_RETURN directly calls ZEND_VM_RETURN(), thus passing
execution back to the caller (zend_generator_resume).
This commit also adds a check that only return; is used in generators and
not return $value;.
* pull-request/54:
Allow arbitrary expressions for empty()
This change is as per RFC https://wiki.php.net/rfc/empty_isset_exprs.
The change allows passing the result of function calls and other
expressions to the empty() language construct. This is accomplished by
simply rewriting empty(expr) to !expr.
The change does not affect the suppression of errors when using empty()
on variables. empty($undefinedVar) will continue not to throw errors.
When an expression is used inside empty() on the other hand, errors will
not be suppressed. Thus empty($undefinedVar + $somethingElse) *will*
throw a notice.
The change also does not make empty() into a real function, so using
'empty' as a callback is still not possible.
In addition to the empty() changes the commit adds nicer error messages
when isset() is used on function call results or other expressions.
Generator functions have to specify the * (asterix) modifier after the
function keyword. If they do so the ZEND_ACC_GENERATOR flag is added to
the fn_flags.
This change is as per RFC https://wiki.php.net/rfc/empty_isset_exprs.
The change allows passing the result of function calls and other
expressions to the empty() language construct. This is accomplished by
simply rewriting empty(expr) to !expr.
The change does not affect the suppression of errors when using empty()
on variables. empty($undefinedVar) will continue not to throw errors.
When an expression is used inside empty() on the other hand, errors will
not be suppressed. Thus empty($undefinedVar + $somethingElse) *will*
throw a notice.
The change also does not make empty() into a real function, so using
'empty' as a callback is still not possible.
In addition to the empty() changes the commit adds nicer error messages
when isset() is used on function call results or other expressions.
This fixes bug #60097.
Before two global variables CG(heredoc) and CG(heredoc_len) were used to
track the current heredoc label. In order to support nested heredoc
strings the *previous* heredoc label was assigned as the token value of
T_START_HEREDOC and the language_parser.y assigned that to CG(heredoc).
This created a dependency of the lexer on the parser. Thus the
token_get_all() function, which accesses the lexer directly without
also running the parser, was not able to tokenize nested heredoc strings
(and leaked memory). Same applies for the source-code highlighting
functions.
The new approach is to maintain a heredoc_label_stack in the lexer, which
contains all active heredoc labels.
As it is no longer required, T_START_HEREDOC and T_END_HEREDOC now don't
carry a token value anymore.
In order to make the work with zend_ptr_stack in this context more
convenient I added a new function zend_ptr_stack_top(), which retrieves the
top element of the stack (similar to zend_stack_top()).
Re-Fixed bug #60536 (Traits Segfault)
#Thanks to tony2001, I found the previous fix -r321089 is actually not a correct one.
#The key problem there is because the traits didn't correct set the property_info.offset
#for private properties. so here come the new fix.
Re-Fixed bug #60536 (Traits Segfault)
#Thanks to tony2001, I found the previous fix -r321089 is actually not a correct one.
#The key problem there is because the traits didn't correct set the property_info.offset
#for private properties. so here come the new fix.
# The handling of private properties in classes is now consistent with private properties in traits.
# Perviously, privates could cause strict warnings, are were not properly merged into the class when
# the parent class had a private property of the same name. Now, we introduce it without notice,
# since it is a new and independent property, just like in normal classes.
# This problem was diagnosed while working on Bug #60536.
# The handling of private properties in classes is now consistent with private properties in traits.
# Perviously, privates could cause strict warnings, are were not properly merged into the class when
# the parent class had a private property of the same name. Now, we introduce it without notice,
# since it is a new and independent property, just like in normal classes.
# This problem was diagnosed while working on Bug #60536.