]> granicus.if.org Git - php/commitdiff
Add class type hints
authorZeev Suraski <zeev@php.net>
Thu, 6 Mar 2003 14:31:17 +0000 (14:31 +0000)
committerZeev Suraski <zeev@php.net>
Thu, 6 Mar 2003 14:31:17 +0000 (14:31 +0000)
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_language_parser.y

index 644f8561f62836e866f565d6248e30357f555044..fb6d394abfb1a5f894de7b2ad67aa52448e636bb 100644 (file)
@@ -1085,7 +1085,7 @@ void zend_do_end_function_declaration(znode *function_token TSRMLS_DC)
 }
 
 
-void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, zend_uchar pass_type TSRMLS_DC)
+void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, zend_uchar pass_type TSRMLS_DC)
 {
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
@@ -1113,6 +1113,19 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
                CG(active_op_array)->arg_types[0]=(unsigned char) offset->u.constant.value.lval;
                CG(active_op_array)->arg_types[offset->u.constant.value.lval] = pass_type;
        }
+
+       if (class_type->op_type != IS_UNUSED) {
+               znode passed_var = opline->result;
+
+               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+               opline->opcode = ZEND_VERIFY_CE;
+               opline->op1 = *class_type;
+               opline->op2 = passed_var;
+               opline->extended_value = offset->u.constant.value.lval;
+       } else {
+               opline->result.u.EA.type |= EXT_TYPE_UNUSED;
+       }
 }
 
 
index f24e14b8c837011e545edccefd42baeafdbb16c6..414736b8f04affaa8b494332110ec9b13a3f2c00 100644 (file)
@@ -311,7 +311,7 @@ void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC);
 int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier);
 void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC);
 void zend_do_end_function_declaration(znode *function_token TSRMLS_DC);
-void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, zend_uchar pass_type TSRMLS_DC);
+void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, zend_uchar pass_type TSRMLS_DC);
 int zend_do_begin_function_call(znode *function_name TSRMLS_DC);
 void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC);
 void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC);
@@ -662,6 +662,7 @@ int zendlex(znode *zendlval TSRMLS_DC);
 #define ZEND_START_NAMESPACE           143
 
 #define ZEND_ADD_INTERFACE                     144
+#define ZEND_VERIFY_CE                         145
 
 /* end of block */
 
index 412e04380b7996bcee49a9edad049572da11af37..11203f68ae8b8447c95e264095b98eb05ee0895a 100644 (file)
@@ -2966,9 +2966,9 @@ int zend_recv_handler(ZEND_OPCODE_HANDLER_ARGS)
                        PZVAL_UNLOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr);
                }
        } else if (PZVAL_IS_REF(*param)) {
-               zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC);
+               zend_assign_to_variable_reference(&EX(opline)->result, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC);
        } else {
-               zend_assign_to_variable(NULL, &EX(opline)->result, NULL, *param, IS_VAR, EX(Ts) TSRMLS_CC);
+               zend_assign_to_variable(&EX(opline)->result, &EX(opline)->result, NULL, *param, IS_VAR, EX(Ts) TSRMLS_CC);
        }
 
        NEXT_OPCODE();
@@ -2998,13 +2998,13 @@ int zend_recv_init_handler(ZEND_OPCODE_HANDLER_ARGS)
                        param = NULL;
                        assignment_value = &EX(opline)->op2.u.constant;
                }
-               zend_assign_to_variable(NULL, &EX(opline)->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC);
+               zend_assign_to_variable(&EX(opline)->result, &EX(opline)->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC);
        } else {
                assignment_value = *param;
                if (PZVAL_IS_REF(assignment_value)) {
-                       zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC);
+                       zend_assign_to_variable_reference(&EX(opline)->result, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC);
                } else {
-                       zend_assign_to_variable(NULL, &EX(opline)->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC);
+                       zend_assign_to_variable(&EX(opline)->result, &EX(opline)->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC);
                }
        }
 
@@ -3993,6 +3993,28 @@ int zend_add_interface_handler(ZEND_OPCODE_HANDLER_ARGS)
        NEXT_OPCODE();
 }
 
