Make behavior consistent with a loop of normal assignments.
This is not a big issue now, because $this is the only case that
may generate an error. However typed references introduce additional
error conditions, which would be silenced by this kind of behavior.
Don't automatically convert literal string keys to integers on
array access, as we may be dealing with an ArrayAccess object,
rather than a plain array.
This fixes the behavior when the storage location of the fetch is
modified before the operand is dereferenced by the using VM opcode.
Furthermore it elimiates references as a possible return value from
*_R opcodes, which will give us more opportunities for inferences,
in particular in regard to typed properties.
I've introduced a new CompileError type, from which ParseError
inherits. These errors are not parse errors in the narrow sense
of the term, even though they happen to be generated during
parsing in our implementation. Additionally reusing the ParseError
class for this purpose would change existing error messages (if
the exception is not caught) from a "Fatal error:" to a "Parse
error:" prefix, and also the error kind from E_COMPILE_ERROR to
E_PARSE.
If op1 is ERROR the behavior is to not perform any assignment and
return NULL. However, if the RHS was a by-value returning function,
we'd instead emit a notice and return the RHS as the return value
(even though the value was not assigned to anything -- the temporary
is immediately destroyed).
This normalized the behavior to always check for an ERROR in op1
first.
This error was already thrown if __get() was used -- however not
if it returned by reference. This is incorrect, because the
reference return makes no difference to a by-reference assignment,
which has reference-breaking semantics. The result was that the
assignment was accepted silently, even though it didn't do anything
(not even the value was assigned, let alone the reference).
Assign-ops and incdec on overloaded properties are implemented
using a read_property followed by write_property. Previously, if
__get() returned by-reference, pre-incdec and assign-op
additionally also modified the reference, while post-incdec worked
correctly.
This change synchronizes the three code-paths to not modify the
reference. The pre-incdec implementation matches the post-incdec
implementation, the assign-op implementation uses a distinct
result operand.
RFC: https://wiki.php.net/rfc/flexible_heredoc_nowdoc_syntaxes
* The ending label no longer has to be followed by a semicolon or
newline. Any non-label character is fine.
* The ending label may be indented. The indentation will be stripped
from all lines in the heredoc/nowdoc string.
Lexing of heredoc strings performs a scan-ahead to determine the
indentation of the ending label, so that the correct amount of
indentation can be removed when calculting the semantic values for
use by the parser. This makes the implementation quite a bit more
complicated than we would like :/
PHP requires boolean typehints to be written "bool" and disallows
"boolean" as an alias. This changes the error messages to match
the actual type name and avoids confusing messages like "must be
of type boolean, boolean given".
This a followup to ce1d69a1f6, which
implements the same change for integer->int.
PHP requires integer typehints to be written "int" and does not
allow "integer" as an alias. This changes type error messages to
match the actual type name and avoids confusing messages like
"must be of the type integer, integer given".