From 68155d0793f9a915839a83da2bdbccb117802cab Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 8 Apr 2026 15:47:30 +0800 Subject: [PATCH] =?UTF-8?q?feat(compiler):=20=E6=B7=BB=E5=8A=A0=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E7=B1=BB=E5=9E=8B=E6=A3=80=E6=9F=A5=E5=92=8C=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E7=B1=BB=E5=9E=8B=E9=AA=8C=E8=AF=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在ArgInfo类中新增class属性用于存储类型信息 - 修改parseParameterType方法以传递ArgInfo对象并设置类名 - 添加对stdClass和ArrayObject类型的测试用例 - 实现参数类型验证逻辑,确保对象类型匹配 - 增强类型转换过程中对对象类型的检测和错误提示 - 优化数组维度赋值的处理逻辑 --- src/Php/ArgInfo.php | 1 + src/Php/CompilerBase.php | 22 ++++++++++++++++----- tests/aot/type_hits/001.phpt | 37 ++++++++++++++++++++++++++++++++++++ tests/aot/type_hits/002.phpt | 23 ++++++++++++++++++++++ 4 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 tests/aot/type_hits/001.phpt create mode 100644 tests/aot/type_hits/002.phpt diff --git a/src/Php/ArgInfo.php b/src/Php/ArgInfo.php index 35fae7eb..54dde567 100644 --- a/src/Php/ArgInfo.php +++ b/src/Php/ArgInfo.php @@ -16,6 +16,7 @@ class ArgInfo public string $type; public string $default = ''; public ?Expr $defaultValue = null; + public string $class = ''; public bool $byRef = false; public bool $variadic = false; public bool $nullable = false; diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 7450781c..b77a7ffd 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -1064,13 +1064,13 @@ class CompilerBase extends \PhpAot\Core\Translator if ($this->method and $name == 'this_') { $this->fatalError($param, 'Cannot use `$this` as parameter of class method'); } - $type = $this->parseParameterType($param, $name); + $argInfo = new ArgInfo(); + $type = $this->parseParameterType($param, $argInfo, $name); if ($param->variadic) { $list[] = self::TYPE_ARRAY . ' ' . $name; } else { $list[] = $type . ' ' . $name; } - $argInfo = new ArgInfo(); $argInfo->name = $name; $argInfo->type = $type; $argInfo->byRef = $param->byRef; @@ -1447,6 +1447,9 @@ class CompilerBase extends \PhpAot\Core\Translator $this->fatalError($left, 'Cannot use [] for strings'); } } + if ($this->isScalar($right) or $this->isVarExpr($right)) { + return $this->parseAssignArrayDim($left, $right); + } } return $var . ' = ' . $this->convertExprType($expr, $this->detectExprType($left), $this->detectExprType($right)); @@ -1980,7 +1983,7 @@ class CompilerBase extends \PhpAot\Core\Translator '}'; } - protected function parseParameterType(Node\Param $param, string $var): string + protected function parseParameterType(Node\Param $param, ArgInfo $argInfo, string $var): string { if ($param->byRef) { return self::TYPE_REF; @@ -1998,7 +2001,9 @@ class CompilerBase extends \PhpAot\Core\Translator } elseif (isset($this->zendTypeMap[$typeName])) { return $this->getTypeFromZendType($typeName); } else { - $this->addObject($var, $this->getNamespacedClassName($typeName)); + $class = $this->getNamespacedClassName($typeName); + $this->addObject($var, $class); + $argInfo->class = $class; return self::TYPE_OBJECT; } } @@ -3257,7 +3262,7 @@ class CompilerBase extends \PhpAot\Core\Translator return $this->functionDef->returnType; } - protected function getTypeConvertedArg($arg, ArgInfo $argInfo): string + protected function getTypeConvertedArg(Node\Arg $arg, ArgInfo $argInfo): string { $expr = $this->parseArg($arg); $type = $this->detectExprType($arg->value); @@ -3267,6 +3272,13 @@ class CompilerBase extends \PhpAot\Core\Translator } if ($argInfo->type === self::TYPE_OBJECT) { + $object = $this->parseVariable($arg->value); + if ($this->isVarExpr($arg->value) and $this->isTypedObject($object)) { + $class = $this->getObjectType($object); + if ($argInfo->class and $class != $argInfo->class) { + $this->fatalError($arg, "Argument `{$argInfo->name}` must be an instance of `{$argInfo->class}`, `{$class}` given"); + } + } return $this->convertObjectExpr($expr); } diff --git a/tests/aot/type_hits/001.phpt b/tests/aot/type_hits/001.phpt new file mode 100644 index 00000000..a695560b --- /dev/null +++ b/tests/aot/type_hits/001.phpt @@ -0,0 +1,37 @@ +--TEST-- +type hits +--FILE-- +name = "John"; + $obj->age = 20; + foo($obj); + + $arr = new ArrayObject(); + $name = "John"; + $arr["name"] = $name; + $arr["age"] = 20; + foo($arr); +} +?> +--EXPECT-- +object(stdClass)#1 (2) { + ["name"]=> + string(4) "John" + ["age"]=> + int(20) +} +object(ArrayObject)#2 (1) { + ["storage":"ArrayObject":private]=> + array(2) { + ["name"]=> + string(4) "John" + ["age"]=> + int(20) + } +} diff --git a/tests/aot/type_hits/002.phpt b/tests/aot/type_hits/002.phpt new file mode 100644 index 00000000..89427c55 --- /dev/null +++ b/tests/aot/type_hits/002.phpt @@ -0,0 +1,23 @@ +--TEST-- +type hits +--FILE-- +name = "John"; + $obj->age = 20; + foo($obj); +} +?> +--EXPECT-- +object(stdClass)#1 (2) { + ["name"]=> + string(4) "John" + ["age"]=> + int(20) +}