fix(php): 修复存根文件函数返回类型检查和类方法处理逻辑

- 修复存根文件中魔术方法(__construct/__destruct/__clone)不需要声明返回类型的问题
- 在FunctionDef构造函数中添加stub参数传递
- 修正main函数参数类型检查逻辑,添加逻辑非运算符
- 移除类方法中重复的'this_'参数添加,在stub函数处理后重新添加
- 添加stub函数的特殊处理逻辑,无具体实现时重置函数定义
- 修复类方法名称处理中的变量引用问题
pull/1/head
韩天峰 5 months ago
parent b0a6898ca8
commit b8516b6ac0
  1. 13
      examples/project/ext.cc
  2. 10
      examples/project/ext.stub.php
  3. 6
      examples/project/main.php
  4. 24
      src/Php/CompilerBase.php
  5. 6
      src/Php/Entity/FunctionDef.php
  6. 3
      src/Php/Preprocessor.php

@ -1,4 +1,5 @@
#include <phpx.h> #include <phpx.h>
#include <iostream>
#include "phpx_func.h" #include "phpx_func.h"
using namespace php; using namespace php;
@ -9,3 +10,15 @@ Int php_fn_test(Int a, Int b) {
var_dump(php_uname()); var_dump(php_uname());
return c; return c;
} }
static php::Str prop_base {ZEND_STRL("base"), true};
void php_foo____construct(php::Object& this_, php::Int value) {
std::cout << "hashCode: " << prop_base.str()->h << "\n";
this_.setProperty(prop_base, value);
}
php::Int php_foo__bar(php::Object &this_, php::Int a, php::Int b) {
std::cout << "hashCode: " << prop_base.str()->h << "\n";
return this_.getProperty(prop_base).toInt() + a + b;
}

@ -2,3 +2,13 @@
function fn_test(int $a, int $b): int function fn_test(int $a, int $b): int
{ {
} }
class Foo {
public int $base = 0;
public function __construct(int $base)
{
}
public function bar(int $a, int $b): int
{
}
}

@ -1,5 +1,5 @@
<?php <?php
function main($argc, array $argv) function main(int $argc, array $argv)
{ {
var_dump($argc, $argv); var_dump($argc, $argv);
fn1(); fn1();
@ -9,4 +9,8 @@ function main($argc, array $argv)
echo $r; echo $r;
} }
var_dump(gettype($rs)); var_dump(gettype($rs));
var_dump("c++ class:");
$o = new Foo(1000);
var_dump($o->bar(123, 342));
} }

