Skip to content

Commit a5b413b

Browse files
committed
finish defer
1 parent 5acabed commit a5b413b

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

try/defer.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ statement:
4646
;
4747
```
4848
修改完这两个文件后需要分别调用re2c、yacc生成对应的C文件,具体的生成命令可以在Makefile.frag中看到:
49-
```c
49+
```sh
5050
$ re2c --no-generation-date --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l
5151
$ yacc -p zend -v -d Zend/zend_language_parser.y -oZend/zend_language_parser.c
5252
```
@@ -294,4 +294,62 @@ ZEND_API int pass_two(zend_op_array *op_array)
294294
295295
__(5)定义ZEND_DEFER_CALL、ZEND_DEFER_CALL_END指令的handler__
296296
297+
ZEND_DEFER_CALL指令执行时需要将return的位置保存下来,我们把这个值保存到zend_execute_data结构中:
298+
```c
299+
//zend_compile.h
300+
struct _zend_execute_data {
301+
...
302+
const zend_op *return_opline;
303+
...
304+
}
305+
```
306+
opcode的handler定义在zend_vm_def.h文件中,定义完成后需要执行`php zend_vm_gen.php`脚本生成具体的handler函数。
307+
```c
308+
ZEND_VM_HANDLER(173, ZEND_DEFER_CALL, ANY, ANY)
309+
{
310+
USE_OPLINE
311+
312+
//1) 将return指令的位置保存到EX(return_opline)
313+
EX(return_opline) = opline + 1;
314+
315+
//2) 跳转
316+
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op1));
317+
ZEND_VM_CONTINUE();
318+
}
319+
320+
ZEND_VM_HANDLER(174, ZEND_DEFER_CALL_END, ANY, ANY)
321+
{
322+
USE_OPLINE
323+
324+
ZEND_VM_SET_OPCODE(EX(return_opline));
325+
ZEND_VM_CONTINUE();
326+
}
327+
```
328+
到目前为止我们已经完成了全部的修改,重新编译PHP后就可以使用defer语法了:
329+
```php
330+
function shutdown($a){
331+
echo $a."\n";
332+
}
333+
function test(){
334+
$a = 1234;
335+
defer shutdown($a);
336+
337+
$a = 8888;
338+
339+
if(1){
340+
return "mid end\n";
341+
}
342+
defer shutdown("9999");
343+
return "last end\n";
344+
}
345+
346+
echo test();
347+
```
348+
执行后将显示:
349+
```sh
350+
8888
351+
mid end
352+
```
353+
这里我们只实现了普通函数调用的方式,关于成员方法、静态方法、匿名函数等调用方式并未实现,留给有兴趣的读者自己去实现。
297354

355+
完整代码:[https://github.com/pangudashu/php-7.0.12](https://github.com/pangudashu/php-7.0.12)

0 commit comments

Comments
 (0)