diff --git a/src/Php/AstNodeType.php b/src/Php/AstNodeType.php index 69020ae9..e27b5140 100644 --- a/src/Php/AstNodeType.php +++ b/src/Php/AstNodeType.php @@ -142,4 +142,9 @@ trait AstNodeType { return $expr instanceof Expr\Array_ && count($expr->items) === 0; } + + protected function isNull(NodeAbstract $expr): bool + { + return $expr instanceof Node\Expr\ConstFetch && $expr->name->toString() === 'null'; + } } diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index f7461930..3bd7252d 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -1055,11 +1055,14 @@ class CompilerBase extends \PhpAot\Core\Translator } if ($param->default) { if ($param->byRef) { - if (!$this->isEmptyArray($param->default)) { - $this->fatalError($param, 'Default value for parameters passed by reference must be an empty array'); - } else { + if ($this->isEmptyArray($param->default)) { $argInfo->default = 'php::getEmptyArrayRef()'; $argInfo->defaultValue = null; + } elseif ($this->isNull($param->default)) { + $argInfo->default = 'nullptr'; + $argInfo->defaultValue = null; + } else { + $this->fatalError($param, 'Only null and empty array can be used as default value for reference parameter'); } } else { $argInfo->default = $this->parseParamDefaultValue($param->default); diff --git a/src/Php/FuncCallOptimizer.php b/src/Php/FuncCallOptimizer.php index 00f74a06..216069b5 100644 --- a/src/Php/FuncCallOptimizer.php +++ b/src/Php/FuncCallOptimizer.php @@ -12,6 +12,42 @@ use PhpParser\Node; trait FuncCallOptimizer { + public function genFuncGetArgs(string $name, Node\Expr\FuncCall $expr): string + { + $funcDef = $this->functionDef; + $list = []; + foreach ($funcDef->argInfoList as $i => $argInfo) { + if ($argInfo->variadic) { + $tmpVar = $this->addTmpVar(self::TYPE_ARRAY); + $this->context->beforeStmtLines[] = $this->genArray($list) . ';'; + $this->context->beforeStmtLines[] = $tmpVar . '.merge(' . $argInfo->name . ');'; + return $tmpVar; + } + $list[] = $argInfo->name; + } + return $this->genArray($list); + } + + public function genFuncGetArg(string $name, Node\Expr\FuncCall $expr) + { + $position = $expr->args[0]->value; + if ($this->isScalarInt($position)) { + $funcDef = $this->functionDef; + $posInt = intval($position->value); + foreach ($funcDef->argInfoList as $i => $argInfo) { + if ($argInfo->variadic) { + return $argInfo->name . '.offsetGet(' . ($posInt - $i) . ')'; + } + if ($i == $posInt) { + return $argInfo->name; + } + } + $this->fatalError($expr, 'wrong parameter position `' . $posInt . '`'); + } else { + $this->fatalError($expr, 'func_get_arg() only support scalar int'); + } + } + protected function parseFuncCallWithOptimizer(string $name, Node\Expr\FuncCall $expr): string|false { $getArg = function ($i) use ($expr) { @@ -71,41 +107,6 @@ trait FuncCallOptimizer return false; } - public function genFuncGetArgs(string $name, Node\Expr\FuncCall $expr): string - { - $funcDef = $this->functionDef; - $list = []; - foreach ($funcDef->argInfoList as $i => $argInfo) { - if ($argInfo->variadic) { - $tmpVar = $this->addTmpVar(self::TYPE_ARRAY); - $this->context->beforeStmtLines[] = $this->genArray($list) . ';'; - $this->context->beforeStmtLines[] = $tmpVar . '.merge(' . $argInfo->name . ');'; - return $tmpVar; - } - $list[] = $argInfo->name; - } - return $this->genArray($list); - } - - public function genFuncGetArg(string $name, Node\Expr\FuncCall $expr) - { - $position = $expr->args[0]->value; - if ($this->isScalarInt($position)) { - $funcDef = $this->functionDef; - $posInt = intval($position->value); - foreach ($funcDef->argInfoList as $i => $argInfo) { - if ($argInfo->variadic) { - return $argInfo->name . '.offsetGet(' . ($posInt - $i) . ')'; - } elseif ($i == $posInt) { - return $argInfo->name; - } - } - $this->fatalError($expr, 'wrong parameter position `' . $posInt . '`'); - } else { - $this->fatalError($expr, 'func_get_arg() only support scalar int'); - } - } - protected function genFuncNumArgs(string $name, Node\Expr\FuncCall $expr): string { $funcDef = $this->functionDef; diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 4b95e3bf..236588bf 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -106,7 +106,7 @@ class Preprocessor extends CompilerBase $type = $v->getType(); switch ($type) { case 'Stmt_Namespace': - $this->prepareNamespaceDef($v); + $this->prepareNamespace($v); break; case 'Stmt_Enum': case 'Stmt_Class': @@ -161,7 +161,7 @@ class Preprocessor extends CompilerBase $this->symbolCallInFile[$this->file] = array_unique($this->symbolCallInFile[$this->file]); } - protected function prepareNamespaceDef(Node\Stmt\Namespace_ $node): void + protected function prepareNamespace(Node\Stmt\Namespace_ $node): void { $this->resetNamespace(); $this->namespace = $node->name ? $this->parseIdentifier($node->name) : ''; diff --git a/src/Php/Translator.php b/src/Php/Translator.php index ac41a099..9a37973b 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -17,6 +17,7 @@ use PhpAot\Php\Entity\InterfaceDef; use PhpAot\Php\Entity\MethodDef; use PhpAot\Php\Entity\PropertyDef; use PhpAot\Php\Exception\Redo; +use PhpAot\Php\Exception\Unsupported; use PhpParser\Modifiers; use PhpParser\Node; use PhpParser\Node\Stmt\Foreach_; @@ -825,6 +826,9 @@ class Translator extends Preprocessor case 'Stmt_Interface': $code .= $this->parseInterface($v2) . PHP_EOL; break; + case 'Stmt_Trait': + $code .= $this->parseTrait($v2) . PHP_EOL; + break; default: abort($v2); } @@ -1363,4 +1367,9 @@ class Translator extends Preprocessor return $code; } + + protected function parseTrait(Node\Stmt\Trait_ $trait) + { + throw new Unsupported('Unsupported Trait '); + } }