Last active
December 24, 2015 00:59
-
-
Save bwoebi/6720403 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c | |
index d789f3c..8fca9ae 100644 | |
--- a/Zend/zend_compile.c | |
+++ b/Zend/zend_compile.c | |
@@ -2226,33 +2226,28 @@ void zend_resolve_class_name(znode *class_name TSRMLS_DC) /* {{{ */ | |
/* }}} */ | |
void zend_do_create_anon_class(znode *result TSRMLS_DC) { /* {{{ */ | |
- char *class_name = NULL; | |
- int class_name_len = 0; | |
- | |
- CG(anon_class_id)++; | |
- | |
- result->op_type = IS_CONST; | |
- | |
- Z_TYPE(result->u.constant) = IS_STRING; | |
- class_name_len = snprintf( | |
- NULL, 0, "Class$$%lu", CG(anon_class_id)); | |
- class_name = (char*) emalloc(class_name_len+1); | |
- snprintf( | |
- class_name, class_name_len+1, | |
- "Class$$%lu", CG(anon_class_id) | |
- ); | |
- class_name[class_name_len] = '\0'; | |
- | |
- Z_STRLEN(result->u.constant) = class_name_len; | |
- Z_STRVAL(result->u.constant) = (char*) zend_new_interned_string( | |
- class_name, class_name_len+1, 1 TSRMLS_CC); | |
+ char *class_name = NULL; | |
+ int class_name_len = 0; | |
+ | |
+ CG(anon_class_id)++; | |
+ | |
+ result->op_type = IS_CONST; | |
+ | |
+ Z_TYPE(result->u.constant) = IS_STRING; | |
+ class_name_len = snprintf(NULL, 0, "Class$$%lu", CG(anon_class_id)); | |
+ class_name = (char*) emalloc(class_name_len+1); | |
+ snprintf(class_name, class_name_len+1, "Class$$%lu", CG(anon_class_id)); | |
+ class_name[class_name_len] = '\0'; | |
+ | |
+ Z_STRLEN(result->u.constant) = class_name_len; | |
+ Z_STRVAL(result->u.constant) = class_name; | |
} /* }}} */ | |
void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */ | |
{ | |
long fetch_class_op_number; | |
zend_op *opline; | |
- | |
+ | |
fetch_class_op_number = get_next_op_number(CG(active_op_array)); | |
opline = get_next_op(CG(active_op_array) TSRMLS_CC); | |
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h | |
index 3bc5ffc..71360c0 100644 | |
--- a/Zend/zend_globals.h | |
+++ b/Zend/zend_globals.h | |
@@ -150,9 +150,11 @@ struct _zend_compiler_globals { | |
zend_bool multibyte; | |
zend_bool detect_unicode; | |
zend_bool encoding_declared; | |
- | |
+ | |
/* anonymous classes */ | |
- zend_ulong anon_class_id; | |
+ zend_ulong anon_class_id; | |
+ znode anon_class_name; | |
+ int anon_class_opline_num; | |
#ifdef ZTS | |
zval ***static_members_table; | |
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y | |
index 5a7dc08..c673d8b 100644 | |
--- a/Zend/zend_language_parser.y | |
+++ b/Zend/zend_language_parser.y | |
@@ -731,42 +731,77 @@ instance_call: | |
chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); } | |
; | |
-new_object: | |
- T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} | |
-; | |
- | |
-anon_class_type: | |
- T_CLASS { | |
- $$.u.op.opline_num = CG(zend_lineno); | |
- $$.EA = ZEND_ACC_ANON_CLASS; | |
- } | |
-; | |
- | |
-anon_class_decl: | |
- anon_class_type { | |
- zend_do_create_anon_class(&$$ TSRMLS_CC); | |
- } extends_from { | |
- zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); | |
- } implements_list | |
- '{' class_statement_list '}' { | |
- zend_do_end_class_declaration(&$1, &$3 TSRMLS_CC); | |
- zend_do_fetch_class(&$$, &$2 TSRMLS_CC); | |
- } | |
+anon_implements_list: | |
+ /* empty */ { $$.EA = 0; } | |
+ | T_IMPLEMENTS { | |
+ $1.u.op.opline_num = CG(zend_lineno); | |
+ $1.EA = ZEND_ACC_ANON_CLASS; | |
+ zend_do_fetch_class(&CG(anon_class_name), &CG(anon_class_name) TSRMLS_CC); | |
+ znode parent = CG(anon_class_name); | |
+ zend_do_create_anon_class(&$$ TSRMLS_CC); | |
+ CG(anon_class_name) = $$; | |
+ zval_copy_ctor(&CG(anon_class_name).u.constant); | |
+ zend_do_begin_class_declaration(&$1, &$$, &parent TSRMLS_CC); | |
+ $1.EA = CG(active_op_array)->last; | |
+ CG(active_op_array)->last = CG(anon_class_opline_num); | |
+ } interface_list { | |
+ CG(anon_class_opline_num) = CG(active_op_array)->last; | |
+ CG(active_op_array)->last = $1.EA; | |
+ $$ = $1; | |
+ } | |
; | |
-new_anon_object: | |
- T_NEW anon_class_decl { | |
- zend_do_extended_fcall_begin(TSRMLS_C); | |
- zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); | |
- } ctor_arguments { | |
- zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); | |
- zend_do_extended_fcall_end(TSRMLS_C); | |
- } | |
+optional_anon_class: | |
+ /* empty */ { $$.EA = 0; } | |
+ | anon_implements_list { | |
+ zend_bool interfaces = $1.EA; | |
+ $1.u.op.opline_num = CG(zend_lineno); | |
+ $1.EA = ZEND_ACC_ANON_CLASS; | |
+ if (!interfaces) { | |
+ zend_do_fetch_class(&CG(anon_class_name), &CG(anon_class_name) TSRMLS_CC); | |
+ znode parent = CG(anon_class_name); | |
+ zend_do_create_anon_class(&$$ TSRMLS_CC); | |
+ CG(anon_class_name) = $$; | |
+ zval_copy_ctor(&CG(anon_class_name).u.constant); | |
+ zend_do_begin_class_declaration(&$1, &$$, &parent TSRMLS_CC); | |
+ } else { | |
+ $$ = CG(anon_class_name); | |
+ } | |
+ } '{' class_statement_list '}' { | |
+ zend_do_fetch_class(&$$, &CG(anon_class_name) TSRMLS_CC); | |
+ zend_do_end_class_declaration(&$1, &$2 TSRMLS_CC); | |
+ $$.EA = 1; | |
+ } | |
; | |
new_expr: | |
- new_object | |
- | new_anon_object | |
+ T_NEW class_name { | |
+ zend_uchar i = 0; | |
+ while (i++ < 4) { | |
+ get_next_op(CG(active_op_array) TSRMLS_CC)->opcode = ZEND_NOP; | |
+ } | |
+ zend_do_extended_fcall_begin(TSRMLS_C); | |
+ zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); | |
+ } ctor_arguments { | |
+ CG(anon_class_opline_num) = CG(active_op_array)->last; | |
+ CG(active_op_array)->last = $1.u.op.opline_num - ((CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)?6:5); | |
+ CG(anon_class_name) = $2; | |
+ } optional_anon_class { | |
+ CG(active_op_array)->last = CG(anon_class_opline_num); | |
+ if ($6.EA) { | |
+ CG(active_op_array)->opcodes[$1.u.op.opline_num].op1_type = IS_VAR; | |
+ CG(active_op_array)->opcodes[$1.u.op.opline_num].op1.var = $6.u.op.var; | |
+ } | |
+ zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); | |
+ zend_do_extended_fcall_end(TSRMLS_C); | |
+ } | |
+ | T_NEW dynamic_class_name_reference { | |
+ zend_do_extended_fcall_begin(TSRMLS_C); | |
+ zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); | |
+ } ctor_arguments { | |
+ zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); | |
+ zend_do_extended_fcall_end(TSRMLS_C); | |
+ } | |
; | |
expr_without_variable: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment