New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for keywords for class/method/label/declare/namespace/class const names #438

Closed
wants to merge 9 commits into
base: master
from

Conversation

4 participants
@bwoebi
Contributor

bwoebi commented Sep 11, 2013

This patch adds possibility to use keywords at some places where previously were only T_STRING's allowed.

Example:

class List { // T_LIST, is now enabled
    public function default() { // T_DEFAULT
        // do some action
    }
}

For further examples see the rfc at https://wiki.php.net/rfc/keywords_as_identifiers

The goal of the patch is to limit less the user's choice of names for labels, classes, functions, namespaces etc.

Internals discussion at http://marc.info/?l=php-internals&m=137893452326358&w=2


Possible constructs (with string being a T_STRING or a keyword):

string::string;
string::string();
$var->string;
$var->string();
(modifier)* function string() { // methods
function T_STRING ((string) $var, ...) // the optional typehint
declare(string = ..., ...);
(namespace) \(string\)*string;
use string as (modifier) string; // namespace aliasing
new string;
class string (extends string) (implements string, ...) {
trait string (extends string) (implements string, ...) {
interface string (extends string, ...) {
string::…;
string: // label for goto
goto string;

What still is impossible: (as function names and constants remain unaffected)

keyword(); // fcall
keyword; // constant
((Z_STRLEN_P(name) == sizeof("parent")-1) &&
!memcmp(lcname, "parent", sizeof("parent")-1)) ||
((Z_STRLEN_P(name) == sizeof("static")-1) &&
!memcmp(lcname, "parent", sizeof("static")-1))) {

This comment has been minimized.

@nikic

nikic Sep 15, 2013

Member

nit: should be static

This comment has been minimized.

@bwoebi

bwoebi Sep 15, 2013

Contributor

Hmpf, fixed. Had that already fixed locally, but forgotten to commit it.

@Majkl578 Majkl578 referenced this pull request Sep 22, 2013

Closed

anon class objects #470

bwoebi added some commits Oct 4, 2013

Moved keyword handling from parser to lexer
Actually, having it in parser, also caused tokenizer and highlighter to return the keyword tokens instead of a T_STRING token which might confuse parsers (and lead this way to a BC break)
Also this way we do not need to maintain a fixed list in parser which needs to be updated on every addition/modification of keywords
Furthermore it allows more control over tokens before they are passed to parser (for future features...)
Optimized
Stored some values in variables (which are then stored during function execution in registers) instead of refetching them everytime
@@ -2,10 +2,12 @@
Bug #43343 (Variable class name)
--FILE--
<?php
namespace Foo;
class Bar { }
class if {

This comment has been minimized.

@smalyshev

smalyshev Oct 16, 2013

Contributor

why replace a working test with something completely different? If we need to test for if as class name, we can add different test, but that's not what this test was about.

This comment has been minimized.

@bwoebi

bwoebi Oct 16, 2013

Contributor

@smalyshev actually a class named namespace is supported. So the test was superfluous in it's old state.

This comment has been minimized.

@smalyshev

smalyshev Oct 16, 2013

Contributor

@bwoebi if it's supported, change the outcome of the test, why rewrite it to something completely different testing something else not related to the bug?

This comment has been minimized.

@bwoebi

bwoebi Oct 16, 2013

Contributor

@smalyshev good question… Don't remember why I had changed the test. Reverted test now and updated expectf to match actual state.

@@ -201,6 +201,11 @@ void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
zend_stack_init(&CG(context_stack));
CG(encoding_declared) = 0;
CG(tokenbufptr) = -1;
CG(tokenbuffer) = emalloc(sizeof(token_buf) * ((CG(tokenbufsize) = ZEND_INIT_TOKEN_BUF_SIZE) + 1));

This comment has been minimized.

@smalyshev

smalyshev Oct 16, 2013

Contributor

I don't think we need to be clever here. Why not just assign CG(tokenbufsize) = ZEND_INIT_TOKEN_BUF_SIZE separately? It would be much more readable.

| T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_ARRAY; }
| T_CALLABLE { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_CALLABLE; }
| fully_qualified_class_name { $$ = $1; }
| class_name { if ((Z_STRLEN($1.u.constant) == 5 && !strncasecmp(Z_STRVAL($1.u.constant), "array", 5)) || (Z_STRLEN($1.u.constant) == 8 && !strncasecmp(Z_STRVAL($1.u.constant), "callable", 8))) { $$.op_type = IS_CONST; efree(Z_STRVAL($1.u.constant)); switch (Z_STRLEN($1.u.constant)) { case 5: Z_TYPE($$.u.constant) = IS_ARRAY; break; case 8: Z_TYPE($$.u.constant) = IS_CALLABLE; break; } } else { $$ = $1; } }

This comment has been minimized.

@smalyshev

smalyshev Oct 16, 2013

Contributor

I think it may be better to take it out as a function. As an one-line expression it is not readable and if we'd ever need to modify it it would be very easy to do it wrong. It probably also has some reuse potential.

/* Handling of T_HALT_COMPILER; might cause memory leaks if not handled */
if (buf_one_token == T_HALT_COMPILER && retval == '(') {
LEX_BUF_ADD
} else if (buf_two_token == T_HALT_COMPILER && buf_one_token == '(' && retval == ')') {

This comment has been minimized.

@smalyshev

smalyshev Oct 16, 2013

Contributor

these two branches seem to have the same code inside, why there's two branches and not just one if with || condition?

@php-pulls

This comment has been minimized.

php-pulls commented Feb 28, 2015

Comment on behalf of nikic at php.net:

Closing as this RFC failed and there now is a new one.

@php-pulls php-pulls closed this Feb 28, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment