Closed thekid closed 3 years ago
Test all this with a PHP 8.1 version with [...enum support...]
Obviously, since Enum
is now a reserved word, one cannot declare a class with that. This breaks lang.Enum
.
# Patch & compile
thekid@Surface:~/bin/php$ curl https://patch-diff.githubusercontent.com/raw/php/php-src/pull/6489.patch | patch -p1
thekid@Surface:~/bin/php$ make clean && ./buildconf && ./config.nice && make
# ...
# Verify enum support is available
thekid@Surface:~/bin/php$ ./sapi/cli/php -r 'enum SortOrder { case ASC; case DESC; } var_dump(SortOrder::ASC);'
enum(SortOrder::ASC)
# Run tests
thekid@Surface:[...]/devel/xp/core$ XP_RT=master xp xp.unittest.Runner src/test/config/unittest/core.ini
Uncaught exception: ParseError (syntax error, unexpected token "enum", expecting identifier)
at <source> [line 10 of ./src/main/php/lang/Enum.class.php]
# ...
We would need to rename the Enum class to XPEnum (following the XPClass idiom). We should be able to do this BC break free for PHP 7 and PHP 8.0 by aliasing Enum
to XPEnum
.
Obviously, since Enum is now a reserved word, one cannot declare a class with that. This breaks lang.Enum.
We've actually changed this recently to ease migration.
https://wiki.php.net/rfc/enumerations
Thanks to a clever trick from Nikita (discussed after the RFC was approved), “enum” is not a reserved word on its own. That means it is still a legal name for a class/interface/trait at this time. It will likely be converted into a full keyword at some point in the future, but this RFC does not specify that timeline. As a side effect, comments are not supported between “enum” and the Enum name, which is of little consequence in practice.
So your class name should not break.
So your class name should not break.
There is a glitch in this implementation, @iluuu1994:
# Works as expected
thekid@Surface:~/bin/php$ ./sapi/cli/php -r 'class Enum { }'
# Breaks
thekid@Surface:~/bin/php$ ./sapi/cli/php -r 'interface Value { } class Enum implements Value { }'
Parse error: syntax error, unexpected token "enum", expecting identifier in Command line code on line 1`
This is the trick you're referencing:
/*
* The enum keyword must be followed by whitespace and another identifier.
* This avoids the BC break of using enum in classes, namespaces, functions and constants.
*/
<ST_IN_SCRIPTING>"enum"{WHITESPACE}[a-zA-Z_\x80-\xff] {
yyless(4);
RETURN_TOKEN_WITH_IDENT(T_ENUM);
}
The problem is that in class Enum implements Value
, the string implements fulfills this rule, yielding the following tokens: T_CLASS T_ENUM T_IMPLEMENTS T_STRING("Value")
, however, the class declaration rule expects T_CLASS T_STRING
, thus causing this parse error.
Oh right, thanks for the heads up. Glad you tested that.
@thekid Pushed a fix, does this resolve the problem?
@thekid Pushed a fix, does this resolve the problem?
Yes, it does:
# After applying the newer patch:
thekid@Surface:~/bin/php$ ./sapi/cli/php -r 'interface Value { } class Enum implements Value { } var_dump(new Enum());'
object(Enum)#1 (0) {
}
Thanks @iluuu1994 ☀
Great! Thanks for testing :slightly_smiling_face:
PHP 8.0:
$ XP_RT=8.0 xp test src/test/php/net/xp_framework/unittest/core/EnumTest.class.php
# ...
♥: 41/45 run (4 skipped), 41 succeeded, 0 failed
Memory used: 2335.88 kB (2544.44 kB peak)
Time taken: 0.079 seconds
PHP 8.1 with enums:
$ XP_RT=master xp xp.unittest.Runner src/test/php/net/xp_framework/unittest/core/EnumTest.class.php
# ...
♥: 45/45 run (0 skipped), 45 succeeded, 0 failed
Memory used: 2250.23 kB (2646.16 kB peak)
Time taken: 0.065 seconds
Forwards compatibility with PHP 8.1 enumerations
enum_exists()
functionUnitEnum
andBackedEnum
interfacesXPClass::isEnum()
to also recognize PHP 8.1 enumsEnum::valuesOf()
andEnum::valuesOf()
to return PHP 8.1 enum casesSee https://wiki.php.net/rfc/enumerations