@ -804,8 +804,12 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function parseFunctionDecl(Node\Stmt\Function_|Node\Stmt\ClassMethod $v): FunctionDef protected function parseFunctionDecl(Node\Stmt\Function_|Node\Stmt\ClassMethod $v): FunctionDef
{ {
// .stub 存根定义 C++ Native 函数,必须设置返回值类型 // .stub 存根定义 C++ Native 函数,必须设置返回值类型
if (!$v->returnType && $this->stubFile) { if ($this->stubFile and !$v->returnType) {
$this->fatalError($v, 'The return type of the function `' . $v->name . '` must be specified'); // 以下魔术方法都不能声明返回值类型 __construct()/__destruct()/__clone()
if (($this->method and !in_array($this->method, ['__construct', '__destruct', '__clone'])) or !$this->method) {
$name = $this->class ? $this->class . '::' . $v->name : $v->name;
$this->fatalError($v, 'The return type of the function `' . $name . '` must be specified');
}
} }
// 返回值不能是引用类型 // 返回值不能是引用类型
if ($v->byRef) { if ($v->byRef) {
@ -814,7 +818,7 @@ class CompilerBase extends \PhpAot\Core\Translator
$fnName = $this->parseIdentifier($v->name); $fnName = $this->parseIdentifier($v->name);
$returnType = $this->parseTypeDecl($v->returnType, self::DECL_TYPE_OF_RETURN); $returnType = $this->parseTypeDecl($v->returnType, self::DECL_TYPE_OF_RETURN);
$functionDef = new FunctionDef($fnName, $returnType, $this->namespace); $functionDef = new FunctionDef($fnName, $returnType, $this->namespace, $this->stubFile);
$this->functionDef = $functionDef; $this->functionDef = $functionDef;
$this->parseParams($v->params, $functionDef); $this->parseParams($v->params, $functionDef);
@ -828,10 +832,10 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($returnType !== self::TYPE_VOID) { if ($returnType !== self::TYPE_VOID) {
$this->fatalError($v, 'main function must return void'); $this->fatalError($v, 'main function must return void');
} }
if ($this->checkArgType($functionDef->argInfoList[0]->type, self::TYPE_INT)) { if (!$this->checkArgType($functionDef->argInfoList[0]->type, self::TYPE_INT)) {
$this->fatalError($v, 'The first parameter of the main function must be of type `int`.'); $this->fatalError($v, 'The first parameter of the main function must be of type `int`.');
} }
if ($this->checkArgType($functionDef->argInfoList[1]->type, self::TYPE_ARRAY)) { if (!$this->checkArgType($functionDef->argInfoList[1]->type, self::TYPE_ARRAY)) {
$this->fatalError($v, 'The second parameter of the main function must be of type `array`.'); $this->fatalError($v, 'The second parameter of the main function must be of type `array`.');
} }
} }
@ -861,7 +865,6 @@ class CompilerBase extends \PhpAot\Core\Translator
// 类方法不要保存到 functions 中 // 类方法不要保存到 functions 中
if ($this->class) { if ($this->class) {
$this->addArgument('this_', self::TYPE_OBJECT);
if ($this->methodDef) { if ($this->methodDef) {
$this->functionDef->method = true; $this->functionDef->method = true;
$this->methodDef->functionDef = $this->functionDef; $this->methodDef->functionDef = $this->functionDef;
@ -870,6 +873,15 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->functionDefineInFile[$name] = $this->functionDef; $this->functionDefineInFile[$name] = $this->functionDef;
} }
// stub 函数,没有函数的具体实现,只有声明,实现在 C++ 或者 .so 中定义
if ($this->functionDef->stub) {
$this->resetFunction();
return '';
}
if ($this->class) {
$this->addArgument('this_', self::TYPE_OBJECT);
}
foreach ($this->functionDef->argInfoList as $argInfo) { foreach ($this->functionDef->argInfoList as $argInfo) {
$this->addArgument($argInfo->name, $argInfo->type); $this->addArgument($argInfo->name, $argInfo->type);
} }

@ -21,15 +21,17 @@ class FunctionDef
public array $argInfoList = []; public array $argInfoList = [];
public int $argCountRequired = 0; public int $argCountRequired = 0;
public string $params = ''; public string $params = '';
public string $namespace = ''; public string $namespace;
public bool $method = false; public bool $method = false;
public bool $stub = false;
public bool $completed = false; public bool $completed = false;
public function __construct(string $name, string $returnType, string $namespace = '') public function __construct(string $name, string $returnType, string $namespace, bool $stub)
{ {
$this->name = $name; $this->name = $name;
$this->returnType = $returnType; $this->returnType = $returnType;
$this->namespace = $namespace; $this->namespace = $namespace;
$this->stub = $stub;
} }
public function getNamespacedName(): string public function getNamespacedName(): string

@ -266,6 +266,7 @@ class Preprocessor extends CompilerBase
protected function prepareMethod(Node\Stmt\ClassMethod $v, Node\Stmt\Class_|Node\Stmt\Trait_|Node\Stmt\Enum_ $class): void protected function prepareMethod(Node\Stmt\ClassMethod $v, Node\Stmt\Class_|Node\Stmt\Trait_|Node\Stmt\Enum_ $class): void
{ {
$this->method = $v->name;
$abstract = $v->flags & Modifiers::ABSTRACT; $abstract = $v->flags & Modifiers::ABSTRACT;
if (!$abstract) { if (!$abstract) {
$this->prepareFunction($v) . PHP_EOL; $this->prepareFunction($v) . PHP_EOL;
@ -276,7 +277,7 @@ class Preprocessor extends CompilerBase
} }
$fullClassName = $this->getFullClassName(); $fullClassName = $this->getFullClassName();
$fullMethodName = $fullClassName . '::' . $v->name; $fullMethodName = $fullClassName . '::' . $this->method;
$this->classMethodOverride[strtolower($fullMethodName)] = false; $this->classMethodOverride[strtolower($fullMethodName)] = false;
// 查找父类是否有同名方法,递归查找 // 查找父类是否有同名方法,递归查找
$fullClassNameLower = strtolower($fullClassName); $fullClassNameLower = strtolower($fullClassName);

Loading…
Cancel
Save