- 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:
Andi Gutmans 2001-11-25 08:49:09 +00:00
parent 3d741d71c6
commit d2da63f629
8 changed files with 46 additions and 7 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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 */

View file

@ -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 *);
@ -547,6 +548,7 @@ int zendlex(znode *zendlval TSRMLS_DC);
#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

View file

@ -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);
}

View file

@ -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); }

View file

@ -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;
}