# tphp **Repository Path**: kllxs_admin/tphp ## Basic Information - **Project Name**: tphp - **Description**: 一个零依赖的 PHP AOT 编译器 —— 将 PHP-like 源码编译为原生 x86-64 可执行文件,支持Windows、Linux、macOS等平台。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2025-08-08 - **Last Updated**: 2026-06-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # TinyPHP > 一个零依赖的 PHP AOT 编译器 —— 将 PHP-like 源码直接编译为原生 x86-64 可执行文件 [![Language](https://img.shields.io/badge/language-PHP%208.1+-blue)](https://www.php.net/) [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE) ## 特性 - **零依赖**:无需 LLVM、GCC、链接器,编译器本身完全用 PHP 编写 - **AOT 编译**:源码直接生成 x86-64 机器码,输出原生 PE (Windows) 或 ELF (Linux) 可执行文件 - **强类型**:语法参考 PHP,但所有变量必须在声明时确定类型,编译期类型推断 - **双平台**:Windows (Win32 API / PE32+) 和 Linux (syscall / ELF64) 代码生成 - **多文件编译**:支持多文件 + 多命名空间 + `use` 导入 - **OOP**:支持 class 定义、`new` 实例化、方法调用、`$this`、`__construct`/`__destruct` ## 快速开始 ```bash # 单文件编译 php tphp.php test/main/main.php .\main.exe # Windows ./main # Linux # 多文件编译 php tphp.php test/files/main.php test/files/demo.php test/files/name.php .\main.exe # 目录编译(自动扫描所有 .php 文件,main.php 作为入口) php tphp.php . # 指定目标平台 php tphp.php test/main/main.php --target=windows -o hello.exe php tphp.php test/main/main.php --target=linux -o hello ``` ## 命令行 ``` 用法: php tphp.php [options] 选项: --target= 目标平台: linux 或 windows (默认: 当前系统) -o 输出文件路径 (默认: 入口文件去掉 .php) -h, --help 显示帮助 ``` ## 语言参考 ### 程序结构 ```php hello(); // 调用对象方法 } ``` ### 变量与类型 所有变量 **必须初始化**,强类型推断,声明后类型不变: | 类型 | 内存布局 | 说明 | 示例 | | ----------- | --------------- | ------------------------ | ---------------------------- | | `int` | 8 字节 (i64) | 64 位有符号整数 | `$a = 1;` | | `float` | 8 字节 (f64) | IEEE 754 双精度浮点 | `$b = 1.0;` | | `string` | 16 字节 (ptr+len)| UTF-8 字符串 | `$c = 'hello world🚀';` | | `bool` | 8 字节 | 布尔值 | `$e = true;` | | `null` | 8 字节 | 空值 | `$f = null;` | | `callable` | 8 字节 (fn ptr) | 匿名函数/闭包 | `$g = function(int $a, int $b): int { ... };` | | `array` | 16 + 元素空间 | 强类型元素数组 | `$arr = array("int", [1,2,3]);` | | `object` | 8 字节 (handle) | 类实例 | `$obj = new MyClass();` | ```php $d; // ❌ 编译错误:变量不能未初始化 ``` ### 函数 支持用户自定义函数、多命名空间函数和 `use function` 导入: ```php // 同一命名空间内直接调用 function add(int $a, int $b): int { return $a + $b; } // 跨命名空间调用 namespace Main; use function Demo\myDemo; function main(): void { myDemo(); // 调用 Demo\myDemo() $c = add(1, 2); // 调用本命名空间的函数 var_dump($c); // (int) 3 } ``` ### 类与对象 支持 class 定义、`public`/`private` 方法、构造/析构函数: ```php class MyClass { public function __construct() { var_dump("constructed"); } public function hello(): void { $this->priv(); // $this 调用私有方法 var_dump("hello"); } private function priv(): void { var_dump("private method"); } public function __destruct() { var_dump("destructed"); } } // 使用 $obj = new MyClass(); // 输出: (string) constructed $obj->hello(); // 输出: (string) private method // (string) hello // 离开作用域时自动调用 __destruct() // 输出: (string) destructed ``` ### 数组 数组是强类型的,声明时指定元素类型,最大容量 64 个元素: ```php $a = array("int", [1, 2, 3]); // int 数组 var_dump($a); // (array(int)) [1, 2, 3] var_dump(count($a)); // (int) 3 var_dump($a[1]); // (int) 2 $a[] = 4; // 追加元素 unset($a[1]); // 删除元素 // callback 数组 — 存储闭包 $b = array("callback", [ function (int $a, int $b): int { return $a + $b; }, function (string $a, string $b): string { return $a . $b; }, ]); var_dump($b[0](1, 2)); // (int) 3 var_dump($b[1]("hello", "world")); // (string) helloworld ``` ### 闭包 闭包必须有强类型参数和返回值声明,支持通过变量或数组索引调用: ```php $add = function (int $a, int $b): int { return $a + $b; }; var_dump($add(1, 2)); // (int) 3 ``` ### 常量与输出 ```php // 常量:值不可变,作用域 namespace 内有效 const PI = 3.1415926; const RED = "red"; function main(): void { echo PI . "\n"; // 3.141593 echo RED . "\n"; // red } ``` ### 类型转换 ```php // (int) 类型转换 echo (int)3.999 . "\n"; // 3 浮点截断 echo (int)"123abc" . "\n"; // 123 前导数字 echo (int)"abc123" . "\n"; // 0 非数字开头 echo (int)true . "\n"; // 1 echo (int)false . "\n"; // 0 echo (int)null . "\n"; // 0 // 对象不能转换为 int // echo (int)$obj . "\n"; // Error: Object cannot be converted to int ``` ### 控制流 ```php // if / else if / else if ($a > 0) { var_dump($a); } else if ($a == 0) { var_dump("zero"); } else { var_dump($b); } // while while ($a < 10) { $a = $a + 1; } // for for ($i = 0; $i < 10; $i++) { if ($i == 5) { break; } } // switch switch ($cmd) { case 1: print("start\n"); break; default: print("unknown\n"); } ``` ### 表达式 ```php // 算术 $a + $b; $a - $b; $a * $b; $a / $b; $a % $b; // 比较 $a == $b; $a === $b; $a != $b; $a !== $b; $a < $b; $a > $b; $a <= $b; $a >= $b; // 自增/自减 $a++; $a--; // 字符串拼接 $c . $c . "-$c"; ``` ### 内置函数 | 函数/关键字 | 说明 | | ------------ | -------------------- | | `var_dump()` | 输出值和类型信息 | | `strlen()` | 返回字符串字节长度 | | `count()` | 返回数组元素个数 | | `echo` | 输出表达式(同 print) | | `print` | 输出表达式 | | `const` | 定义命名空间级常量 | | `(int)` | 类型转换为整数 | ## 架构 ``` 源码 (.php × N) │ ▼ Compiler (多文件合并、命名空间/导入解析) │ ▼ Lexer (词法分析) → Token 流 │ ▼ Parser (语法分析) → AST (Pratt Parser) │ ▼ CodeGenerator → x86-64 机器码 (X64Builder) │ │ ▼ ▼ PEWriter ELFWriter (Windows) (Linux) │ │ ▼ ▼ Win32 API syscall (kernel32) (write, exit) │ │ └─────┬─────┘ ▼ 原生可执行文件 (.exe / ELF) ``` **编译器运行时不需要任何外部工具**——直接生成机器码和 PE/ELF 头部,包含完整的 IAT 导入表。 ### 双平台对比 | 特性 | Windows | Linux | | ---------- | --------------------------- | ------------------------ | | 输出格式 | PE32+ | ELF64 | | 输出方式 | Win32 API (WriteFile) | syscall (write, exit) | | 调用约定 | Microsoft x64 (RCX,RDX,R8,R9)| System V (RDI,RSI,RDX,RCX) | | 字符串存储 | .rdata 段,RIP 相对寻址 | .text 段末尾内嵌 | | 字符串拼接 | HeapAlloc + rep movsb | 顺序输出 | | IAT 导入 | kernel32.dll (6 个函数) | 不需要 | ## 源码结构 ``` tphp/ ├── tphp.php # CLI 入口:参数解析、多文件扩展、编译调度 ├── src/ │ ├── AST.php # AST 节点定义 + TphpType 类型枚举 │ ├── Token.php # Token 数据结构 │ ├── TokenType.php # Token 类型枚举 │ ├── Lexer.php # 词法分析器 │ ├── Parser.php # 语法分析器 (Pratt parser) │ ├── X64Builder.php # x86-64 机器码构建器 │ ├── CodeGenerator.php # 代码生成 (Linux / syscall) │ ├── CodeGeneratorWindows.php # 代码生成 (Windows / Win32 API) │ ├── Compiler.php # 编译流程编排 + 多文件合并 │ ├── ELFWriter.php # ELF64 二进制写入器 │ └── PEWriter.php # PE32+ 二进制写入器 └── test/ ├── main/ # 基础功能测试 │ ├── main.php # 最小示例 │ └── function.php # 多函数定义/调用 ├── var/ # 变量/数组/类型测试 │ ├── var.php # 综合功能演示 │ │ float.php # 浮点数输出 │ │ array.php # 数组功能演示 │ │ type_conversion.php # 类型转换测试 │ └── const.php # 常量测试 ├── files/ # 多文件/命名空间/OOP 测试 │ ├── main.php # 入口(use 导入、new、方法调用) │ ├── demo.php # Demo 命名空间 + class MyDemo │ └── name.php # MyAdmin\Name 命名空间函数 └── control_flow/ # 控制流测试 ├── string.php # if/for/switch/break/=== 综合 └── int.php # 整数控制流 ``` ## 路线图 - [x] **多函数定义与调用**:支持多个用户自定义函数 - [x] **多文件编译**:多文件 + 多命名空间 + `use` 导入 - [x] **Class / OOP**:class 定义、`new`/`$this`/`->`、构造/析构、public/private - [x] **控制流**:`for` / `switch` / `else if` / `break` / `===` / `!==` / `$i++` - [x] **类型转换**:`(int)float/string/bool/null/array` - [x] **常量**:`const` 声明 + 引用 - [x] **echo**:同 print,无需括号 - [ ] **continue** / **foreach** / **(float)/(string) 转换**:继续完善 - [ ] **C 动态库调用 (FFI)**:运行时加载 `.dll` / `.so` - [ ] **浮点精度输出**:ftoa 支持小数部分 ### C 动态库调用 (FFI) 支持在 tphp 中调用 C 编译的动态库(`.dll` / `.so`),无需链接器。 **目标语法:** ```php