4.1 KiB
Python 工具子模块
TypePHP 将 Python IDE helper 生成器和 Python 源码转换器集成到了 tpc。两者位于独立的
src/PythonTools 目录,只复用 tpc 命令入口,不进入正常的 PHP 预处理、C++ 生成和编译流水线。
Python namespace IDE helper
./tpc --gen-python-helper math
./tpc --gen-python-helper numpy.linalg
./tpc --gen-python-helper numpy --output-dir .ide-helper
命令通过 PHPy 导入指定 Python module,并使用 Python inspect API 采集函数、参数、类、方法和
module attribute。PHPy 扩展以及目标 Python module 必须安装在执行 tpc 的主机环境中。
默认生成文件位于当前目录的 ide-helper 中。--output-dir 可以替换这个输出根目录,既支持
相对当前目录的路径,也支持绝对路径:
ide-helper/python/math.php
ide-helper/python/numpy/linalg.php
ide-helper/PyObject.php
首次生成 module helper 时,会同时生成公共的 PyObject.php。它包含 PyObject 的动态访问、调用、
数组访问、迭代以及 toArray()、toValue() 等方法提示,供所有 Python module helper 共享。若该文件
已经存在,生成器会保留原文件,不进行覆盖。
生成内容使用 TypePHP 的 module-as-namespace 形式,例如 python\math\sqrt(),并兼容普通
use、use function 和 use const 的 IDE 名称解析。文件末尾包含 die,用于在误执行时明确
终止程序。helper 只能交给 IDE 索引,不能被 include,也不能加入 TypePHP 项目的 sources 或编译输入。
PyObject::IDE_HELPER_ONLY 是所有 helper 共用的提示常量。非 void stub 的方法体使用
die(\PyObject::IDE_HELPER_ONLY),以满足 IDE 对返回类型控制流的检查,不会再产生“缺少 return
语句”的诊断。module attribute 使用命名空间 const 声明,支持 IDE 的常量补全和 use const。
PHP 8.1 及以上允许在常量初始化表达式中使用 new。module attribute 因此直接使用仅供 IDE
分析的 PyObject 实例作为占位值:
const pi = new \PyObject();
这样 IDE 会将常量精确识别为 PyObject,而不是从 null 推断出错误类型。
公共 PyObject helper 还声明了 TypePHP 的虚拟关键词方法,包括 toInt()、toFloat()、
toString()、toBool()、toStream()、高精度类型转换、toObject()、toAny() 和 toRef()。
这些声明仅用于 IDE 补全;调用会在编译期展开,并不是 PHPy PyObject 运行时类的实体方法。
toArray() 和 toValue() 则仍是 PHPy 提供的真实方法。
Python class 的构造函数会显式调用 parent::__construct()。Python 对象若定义了 count(),helper
不会重复声明它,因为 PyObject::count(): int 已用于 PHP Countable。需要调用 Python 自身的
count() 时,应显式写为 $object->__call('count', $arguments)。
PHP function/class 名称大小写不敏感,而 Python 名称大小写敏感;PHP 保留字也不能声明为普通 stub symbol。生成器会以注释报告无法用合法 PHP 声明表达的符号,不会擅自重命名 Python API。
Python 转 TypePHP
./tpc --convert-python-to-php script.py > script.php
转换器调用 PATH 中的 python3 解析 Python AST,然后输出使用 TypePHP Python namespace
语法的 PHP 源码。普通 module import 会转换为 namespace import:
import math
print(math.sqrt(16))
use python\math;
function main(): void
{
python\print(math\sqrt(16));
}
当前支持普通 import、函数、赋值、调用、容器字面量、基础运算、单项比较、if/while/for、 lambda 和基础 f-string。module 顶层变量会转换为 PHP global,以保持函数读取 module 变量的能力。
转换器遵循“不能可靠保持语义就拒绝”的原则。class、async、generator、try/with、decorator、 destructuring assignment、chained comparison、嵌套函数以及 loop-else 等尚未完成的语法会抛出带 源文件和行号的错误,不会生成看似可用但语义错误的 PHP 代码。