====== PHP RFC: Extended keyword support ======
* Version: 1.2
* Date: 2013-09-14
* Author: Bob Weinand, bobwei9@hotmail.com
* Status: Declined
* The implementation was creating too much need for maintenance etc. Don't duplicate that proposal without a better implementation.
* First Published at: http://wiki.php.net/rfc/keywords_as_identifiers
===== Introduction =====
This RFC aims to remove some restrictions which are due to the fact that keywords are not included in T_STRING (especially for class const, method and class names).
This especially could be useful to preserve more BC compatibility whenever new keywords are introduced.
===== What is now possible =====
* One might want to define an HTTP agent class. And would like to store some HTTP status constants:
class HTTP {
const CONTINUE = 100; // Works with patch
// But currently this fails with a parse error, because continue is a keyword.
const SWITCHING_PROTOCOLS = 101;
// etc. ...
}
* Building conditions with "and" or "or" methods
class Cond {
public static function and (...) { // using an "and" or "or" as name currently fails
// some logic here
return $andCondition;
}
public static function or (...) {
// some logic here
return $orCondition;
}
}
Cond::and($cond1, $cond2);
* Prevents unnecessary use of _****_call magic method ("-****>keyword_name_for_non_static_method()" works, but "public function keyword_name_for_non_static_method() {}" currently fails)
// Ugly, current code
class SomeClass {
private $list = [];
public function _list () {
return $this->list;
}
public function __call ($func, $args) {
if (method_exists($this, "_".$func)) {
return call_user_func_array("_".$func, $args); // or some similar thing, if not underscores etc....
}
// some error handling here
}
}
// How we could write it with the patch
class SomeClass {
private $list = [];
public function list () {
return $this->list;
}
}
===== Details of proposal =====
Concretely this patch enables:
* all keywords for
* method names
* class constant names
* declare directive names
* class names
* trait names
* interface names
* goto label names
* namespace names
* actual language features are preserved:
* a label (for goto) named //default// or //else// won't work ("default:" in switch or "else:" in alternative if structure)
* a namespace named //namespace// won't work (a namespace name beginning with "namespace\" is a relative namespace name)
* a class constant named //class// can't be defined ("classname::class" has a special meaning)
* ...
An example what is possible with this patch:
namespace Class {
class List {
const default = 0;
public $case = array(array(self::default));
public static function echo (List $instance) {
var_dump($instance->case);
}
public function new (array $entry) {
$this->case[] = $entry;
return $this;
}
}
}
namespace {
\Class\List::echo((new Class\List)->new(array(1)));
}
==== Typehints ====
Currently when using array or callable as typehint, the old behaviour is preferred over comparing if it's a class/interface named array or callable.
I'm not sure if we should just allow both in this special case.
===== Implementation =====
The transformation of alphabetic tokens to a T_STRING is done in lexer (post-processing output of lexer).
Initially it was done in parser, but that had a few disadvantages:
* more restricted support for keywords
* output of token_get_all() and highlight_*() functions was still using the unconverted tokens
That is also why performance is affected, as it is some code which needs to be run on every token.
===== Impact on performance =====
There is a slight decrease in //compilation performance// of up to 10% in worst case. So, actually, when used with opcache (execution only), any impact shouldn't be noticeable.
For that benchmark I used an 1.5 megabyte big file wrapped in an //if (false)// (so that nothing is executed): https://raw.github.com/nikic/PHP-Parser/master/lib/PHPParser/Parser.php
Compare actual run time:
time ./sapi/cli/php -r 'for($i=0;$i++<5000;)require "Parser.php";'
real 0m33.132s
user 0m32.816s
sys 0m0.313s
To run time with patch applied:
time ./sapi/cli/php -r 'for($i=0;$i++<5000;)require "Parser.php";'
real 0m36.720s
user 0m36.400s
sys 0m0.316s
===== Proposed PHP Version(s) =====
This RFC should go into next PHP 5.x.
===== Patch =====
* The patch is against master
* Pull request is at [[https://github.com/php/php-src/pull/438]]
===== References =====
* Mailing List thread at [[http://markmail.org/message/7rn4mbwkbytqa3ig]]
===== Rejected Features =====
* Initially the patch contained also some support for functions and constants which was removed later due to some resulting syntactic inconsistencies
===== Vote =====
* Yes
* No
Deadline was Monday, 28th october 2013.
===== Versions =====
* 1.0: Initial proposal (16.9.2013)
* 1.1: Added some more examples (18.9.2013)
* 1.2: Removed some restrictions (now all keywords are permitted except the ones which would conflict with the existing language) (16.10.2013)