• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

深入懂得PHP内核(六)函数的定义、传参及返回值

php 搞代码 3年前 (2022-01-24) 12次浏览 已收录 0个评论

深入理解PHP内核(六)函数的定义、传参及返回值

一、函数的定义

  用户函数的定义从function 关键字开始,如下

<span style="color: #0000ff">function</span> foo(<span style="color: #800080">$var</span><span style="color: #000000">) {    </span><span style="color: #0000ff">echo</span> <span style="color: #800080">$var</span><span style="color: #000000">;}</span>

  1、词法分析

  在Zend/zend_language_scanner.l中我们找到如下所示的代码:

<span style="color: #800000">"</span><span style="color: #800000">function</span><span style="color: #800000">"</span><span style="color: #000000"> {    </span><span style="color: #0000ff">return</span><span style="color: #000000"> T_FUNCTION;}</span>

  它所表示的含义是function将会生成T_FUNCTION标记。在获取这个标记后,我们开始语法分析。

  2、语法分析

  在Zend/zend_language_parser.y文件中找到函数的声明过程标记如下:

<span style="color: #000000">function:    T_FUNCTION { $$.u.opline_num </span>=<span style="color: #000000"> CG(zend_lineno); }; is_reference:        </span><span style="color: #008000">/*</span><span style="color: #008000"> empty </span><span style="color: #008000">*/</span> { $$.op_type =<span style="color: #000000"> ZEND_RETURN_VAL; }    </span>|   <span style="color: #800000">'</span><span style="color: #800000">&</span><span style="color: #800000">'</span>         { $$.op_type <div style="color:transparent">!本文来源gaodai.ma#com搞##代!^码网(</div><sup>搞gaodaima代码</sup>=<span style="color: #000000"> ZEND_RETURN_REF; }; unticked_function_declaration_statement:        function is_reference T_STRING {zend_do_begin_function_declaration(</span>&$<span style="color: #800080">1</span>, &$<span style="color: #800080">3</span>, <span style="color: #800080">0</span>, $<span style="color: #800080">2</span><span style="color: #000000">.op_type, NULL TSRMLS_CC); }            </span><span style="color: #800000">'</span><span style="color: #800000">(</span><span style="color: #800000">'</span> parameter_list <span style="color: #800000">'</span><span style="color: #800000">)</span><span style="color: #800000">'</span> <span style="color: #800000">'</span><span style="color: #800000">{</span><span style="color: #800000">'</span> inner_statement_list <span style="color: #800000">'</span><span style="color: #800000">}</span><span style="color: #800000">'</span><span style="color: #000000"> {                zend_do_end_function_declaration(</span>&$<span style="color: #800080">1</span><span style="color: #000000"> TSRMLS_CC); };</span>

    关注点在function is_reference T_STRING,表示function关键字,是否引用,函数名

  T_FUNCTION标记只是用来定位函数的声明,表示这是一个函数,而更多的工作是与这个函数相关的东西,包括参数,返回值。

  3、生成中间代码

  语法解析后,我们看到所执行编译函数为zend_do_begin_function_declaration。在Zend/zend_complie.c文件找到其实现如下:

<span style="color: #0000ff">void</span> zend_do_begin_function_declaration(znode *<span style="color: #000000">function_token, znode </span>*<span style="color: #000000">function_name, </span><span style="color: #0000ff">int</span> is_method, <span style="color: #0000ff">int</span> return_reference, znode *fn_flags_znode TSRMLS_DC) <span style="color: #008000">/*</span><span style="color: #008000"> {{{ </span><span style="color: #008000">*/</span><span style="color: #000000">{    ...</span><span style="color: #008000">//</span><span style="color: #008000">省略</span>    function_token->u.op_array =<span style="color: #000000"> CG(active_op_array);    lcname </span>=<span style="color: #000000"> zend_str_tolower_dup(name, name_len);     orig_interactive </span>=<span style="color: #000000"> CG(interactive);    CG(interactive) </span>= <span style="color: #800080">0</span><span style="color: #000000">;    init_op_array(</span>&<span style="color: #000000">op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);    CG(interactive) </span>=<span style="color: #000000"> orig_interactive;      ...</span><span style="color: #008000">//</span><span style="color: #008000">省略</span>     <span style="color: #0000ff">if</span><span style="color: #000000"> (is_method) {        ...</span><span style="color: #008000">//</span><span style="color: #008000">省略,类方法 在后面的章节介绍</span>?!<span style="color: #000000">?GH    } </span><span style="color: #0000ff">else</span><span style="color: #000000"> {        zend_op </span>*opline =<span style="color: #000000"> get_next_op(CG(active_op_array) TSRMLS_CC);          opline</span>->opcode =<span style="color: #000000"> ZEND_DECLARE_FUNCTION;        opline</span>->op1.op_type =<span style="color: #000000"> IS_CONST;        build_runtime_defined_function_key(</span>&opline-><span style="color: #000000">op1.u.constant, lcname,            name_len TSRMLS_CC);        opline</span>->op2.op_type =<span style="color: #000000"> IS_CONST;        opline</span>->op2.u.constant.type =<span style="color: #000000"> IS_STRING;        opline</span>->op2.u.constant.value.str.val =<span style="color: #000000"> lcname;        opline</span>->op2.u.constant.value.str.len =<span style="color: #000000"> name_len;        Z_SET_REFCOUNT(opline</span>->op2.u.constant, <span style="color: #800080">1</span><span style="color: #000000">);        opline</span>->extended_value =<span style="color: #000000"> ZEND_DECLARE_FUNCTION;        zend_hash_update(CG(function_table), opline</span>-><span style="color: #000000">op1.u.constant.value.str.val,            opline</span>->op1.u.constant.value.str.len, &<span style="color: #000000">op_array, </span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(zend_op_array),             (</span><span style="color: #0000ff">void</span> **) &<span style="color: #000000">CG(active_op_array));    } }</span><span style="color: #008000">/*</span><span style="color: #008000"> }}} </span><span style="color: #008000">*/</span><span style="color: #000000"><br /></span>


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:深入懂得PHP内核(六)函数的定义、传参及返回值

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址