+
+int zend_verify_ce_handler(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zval *arg = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
+       zend_class_entry *ce = EX_T(EX(opline)->op1.u.var).EA.class_entry;
+
+       if ((Z_TYPE_P(arg) != IS_OBJECT)
+               || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
+               char *error_msg;
+
+               if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+                       error_msg = "implement interface";
+               } else {
+                       error_msg = "be an instance of";
+               }
+               zend_error(E_ERROR, "Argument %d must %s %s", EX(opline)->extended_value, error_msg, ce->name);
+       }
+
+       NEXT_OPCODE();
+}
+
+
 void zend_init_opcodes_handlers()
 {
        zend_opcode_handlers[ZEND_NOP] = zend_nop_handler;
@@ -4170,6 +4192,7 @@ void zend_init_opcodes_handlers()
        zend_opcode_handlers[ZEND_START_NAMESPACE] = zend_start_namespace_handler;
 
        zend_opcode_handlers[ZEND_ADD_INTERFACE] = zend_add_interface_handler;
+       zend_opcode_handlers[ZEND_VERIFY_CE] = zend_verify_ce_handler;
 }
 
 /*
index 50d495fbd621639552dcf39fa7df8d719d8955cc..c25ce39f08b2262fbddb1c5f44d4cc2eb3868515 100644 (file)
@@ -438,19 +438,25 @@ parameter_list:
 
 
 non_empty_parameter_list:
-               T_VARIABLE                              { znode tmp;  fetch_simple_variable(&tmp, &$1, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE TSRMLS_CC); }
-       |       '&' T_VARIABLE                  { znode tmp;  fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE TSRMLS_CC); }
-       |       '&' T_VARIABLE '=' static_scalar                        { znode tmp;  fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$4, BYREF_FORCE TSRMLS_CC); }
-       |       T_CONST T_VARIABLE              { znode tmp;  fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE TSRMLS_CC); }
-       |       T_VARIABLE '=' static_scalar                            { znode tmp;  fetch_simple_variable(&tmp, &$1, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$3, BYREF_NONE TSRMLS_CC); }
-       |       non_empty_parameter_list ',' T_VARIABLE         { znode tmp;  fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE TSRMLS_CC); }
-       |       non_empty_parameter_list ',' '&' T_VARIABLE     { znode tmp;  fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE TSRMLS_CC); }
-       |       non_empty_parameter_list ',' '&' T_VARIABLE      '=' static_scalar { znode tmp;  fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$6, BYREF_FORCE TSRMLS_CC); }
-       |       non_empty_parameter_list ',' T_CONST T_VARIABLE                         { znode tmp;  fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE TSRMLS_CC); }
-       |       non_empty_parameter_list ',' T_VARIABLE '=' static_scalar       { znode tmp;  fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$5, BYREF_NONE TSRMLS_CC); }
+               optional_class_type T_VARIABLE                          { znode tmp;  fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$1, BYREF_NONE TSRMLS_CC); }
+       |       optional_class_type '&' T_VARIABLE                      { znode tmp;  fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$1, BYREF_FORCE TSRMLS_CC); }
+       |       optional_class_type '&' T_VARIABLE '=' static_scalar                    { znode tmp;  fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$5, &$1, BYREF_FORCE TSRMLS_CC); }
+       |       T_CONST optional_class_type T_VARIABLE          { znode tmp;  fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$2, BYREF_NONE TSRMLS_CC); }
+       |       optional_class_type T_VARIABLE '=' static_scalar                                { znode tmp;  fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$4, &$1, BYREF_NONE TSRMLS_CC); }
+       |       non_empty_parameter_list ',' optional_class_type T_VARIABLE     { znode tmp;  fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$3, BYREF_NONE TSRMLS_CC); }
+       |       non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE { znode tmp;  fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$3, BYREF_FORCE TSRMLS_CC); }
+       |       non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE  '=' static_scalar { znode tmp;  fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$7, &$3, BYREF_FORCE TSRMLS_CC); }
+       |       non_empty_parameter_list ',' T_CONST optional_class_type T_VARIABLE  { znode tmp;  fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$4, BYREF_NONE TSRMLS_CC); }
+       |       non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' static_scalar   { znode tmp;  fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$6, &$3, BYREF_NONE TSRMLS_CC); }
 ;
 
 
+optional_class_type:
+               /* empty */             { $$.op_type = IS_UNUSED; }
+       |       namespace_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { do_fetch_class(&$$, &$1, &$3 TSRMLS_CC); }
+       |       T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
+;
+
 function_call_parameter_list:
                non_empty_function_call_parameter_list  { $$ = $1; }
        |       /* empty */                             { $$.u.constant.value.lval = 0; }