TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
2.9 KiB
93 lines
2.9 KiB
<?php
|
|
/**
|
|
* This file is part of Swoole-Compiler(AOT).
|
|
*
|
|
* @link https://www.swoole.com/
|
|
* @contact service@swoole.com
|
|
*/
|
|
|
|
namespace PhpAot\Php\Generator;
|
|
|
|
use PhpParser\NodeAbstract;
|
|
|
|
trait ClosureGenerator
|
|
{
|
|
/**
|
|
* @param $useCurrentScope bool 直接使用当前作用域,C++ 函数将使用 & 捕获所有闭包变量
|
|
*/
|
|
protected function genClosure(NodeAbstract $expr, array $params, callable $bodyGenCb, array $uses = [], bool $useCurrentScope = false): string
|
|
{
|
|
$tmpVar = $this->genTmpVarName();
|
|
$capture = $useCurrentScope ? '&' : '';
|
|
|
|
$code = $this->getIndent() .
|
|
'php::ClosureFn ' . $tmpVar . ' = [' . $capture . ']('
|
|
. 'INTERNAL_FUNCTION_PARAMETERS, '
|
|
. self::TYPE_OBJECT . ' &this_, '
|
|
. self::TYPE_ARGS . ' &vars_) ' .
|
|
'-> ' . self::TYPE_VAR . ' {' . PHP_EOL;
|
|
|
|
if (!$useCurrentScope) {
|
|
$oriLocalVars = $this->localVars;
|
|
$this->localVars = [];
|
|
}
|
|
|
|
$oriArgs = $this->arguments;
|
|
$this->arguments = [];
|
|
$oriInClosure = $this->inClosure;
|
|
$this->inClosure = true;
|
|
|
|
$this->indentLevel++;
|
|
|
|
foreach ($params as $i => $param) {
|
|
if ($param->byRef) {
|
|
$this->fatalError($expr, 'Closure cannot use reference parameter');
|
|
}
|
|
$var = $this->parseIdentifier($param->var);
|
|
$code .= 'auto ' . $var . ' = php::getCallArg(' . $i . ');' . PHP_EOL;
|
|
$this->addArgument($var, self::TYPE_VAR);
|
|
}
|
|
|
|
foreach ($uses as $i => $useItem) {
|
|
$var = $this->parseIdentifier($useItem->var);
|
|
$code .= 'auto ' . $var . ' = vars_.get(' . $i . ');' . PHP_EOL;
|
|
$this->addArgument($var, self::TYPE_VAR);
|
|
}
|
|
|
|
if ($this->methodDef) {
|
|
$this->addArgument('this_', self::TYPE_OBJECT);
|
|
}
|
|
|
|
$code .= $bodyGenCb();
|
|
|
|
$this->indentLevel--;
|
|
$code .= '};' . PHP_EOL;
|
|
|
|
$this->beforeStmtLines[] = $code;
|
|
if (!$useCurrentScope) {
|
|
$this->localVars = $oriLocalVars;
|
|
}
|
|
$this->arguments = $oriArgs;
|
|
$this->inClosure = $oriInClosure;
|
|
|
|
$useVars = [];
|
|
if ($uses) {
|
|
foreach ($uses as $useItem) {
|
|
$var = $this->parseIdentifier($useItem->var);
|
|
if ($this->isVarExpr($useItem->var) and !$this->hasVar($var)) {
|
|
$this->errorUndefinedVariable($useItem->var);
|
|
}
|
|
if ($useItem->byRef) {
|
|
$useVars[] = $this->convertToRef($useItem->var);
|
|
} else {
|
|
$useVars[] = $var;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($this->methodDef) {
|
|
return 'php::newClosure(' . $tmpVar . ', { ' . implode(', ', $useVars) . ' }, this_)';
|
|
}
|
|
return 'php::newClosure(' . $tmpVar . ', { ' . implode(', ', $useVars) . ' })';
|
|
}
|
|
}
|
|
|