]> granicus.if.org Git - php/commitdiff
- Support instantiation of nested class. The following script now should
authorAndi Gutmans <andi@php.net>
Sun, 4 Nov 2001 19:30:49 +0000 (19:30 +0000)
committerAndi Gutmans <andi@php.net>
Sun, 4 Nov 2001 19:30:49 +0000 (19:30 +0000)
- 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();
-

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_language_parser.y

index 2185ed4fb7c547672264111b94c3eb25107650ad..a9f0a09e7a9b0a36f6f1f80eb5611bbc964bb078 100644 (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));
index 17d88c85e92fbc1d6c3b204b9cd0089601d5c929..b371cdc5eb150645a59220a97bba92eb9042ac65 100644 (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);
 
index d63a13e21c0db6070c946ff6902f49926807be9f..efc82dfc5fad871fe1669d5350f206f2e07107eb 100644 (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:
index 67b6af8f994d4b37709d688ed24088e8c3a83bf1..a32234e3ecfd50b23318cc2719f817cb3b30aa3b 100644 (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: