1
0
mirror of https://github.com/php/php-src.git synced 2026-04-25 00:48:25 +02:00

- Support instantiation of nested class. The following script now should

- work:
-<?php
-	class foo
-	{
-		function bar()
-		{
-			print "bar() in class bar\n";
-		}
-
-		class barbara
-		{
-			function bar()
-			{
-				print "bar() in class foo::barbara\n";
-			}
-		}
-	}
-
-	$obj = new foo();
-	$obj->bar();
-
-	$obj = new foo::barbara();
-	$obj->bar();
-
This commit is contained in:
Andi Gutmans
2001-11-04 19:30:49 +00:00
parent bddb9539f7
commit a332f826a7
4 changed files with 35 additions and 32 deletions
+9 -9
View File
@@ -914,6 +914,7 @@ void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_
} else {
SET_UNUSED(opline->op1);
}
zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
opline->op2 = *class_name;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
opline->result.op_type = IS_CONST; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
@@ -948,12 +949,14 @@ void zend_do_end_function_call(znode *function_name, znode *result, znode *argum
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
if (function_name->op_type==IS_CONST && !is_method && !is_dynamic_fcall) {
if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
opline->opcode = ZEND_DO_FCALL;
opline->op1 = *function_name;
} else {
opline->opcode = ZEND_DO_FCALL_BY_NAME;
SET_UNUSED(opline->op1);
}
opline->op1 = *function_name;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
opline->result.op_type = IS_VAR;
*result = opline->result;
@@ -1824,7 +1827,7 @@ void zend_do_pop_object(znode *object TSRMLS_DC)
}
void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC)
void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
unsigned char *ptr = NULL;
@@ -1832,7 +1835,7 @@ void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC)
opline->opcode = ZEND_NEW;
opline->result.op_type = IS_VAR;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
opline->op1 = *class_name;
opline->op1 = *class_type;
SET_UNUSED(opline->op2);
new_token->u.opline_num = get_next_op_number(CG(active_op_array));
@@ -1851,14 +1854,11 @@ void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC)
}
void zend_do_end_new_object(znode *result, znode *class_name, znode *new_token, znode *argument_list TSRMLS_DC)
void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC)
{
znode ctor_result;
if (class_name->op_type == IS_CONST) {
zval_copy_ctor(&class_name->u.constant);
}
zend_do_end_function_call(class_name, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
zend_do_free(&ctor_result TSRMLS_CC);
CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
+2 -2
View File
@@ -313,8 +313,8 @@ void zend_do_push_object(znode *object TSRMLS_DC);
void zend_do_pop_object(znode *object TSRMLS_DC);
void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC);
void zend_do_end_new_object(znode *result, znode *class_name, znode *new_token, znode *argument_list TSRMLS_DC);
void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC);
void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC);
void zend_do_fetch_constant(znode *result, znode *constant_name, int mode TSRMLS_DC);
+20 -18
View File
@@ -1487,9 +1487,24 @@ binary_assign_op_addr: {
case ZEND_FETCH_CLASS:
{
if (EX(opline)->op1.op_type == IS_UNUSED) {
if (zend_hash_find(EG(class_table), EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) {
zend_error(E_ERROR, "Class '%s' not found", EX(opline)->op2.u.constant.value.str.val);
zval tmp;
zval *class_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
if (class_name->type != IS_STRING) {
tmp = *class_name;
zval_copy_ctor(&tmp);
convert_to_string(&tmp);
class_name = &tmp;
zend_str_tolower(tmp.value.str.val, tmp.value.str.len);
}
if (zend_hash_find(EG(class_table), class_name->value.str.val, class_name->value.str.len+1, &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) {
zend_error(E_ERROR, "Class '%s' not found", class_name->value.str.val);
}
if (class_name == &tmp) {
zval_dtor(&tmp);
}
FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2));
} else {
if (zend_hash_find(&EX(Ts)[EX(opline)->op1.u.var].EA.class_entry->class_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) {
zend_error(E_ERROR, "Class '%s' not found", EX(opline)->op2.u.constant.value.str.val);
@@ -2015,26 +2030,13 @@ send_by_ref:
case ZEND_SWITCH_FREE:
zend_switch_free(EX(opline), EX(Ts) TSRMLS_CC);
NEXT_OPCODE();
case ZEND_NEW: {
zval *tmp = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
zval class_name;
zend_class_entry *ce;
class_name = *tmp;
zval_copy_ctor(&class_name);
convert_to_string(&class_name);
zend_str_tolower(class_name.value.str.val, class_name.value.str.len);
if (zend_hash_find(EG(class_table), class_name.value.str.val, class_name.value.str.len+1, (void **) &ce)==FAILURE) {
zend_error(E_ERROR, "Cannot instantiate non-existent class: %s", class_name.value.str.val);
}
case ZEND_NEW:
{
EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr;
ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr);
object_init_ex(EX(Ts)[EX(opline)->result.u.var].var.ptr, ce);
object_init_ex(EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(Ts)[EX(opline)->op1.u.var].EA.class_entry);
EX(Ts)[EX(opline)->result.u.var].var.ptr->refcount=1;
EX(Ts)[EX(opline)->result.u.var].var.ptr->is_ref=1;
zval_dtor(&class_name);
FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1));
}
NEXT_OPCODE();
case ZEND_FETCH_CONSTANT:
+4 -3
View File
@@ -429,8 +429,8 @@ expr_without_variable:
| cvar '=' expr { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
| cvar '=' '&' w_cvar { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
| cvar '=' '&' function_call { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
| cvar '=' '&' T_NEW static_or_variable_string { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$5, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
| T_NEW static_or_variable_string { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$2, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
| cvar '=' '&' T_NEW parse_class_entry { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
| T_NEW parse_class_entry { 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);}
| cvar T_PLUS_EQUAL expr { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
| cvar T_MINUS_EQUAL expr { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
| cvar T_MUL_EQUAL expr { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); }
@@ -509,7 +509,8 @@ function_call:
parse_class_entry:
parse_class_entry T_PAAMAYIM_NEKUDOTAYIM T_STRING { do_fetch_class(&$$, &$1, &$3 TSRMLS_CC); }
| T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
| static_or_variable_string { /* Using static_or_variable_string and not T_STRING because NEW supported $var */
do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
;
static_or_variable_string: