mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
- Support static members. The following script works:
<? class foo { class bar { function init_values() { for ($i=1; $i<10; $i++) { foo::bar::$hello[$i] = $i*$i; } } function print_values() { for ($i=1; $i<10; $i++) { print foo::bar::$hello[$i] . "\n"; } } } } foo::bar::init_values(); foo::bar::print_values(); for ($i=1; $i<10; $i++) { print $hello[$i]?"Shouldn't be printed\n":""; } ?>
This commit is contained in:
parent
3d741d71c6
commit
d2da63f629
8 changed files with 46 additions and 7 deletions
|
@ -251,6 +251,7 @@ static void register_standard_class(void)
|
|||
zend_standard_class_def.name = zend_strndup("stdClass", zend_standard_class_def.name_length);
|
||||
zend_standard_class_def.parent = NULL;
|
||||
zend_hash_init_ex(&zend_standard_class_def.default_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
|
||||
zend_hash_init_ex(&zend_standard_class_def.static_members, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
|
||||
zend_hash_init_ex(&zend_standard_class_def.function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1, 0);
|
||||
zend_standard_class_def.constructor = NULL;
|
||||
zend_standard_class_def.handle_function_call = NULL;
|
||||
|
|
|
@ -284,6 +284,7 @@ struct _zend_class_entry {
|
|||
HashTable function_table;
|
||||
HashTable default_properties;
|
||||
HashTable class_table;
|
||||
HashTable static_members;
|
||||
zend_function_entry *builtin_functions;
|
||||
|
||||
union _zend_function *constructor;
|
||||
|
|
|
@ -572,6 +572,7 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
|
|||
|
||||
if (!class_type->constants_updated) {
|
||||
zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
|
||||
zend_hash_apply_with_argument(&class_type->static_members, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
|
||||
class_type->constants_updated = 1;
|
||||
}
|
||||
|
||||
|
@ -1215,6 +1216,7 @@ ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_
|
|||
*class_entry->refcount = 1;
|
||||
class_entry->constants_updated = 0;
|
||||
zend_hash_init(&class_entry->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1);
|
||||
zend_hash_init(&class_entry->static_members, 0, NULL, ZVAL_PTR_DTOR, 1);
|
||||
zend_hash_init(&class_entry->function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1);
|
||||
zend_hash_init(&class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 1);
|
||||
|
||||
|
|
|
@ -254,6 +254,19 @@ void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC)
|
|||
fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
|
||||
}
|
||||
|
||||
void zend_do_fetch_static_member(znode *class TSRMLS_DC)
|
||||
{
|
||||
zend_llist *fetch_list_ptr;
|
||||
zend_llist_element *le;
|
||||
zend_op *opline_ptr;
|
||||
|
||||
zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
|
||||
le = fetch_list_ptr->head;
|
||||
|
||||
opline_ptr = (zend_op *)le->data;
|
||||
opline_ptr->op2 = *class;
|
||||
opline_ptr->extended_value = ZEND_FETCH_STATIC_MEMBER;
|
||||
}
|
||||
|
||||
void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC)
|
||||
{
|
||||
|
@ -1251,6 +1264,8 @@ void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce)
|
|||
|
||||
/* Perform inheritance */
|
||||
zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
|
||||
/* STATIC_MEMBERS_FIXME */
|
||||
zend_hash_merge(&ce->static_members, &parent_ce->static_members, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
|
||||
zend_hash_merge(&ce->function_table, &parent_ce->function_table, (void (*)(void *)) function_add_ref, &tmp_zend_function, sizeof(zend_function), 0);
|
||||
ce->parent = parent_ce;
|
||||
if (!ce->handle_property_get)
|
||||
|
@ -1357,6 +1372,7 @@ ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_tabl
|
|||
(*ce->refcount)--;
|
||||
zend_hash_destroy(&ce->function_table);
|
||||
zend_hash_destroy(&ce->default_properties);
|
||||
zend_hash_destroy(&ce->static_members);
|
||||
return FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
|
@ -1688,6 +1704,7 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
|
|||
zend_hash_init(&new_class_entry.function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0);
|
||||
zend_hash_init(&new_class_entry.class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
|
||||
zend_hash_init(&new_class_entry.default_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
|
||||
zend_hash_init(&new_class_entry.static_members, 10, NULL, ZVAL_PTR_DTOR, 0);
|
||||
|
||||
new_class_entry.constructor = NULL;
|
||||
|
||||
|
@ -1712,6 +1729,9 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
|
|||
/* copy default properties */
|
||||
zend_hash_copy(&new_class_entry.default_properties, &parent_class->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
|
||||
|
||||
/* copy static members */
|
||||
zend_hash_copy(&new_class_entry.static_members, &parent_class->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
|
||||
|
||||
new_class_entry.constructor = parent_class->constructor;
|
||||
|
||||
/* copy overloaded handlers */
|
||||
|
|
|
@ -232,6 +232,7 @@ void zend_do_fetch_globals(znode *varname TSRMLS_DC);
|
|||
void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC);
|
||||
void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC);
|
||||
void fetch_string_offset(znode *result, znode *parent, znode *offset TSRMLS_DC);
|
||||
void zend_do_fetch_static_member(znode *class TSRMLS_DC);
|
||||
void zend_do_print(znode *result, znode *arg TSRMLS_DC);
|
||||
void zend_do_echo(znode *arg TSRMLS_DC);
|
||||
typedef int (*unary_op_type)(zval *, zval *);
|
||||
|
@ -544,9 +545,10 @@ int zendlex(znode *zendlval TSRMLS_DC);
|
|||
|
||||
|
||||
/* global/local fetches */
|
||||
#define ZEND_FETCH_GLOBAL 0
|
||||
#define ZEND_FETCH_LOCAL 1
|
||||
#define ZEND_FETCH_STATIC 2
|
||||
#define ZEND_FETCH_GLOBAL 0
|
||||
#define ZEND_FETCH_LOCAL 1
|
||||
#define ZEND_FETCH_STATIC 2
|
||||
#define ZEND_FETCH_STATIC_MEMBER 3
|
||||
|
||||
/* unset types */
|
||||
#define ZEND_UNSET_REG 0
|
||||
|
|
|
@ -547,6 +547,9 @@ static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type
|
|||
}
|
||||
target_symbol_table = EG(active_op_array)->static_variables;
|
||||
break;
|
||||
case ZEND_FETCH_STATIC_MEMBER:
|
||||
target_symbol_table = &Ts[opline->op2.u.var].EA.class_entry->static_members;
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
}
|
||||
|
||||
|
@ -579,7 +582,7 @@ static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type
|
|||
}
|
||||
if (opline->extended_value == ZEND_FETCH_LOCAL) {
|
||||
FREE_OP(Ts, &opline->op1, free_op1);
|
||||
} else if (opline->extended_value == ZEND_FETCH_STATIC) {
|
||||
} else if (opline->extended_value == ZEND_FETCH_STATIC || opline->extended_value == ZEND_FETCH_STATIC_MEMBER) {
|
||||
zval_update_constant(retval, (void *) 1 TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
|
|
@ -515,7 +515,7 @@ parse_class_entry:
|
|||
|
||||
static_or_variable_string:
|
||||
T_STRING { $$ = $1; }
|
||||
| r_cvar { $$ = $1; }
|
||||
| r_cvar_without_static_member { $$ = $1; }
|
||||
;
|
||||
|
||||
|
||||
|
@ -597,10 +597,18 @@ rw_cvar:
|
|||
cvar { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); $$ = $1; }
|
||||
;
|
||||
|
||||
cvar:
|
||||
variable { $$ = $1; }
|
||||
r_cvar_without_static_member:
|
||||
variable { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
|
||||
;
|
||||
|
||||
cvar:
|
||||
variable { $$ = $1; }
|
||||
| static_member {$$ = $1; }
|
||||
;
|
||||
|
||||
static_member:
|
||||
parse_class_entry T_PAAMAYIM_NEKUDOTAYIM variable { $$ = $3; zend_do_fetch_static_member(&$1 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
variable:
|
||||
variable_property '(' { zend_do_begin_method_call(NULL, &$1 TSRMLS_CC); }
|
||||
|
|
|
@ -117,6 +117,7 @@ ZEND_API void destroy_zend_class(zend_class_entry *ce)
|
|||
efree(ce->refcount);
|
||||
zend_hash_destroy(&ce->function_table);
|
||||
zend_hash_destroy(&ce->default_properties);
|
||||
zend_hash_destroy(&ce->static_members);
|
||||
zend_hash_destroy(&ce->class_table);
|
||||
break;
|
||||
case ZEND_INTERNAL_CLASS:
|
||||
|
@ -124,6 +125,7 @@ ZEND_API void destroy_zend_class(zend_class_entry *ce)
|
|||
free(ce->refcount);
|
||||
zend_hash_destroy(&ce->function_table);
|
||||
zend_hash_destroy(&ce->default_properties);
|
||||
zend_hash_destroy(&ce->static_members);
|
||||
zend_hash_destroy(&ce->class_table);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue