How PHP functions increase the mandatory type return instance

Source: Internet
Author: User
Tags constant zend

In the development process, the return value type of the function should be invariant, but PHP is a weakly typed language.

So PHP does not have this kind of syntax verification, because of this, caused a lot of pits.

For example, the following code:

<?php

function Getarticles (...) {

$arrData = Array ();

if ($exp 1) {

return $arrData;

}else if ($exp 2) {

return 1;

}else{

return false;

}

}

$arrData =getarticles (...);

foreach ($arrData as $record) {

Do something.

....

}

?>

function Getarticles returns different types of values based on different conditions, there are bool, int, and array, and normally such functions want to return the array, and then take the array to do some other operation,

Because the function return value type is not fixed, the call is likely to produce a variety of unexpected pits,

So I thought, since it can't be regulated, it's directly mandatory.

A function/method return value can enforce a type, as shown



Supports four coercion type restrictions: int, array, bool, object, when the return value does not match the type in the function declaration, throws the warning, would have thrown the error, but felt

Too ruthless, can only be regarded as an anomaly, not wrong, so use warning good.

PHP itself is not supported by the syntax of the INT function, so to support, you have to fix the parser, about the parser, you can go here >>> view

Details, here is not to say,

Modify syntax scan ZEND/ZEND_LANGUAGE_SCANNER.L file first

Add the following code:

<ST_IN_SCRIPTING> "int" {

return t_function_return_int;

}

<ST_IN_SCRIPTING> "BOOL" {

return t_function_return_object;

}

<ST_IN_SCRIPTING> "Object" {

return t_function_return_object;

}

<ST_IN_SCRIPTING> "Resource" {

return t_function_return_resource;

}

The meaning is very simple, the scanner scans to the keyword int, bool, object, resource, array when return corresponding t_function_*, this is a token,

Scanner According to different token do different processing, token to first in ZEND/ZEND_LANGUAGE_PARSER.Y file defined

Add the following code

..........

%token T_function_return_int

%token T_function_return_bool

%token t_function_return_string

%token T_function_return_object

%token T_function_return_resource

Then add the token processing logic:

function

t_function {$$.u.opline_num = CG (Zend_lineno); $$.u.ea.var = 0;}

| T_function_return_int T_function {

$$.u.opline_num = CG (Zend_lineno);

$$.u.ea.var = Is_long;

}

| T_function_return_bool T_function {

$$.u.opline_num = CG (Zend_lineno);

$$.u.ea.var = Is_bool;

}

| T_function_return_string T_function {

$$.u.opline_num = CG (Zend_lineno);

$$.u.ea.var = is_string;

}

| T_function_return_object T_function {

$$.u.opline_num = CG (Zend_lineno);

$$.u.ea.var = Is_object;

}

| T_function_return_resource T_function {

$$.u.opline_num = CG (Zend_lineno);

$$.u.ea.var = Is_resource;

}

| T_array T_function {

$$.u.opline_num = CG (Zend_lineno);

$$.u.ea.var = Is_array;

}

The $$.u.ea.var store is the function return type, and finally to match it with the return value type,

So the grammar interpreter can handle our new PHP syntax.

This is not enough and you need to modify the processing logic of the function declaration definition

ZEND/ZEND_COMPILE.C:: zend_do_begin_function_declaration

......

Zend_op_array Op_array;

Char *name = function_name->u.constant.value.str.val;

int Name_len = function_name->u.constant.value.str.len;

int function_type = function_token->u.ea.var; Save the function type, added in the grammar interpreter: $$.u.ea.var = Is_long;

int function_begin_line = function_token->u.opline_num;

......

Op_array.function_name = name;

Op_array.fn_type = Function_type; Save the type to Op_array.

Op_array.return_reference = return_reference;

Op_array.fn_flags |= fn_flags;

op_array.pass_rest_by_reference = 0;

..........

PHP is the first parse PHP syntax to generate the corresponding opcode, the need for the environment, parameter information saved to the Execute_data global variables, and finally through the Execute function to implement opcode,

So to do processing is to save the type of function to opcode: Op_array.fn_type = function_type;

Op_array is not fn_type, to modify the structure of Op_array, increase zend_uint fn_type;

(About opcode You can imagine the conversion from C to assembly, my blog has related articles, you can refer to)

Finally, to modify the opcode destroy function, the return of the function returns will generate token T_return,t_return will invoke a different Calback function based on the returned type:

Zend_return_spec_const_handler

Zend_return_spec_tmp_handler

Zend_return_spec_var_handler

It has three callback, if the return value is a CONST type of data, then Zend_return_spec_const_handler
The return value is temporary data, such as: Returns 1, then Zend_return_spec_tmp_handler
The return value is a variable, such as: Returns $a, Zend_return_spec_var_handler

So add the processing logic to these three callback functions:

Add the following code before the callback function return

if (EG (active_op_array)->fn_type > 0) && z_type_p (retval_ptr)!= EG (Active_op_array)->fn_type) {

PHP_ERROR_DOCREF0 (NULL tsrmls_dc,e_warning, "function name%s return a wrong type.", EG (Active_op_array)->function_ name);

}

Fn_type is compared to the type of the return value, and if there is no match, the warning is thrown.

I have patched, currently only support php5.3 version, there is a need to take a play.

I do not know why the official does not support this grammar, I think it is quite necessary.

Download Patch: Php-syntax.patch

Continued:

Then I talked to Brother Heosen: Http://weibo.com/laruence.

The following is his answer:

"This topic, basically also is the Mail group menstruation pastes ...." 1. Because PHP is a type, many types can be converted to each other, so in the end to the implicit conversion, your implementation is not converted, such limitations are too large, if the conversion involves a variety of conversion rules. 2. Nor is it unsupported, but your implementation is certainly not enough (various custom classes, and inheriting classes). 3. If you want to do JIT later, you may consider support. "

So it seems that the issue of the official is also more tangled, is really my idea is not to cast, only need to throw a warning on the line, so that developers decide whether to convert, is not better?



The hack language of Facebook also supports forced type conversions. However, the changes are too much, PHP upgrade maintenance is not a bit worse.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.