illegalstudio/elephc
GitHub: illegalstudio/elephc
elephc 是一个将 PHP 代码编译为原生二进制文件的编译器,解决了 PHP 依赖运行时和性能限制的问题。
Stars: 208 | Forks: 6
# elephc
一个 PHP 到原生代码的编译器。接收一个 PHP 子集并直接将其编译为原生汇编代码,为当前支持的目标平台生成独立的二进制文件:**macOS ARM64**、**Linux ARM64** 和 **Linux x86_64**。无解释器,无虚拟机,无 Zend 引擎,无 opcode 回退机制。
## PHP 中的异步 HTTP 服务器
一个异步 HTTP/1.1 服务器 —— 一个非阻塞的 `poll()` 事件循环,每个连接对应一个 Fiber,通过 `extern` FFI 访问原始 TCP 套接字,外加一个 HTTP 解析器和路由器 —— 完全用 PHP 编写并编译为单个原生二进制文件。无解释器,无 PHP-FPM,无 Nginx。

参见 [showcases/http-server/](showcases/http-server/) 获取完整源代码和构建说明。
## 用 PHP 渲染 DOOM
旗舰展示:一个实时 3D 渲染器,加载原始 DOOM WAD 文件并渲染 E1M1 —— BSP 遍历、透视投影、逐列雾效、区域光照、碰撞检测、台阶攀爬 —— 完全用 PHP 编写并编译为原生二进制文件。

参见 [showcases/doom/](showcases/doom/) 获取完整源代码和构建说明。
## 为什么做这个
我第一本“严肃编程”的书是《PHP 4 和 MySQL》。经过多年的代码实验,那本书将我的热情变成了职业。在过去的 20 年里,我使用过许多语言,但 PHP 是最持续让我养家糊口的语言。
PHP 拥有简单、平易近人且优雅的语法。全球数百万开发者已经非常熟悉它。这使它成为一个理想的桥梁,能让 Web 开发者更接近底层编程 —— 系统级工作、原生二进制文件、理解底层原理 —— 而无需他们首先学习一门全新的语言。
我一直怀念 PHP 的一点是它能够生成优化、快速的原生二进制文件。当其他人都在忙着构建下一个 Facebook 时,我想我可以尝试填补这个空白,为 PHP 编写一个编译器。
当然,在性能关键或系统级工作方面,PHP 有其局限性。这就是为什么 elephc 引入了编译器扩展,如用于扁平 POD 记录的 `packed class`、用于连续类型化数组的 `buffer`、用于原始内存访问的 `ptr` 以及用于 FFI 的 `extern` —— 这些构造为 PHP 开发者提供了所需的工具,而无需放弃他们已经熟悉的语言。
它并不完美,但**它确实有效**。这是一个坚实的起点,更重要的是,它是理解**编译器如何工作**以及汇编语言如何在底层运作的绝佳方式。
我尽可能将项目设计得模块化。每个函数都有其自己的代码生成文件,并且每个文件都**逐行注释**,因此你可以清楚地看到一个高级构造如何被翻译成其低级等价物。
## 你可以期待什么
你可以使用 [文档](docs/) 中记录的构造来编写 PHP。支持单继承的类、接口、`instanceof`、空值安全访问 (`?->`)、抽象类、final 类、方法以及类型化/静态属性、PHP 风格的静态属性重声明、构造函数属性提升、trait、构造函数、实例/静态方法、函数/类/方法的大小写不敏感 PHP 符号查找、具有后期静态绑定的 `self::` / `parent::` / `static::`、`readonly` 属性和类、枚举、声明上的 PHP 8 属性、命名参数、一等公民可调用对象、类型化的函数和方法参数及返回值、`try` / `catch` / `finally` / `throw`、可见性修饰符、联合和可空类型、写时复制数组、具有 PHP 插入顺序和整数/字符串数字键规范化的关联数组、带 `+` 的数组联合、闭包、带 `yield` / `yield from` 的生成器函数和生成器闭包、命名空间、包含、编译期 Composer/SPL 自动加载、类/内省辅助函数,以及在 macOS ARM64、Linux ARM64 和 Linux x86_64 上的 PHP 8.1 风格 `Fiber` 协程。
对于面向性能的代码,elephc 提供了超越标准 PHP 的编译器扩展 —— 参见上面的“为什么”部分。
然后编译并运行:
```
elephc myfile.php
./myfile
```
该编译器是实验性的且在不断演进。并非 PHP 支持的所有内容都已实现,并且你会遇到 bug。但正如 DOOM 展示所演示的,你现在就可以用它构建真实的、非简单的程序。
## 学习编译器如何工作
elephc 被设计为可读的。代码生成和运行时层被大量注释,因此你可以看到每个降低步骤和发出的指令在做什么 —— 从栈帧设置到系统调用,从整数到字符串的转换到数组的内存布局。如果你曾好奇 `echo "hello"` 和 CPU 执行它之间发生了什么,请跟随 `src/codegen/` 中的代码并阅读注释。**无需汇编知识基础。**
## elephc 有何不同
有几种方法可以使 PHP 更易于分发或运行更快:将 PHP 运行时打包成一个可执行文件、加密字节码、通过带 JIT 的 Zend VM 运行,或者编译选定的热路径同时对动态代码回退到 opcode。
elephc 走了一条更窄但更清晰的路线:它是一个从头开始编写的、针对 PHP 静态子集的编译器。它解析 PHP 源代码,进行类型检查,将其降低到目标平台特定的汇编代码,将其汇编并链接为原生可执行文件,并且只附带生成程序所需的小型运行时例程。如果 elephc 编译了某个构造,那么该构造就是原生代码,而不是解释执行的 PHP。
这个权衡是故意的:
- 与基于 VM 的 PHP 实现相比,**传统兼容性更少**。
- **更高的机械透明度**:可读的汇编输出、源代码映射、逐行注释的代码生成以及有文档记录的内存模型。
- **无隐藏的运行时依赖**:生成的二进制文件不需要 PHP、Zend 引擎、加载器扩展或内嵌的解释器。
- **面向原生的扩展**:`extern`、`ptr`、`buffer` 和 `packed class` 让 PHP 形式的代码能够进入系统级、FFI、游戏和性能敏感的工作负载。
这并不意味着 elephc 必须存在于现有的 PHP 生态系统之外。当前的 CLI 路径生成独立可执行文件,但路线图还包括共享/静态库输出和实验性的 PHP 扩展桥接。这开辟了一条实际的中间路径:保持 WordPress、Laravel 或 Symfony 等框架在 PHP 上运行,然后将静态的、性能敏感的模块编译为原生库或 PHP 扩展。
因此,elephc 目前并不是一个能直接替换整个动态框架的解决方案。长期目标更为有用:使将 PHP 代码中足够静态的部分编译为可检查的原生代码成为可能,而应用程序的其余部分可以保留在普通的 PHP 中。
## 要求
- Rust 工具链 (`cargo`)
- 用于你的主机/目标的原生汇编器和链接器
- 在 macOS 上:Xcode 命令行工具 (`xcode-select --install`)
- 在 Linux 上:标准原生工具链 (`as`、`ld`、libc 开发文件)
## 安装
### Homebrew (推荐)
```
brew install illegalstudio/tap/elephc
```
### 从源代码安装
```
git clone https://github.com/illegalstudio/elephc.git
cd elephc
cargo build --release
```
二进制文件位于 `./target/release/elephc`。
### 手动下载
预构建的二进制文件可在 [Releases](https://github.com/illegalstudio/elephc/releases) 页面获取。如果 macOS 阻止该二进制文件,运行:
```
xattr -cr elephc
```
## 用法
```
# 将 PHP 文件编译为原生二进制文件
elephc hello.php
./hello
# 自定义堆大小(默认:8MB)
elephc --heap-size=16777216 heavy.php
# 在调试所有权问题时启用运行时堆验证
elephc --heap-debug heavy.php
# 在调试 GC 行为时将分配/释放计数器打印到 stderr
elephc --gc-stats heavy.php
# 启用编译时功能分支
elephc --define DEBUG app.php
# 打印每个阶段的编译器计时
elephc --timings hello.php
# 生成汇编和简单的源映射伴随文件
elephc --emit-asm --source-map hello.php
# 运行前端检查而不写入汇编或二进制文件
elephc --check hello.php
# 为 FFI 链接额外的原生库或框架
elephc app.php -l sqlite3 -L /opt/homebrew/lib --framework Cocoa
# 显式目标选择
# 当前支持的目标:macos-aarch64、linux-aarch64、linux-x86_64
elephc --target linux-aarch64 hello.php
elephc --target linux-x86_64 hello.php
```
或通过 cargo:
```
cargo run -- hello.php
./hello
```
## 展示项目
| 展示项目 | 描述 |
|---|---|
| [HTTP 服务器](showcases/http-server/) | 异步 HTTP/1.1 服务器,具有非阻塞 `poll()` 事件循环,每个连接一个 `Fiber`,通过 `extern` FFI 使用 POSIX 套接字,`ptr` 缓冲区,HTTP 解析器和路由器 |
| [DOOM E1M1](showcases/doom/) | 实时 3D WAD 渲染器,使用 BSP 遍历、SDL2 FFI、`packed class` 几何数据、`buffer` 存储、碰撞检测、HUD |
| [SDL 帧缓冲区](examples/sdl_framebuffer/) | 通过 FFI 使用 SDL2 进行像素级渲染 |
| [SDL 音频](examples/sdl_audio/) | 通过 FFI 使用 SDL2 进行音频播放 |
| [热路径缓冲区](examples/hot-path/) | `packed class` + `buffer` 用于性能关键数据 |
| [FFI 内存](examples/ffi-memory/) | 通过 FFI 使用 `malloc`、`free`、`memcpy` 实现原始 C 内存模式 |
## FFI
elephc 可以通过 `extern` 声明直接调用原生 C 函数。
```
"value"]`、`[[1,2],[3,4]]` (索引、关联、多维、写时复制、带 `+` 的联合) |
| `object` | `new Foo()`、`$user->name` |
| `pointer` | `ptr($x)`、`ptr_null()`、`ptr_cast($p)` |
| `enum` | `enum Color: int { case Red = 1; }`、`Color::Red->value`、`Color::from(1)` |
| `int\|string` | `int\|string $x = 42;`、`function show(int\|string $x): string { ... }` |
| `?int` | `?int $x = null;`、`function find(): ?int { ... }` |
| `buffer` | `buffer $xs = buffer_new(256)` |
| `packed class` | `packed class Vec2 { public float $x; public float $y; }` |
### 支持的构造
支持的构造、运算符和控制结构的完整列表在 [文档](docs/) 中。亮点:
- **面向对象编程**:类、抽象/final 类、类型化/final/静态属性和方法、PHP 风格的静态属性重声明、直接静态数组属性写入、构造函数属性提升、接口、`instanceof`、trait、枚举、PHP 8 声明属性、有限的属性反射(`ReflectionClass`/`ReflectionMethod`/`ReflectionProperty::getAttributes()`,`ReflectionAttribute::newInstance()`)、`readonly`、静态/实例方法、大小写不敏感的类/接口/trait 和方法查找、`self::`/`parent::`/`static::`、`::class` 反射、`new self()` / `new static()` / `new parent()`、魔术方法 (`__toString`、`__get`、`__set`)
- **函数**:大小写不敏感的用户和内置函数调用、默认参数、可变参数/展开、按引用传递、命名参数、全局变量、静态局部变量、一等公民可调用对象、闭包、箭头函数、静态闭包 (`static function () { }`、`static fn () => ...`)
- **生成器**:生成器函数和闭包、`yield`、键值 yield、`yield from`、`Generator::send()`、`throw()`、`getReturn()`,以及对 `Iterator` / `IteratorAggregate` 的 `foreach`
- **Fibers**:`Fiber`、`FiberError`、`Fiber::suspend()`、`Fiber::getCurrent()`、`start()`、`resume()`、`throw()`、`getReturn()`、状态谓词、闭包捕获、受保护的原生栈,以及 ARM64 / Linux x86_64 上下文切换
- **控制流**:if/elseif/else、while、do-while、for、foreach、switch、match、break/continue(包括多层深度)、try/catch/finally/throw
- **语句和字面量**:`const` / `define()` 常量、`global` 声明、`static` 局部变量、`print` 表达式、列表解包、PHP 数字字面量形式、heredoc / nowdoc 字符串
- **运算符**:算术、比较、`instanceof`、逻辑、位运算、三元、空值合并 (`??`)、PHP 8.5 管道 (`|>`)、局部和稳定非局部目标的赋值表达式、空值合并赋值 (`??=`)、错误控制 (`@`)、复合赋值
- **类型**:联合类型 (`int|string`)、可空类型 (`?int`)、`never` 返回类型、`iterable` 伪类型、`fopen()` 的推断 `resource|false` 值和标准流的 `resource` 值、类型转换、类型化属性、类型化的函数、方法、闭包和箭头参数及返回值
- **模块**:命名空间、use 导入、include/require/include_once/require_once、编译期 Composer PSR-4/PSR-0/classmap/files 自动加载、`spl_autoload_register()` 规则提取、PHP 魔术常量
- **FFI**:extern 函数、extern 块、extern 全局变量、extern 类、指针内置函数
- **扩展**:`ifdef`、`packed class`、`buffer`、`buffer_new()`、`buffer_len()`、`buffer_free()`
### 内置函数 (290+)
**字符串:** `strlen`、`substr`、`strpos`、`strrpos`、`strstr`、`str_replace`、`str_ireplace`、`substr_replace`、`strtolower`、`strtoupper`、`ucfirst`、`lcfirst`、`ucwords`、`trim`、`ltrim`、`rtrim`、`str_repeat`、`str_pad`、`strrev`、`str_split`、`strcmp`、`strcasecmp`、`str_contains`、`str_starts_with`、`str_ends_with`、`ord`、`chr`、`explode`、`implode`、`sprintf`、`printf`、`sscanf`、`md5`、`sha1`、`hash`、`number_format`、`addslashes`、`stripslashes`、`nl2br`、`wordwrap`、`bin2hex`、`hex2bin`、`htmlspecialchars`、`htmlentities`、`html_entity_decode`、`urlencode`、`urldecode`、`rawurlencode`、`rawurldecode`、`base64_encode`、`base64_decode`、`ctype_alpha`、`ctype_digit`、`ctype_alnum`、`ctype_space`
**数组:** `count`、`array_push`、`array_pop`、`in_array`、`array_keys`、`array_values`、`sort`、`rsort`、`isset`、`array_key_exists`、`array_search`、`array_merge`、`array_slice`、`array_splice`、`array_combine`、`array_flip`、`array_reverse`、`array_unique`、`array_sum`、`array_product`、`array_chunk`、`array_pad`、`array_fill`、`array_fill_keys`、`array_diff`、`array_intersect`、`array_diff_key`、`array_intersect_key`、`array_unshift`、`array_shift`、`asort`、`arsort`、`ksort`、`krsort`、`natsort`、`natcasesort`、`shuffle`、`array_rand`、`array_column`、`range`、`array_map`、`array_filter`、`array_reduce`、`array_walk`、`usort`、`uksort`、`uasort`、`call_user_func`、`call_user_func_array`、`function_exists`
**数学:** `abs`、`floor`、`ceil`、`round`、`sqrt`、`pow`、`min`、`max`、`intdiv`、`fmod`、`fdiv`、`rand`、`mt_rand`、`random_int`、`sin`、`cos`、`tan`、`asin`、`acos`、`atan`、`atan2`、`sinh`、`cosh`、`tanh`、`log`、`log2`、`log10`、`exp`、`hypot`、`deg2rad`、`rad2deg`、`pi`
**类型和类内省:** `gettype`、`settype`、`empty`、`unset`、`is_int`、`is_float`、`is_string`、`is_bool`、`is_null`、`is_numeric`、`is_nan`、`is_finite`、`is_infinite`、`is_iterable`、`is_callable`、`boolval`、`floatval`、`intval`、`class_exists`、`interface_exists`、`trait_exists`、`enum_exists`、`class_alias`、`get_class`、`get_parent_class`、`get_declared_classes`、`get_declared_interfaces`、`get_declared_traits`、`is_a`、`is_subclass_of`
**I/O:** `fopen`、`fclose`、`fread`、`fwrite`、`fgets`、`fgetc`、`fpassthru`、`flock`、`tmpfile`、`readfile`、`feof`、`readline`、`fseek`、`ftell`、`rewind`、`file_get_contents`、`file_put_contents`、`file`、`fgetcsv`、`fputcsv`、`file_exists`、`is_file`、`is_dir`、`is_readable`、`is_writable`、`is_writeable`、`is_executable`、`is_link`、`symlink`、`link`、`readlink`、`linkinfo`、`filesize`、`filemtime`、`fileatime`、`filectime`、`fileperms`、`fileowner`、`filegroup`、`fileinode`、`filetype`、`stat`、`lstat`、`fstat`、`clearstatcache`、`basename`、`dirname`、`pathinfo`、`realpath`、`fnmatch`、`touch`、`chmod`、`chown`、`chgrp`、`umask`、`ftruncate`、`fflush`、`fsync`、`fdatasync`、`copy`、`rename`、`unlink`、`mkdir`、`rmdir`、`scandir`、`glob`、`getcwd`、`chdir`、`tempnam`、`sys_get_temp_dir`、`var_dump`、`print_r`
**系统:** `exit`、`die`、`time`、`microtime`、`date`、`mktime`、`strtotime`、`sleep`、`usleep`、`getenv`、`putenv`、`php_uname`、`phpversion`、`exec`、`shell_exec`、`system`、`passthru`、`json_encode`、`json_decode`、`json_last_error`、`json_last_error_msg`、`json_validate`、`preg_match`、`preg_match_all`、`preg_replace_callback`、`preg_replace`、`preg_split`、`define`、`class_attribute_names`、`class_attribute_args`、`class_get_attributes`
**SPL/自动加载:** `spl_autoload_register`、`spl_autoload_unregister`、`spl_autoload_functions`、`spl_autoload_extensions`、`spl_autoload_call`、`spl_autoload`、`spl_classes`、`spl_object_id`、`spl_object_hash`
**指针/缓冲区:** `ptr`、`ptr_null`、`ptr_is_null`、`ptr_get`、`ptr_set`、`ptr_read8`、`ptr_read16`、`ptr_read32`、`ptr_read_string`、`ptr_write8`、`ptr_write16`、`ptr_write32`、`ptr_write_string`、`ptr_offset`、`ptr_cast`、`ptr_sizeof`、`buffer_new`、`buffer_len`、`buffer_free`
### 常量
`INF`、`NAN`、`PHP_INT_MAX`、`PHP_INT_MIN`、`PHP_FLOAT_MAX`、`PHP_FLOAT_MIN`、`PHP_FLOAT_EPSILON`、`M_PI`、`M_E`、`M_SQRT2`、`M_PI_2`、`M_PI_4`、`M_LOG2E`、`M_LOG10E`、`PHP_EOL`、`PHP_OS`、`DIRECTORY_SEPARATOR`、`STDIN`、`STDOUT`、`STDERR`、`PATHINFO_DIRNAME`、`PATHINFO_BASENAME`、`PATHINFO_EXTENSION`、`PATHINFO_FILENAME`、`PATHINFO_ALL`、`FNM_NOESCAPE`、`FNM_PATHNAME`、`FNM_PERIOD`、`FNM_CASEFOLD`、`LOCK_SH`、`LOCK_EX`、`LOCK_UN`、`LOCK_NB`、`JSON_HEX_TAG`、`JSON_HEX_AMP`、`JSON_HEX_APOS`、`JSON_HEX_QUOT`、`JSON_FORCE_OBJECT`、`JSON_NUMERIC_CHECK`、`JSON_UNESCAPED_SLASHES`、`JSON_PRETTY_PRINT`、`JSON_UNESCAPED_UNICODE`、`JSON_PARTIAL_OUTPUT_ON_ERROR`、`JSON_PRESERVE_ZERO_FRACTION`、`JSON_INVALID_UTF8_IGNORE`、`JSON_INVALID_UTF8_SUBSTITUTE`、`JSON_THROW_ON_ERROR`、`JSON_OBJECT_AS_ARRAY`、`JSON_BIGINT_AS_STRING`、`JSON_ERROR_NONE`、`JSON_ERROR_DEPTH`、`JSON_ERROR_STATE_MISMATCH`、`JSON_ERROR_CTRL_CHAR`、`JSON_ERROR_SYNTAX`、`JSON_ERROR_UTF8`、`JSON_ERROR_RECURSION`、`JSON_ERROR_INF_OR_NAN`、`JSON_ERROR_UNSUPPORTED_TYPE`、`JSON_ERROR_INVALID_PROPERTY_NAME`、`JSON_ERROR_UTF16`、`__DIR__`、`__FILE__`、`__LINE__`、`__FUNCTION__`、`__CLASS__`、`__METHOD__`、`__NAMESPACE__`、`__TRAIT__`
也支持通过 `const NAME = value;` 和 `define("NAME", value);` 定义的用户常量。常量保持大小写敏感,与 PHP 一致。
## 它如何工作
```
PHP source → Lexer → Parser (AST) → Magic constants (per-file) → Conditional (ifdef/--define) → Autoload registry build (Composer + SPL rules) → Resolver (include declaration discovery, include/require inlining, per-file constants, once guards, function variant marks) → NameResolver (namespaces/use/FQNs) → Autoload run (class-triggered file insertion) → Optimizer (constant folding) → Type Checker → Optimizer (constant propagation) → Optimizer (control-flow pruning) → Optimizer (control-flow normalization) → Optimizer (dead-code elimination) → Codegen → as + ld → native executable
```
编译器为目标平台生成可读的汇编代码。你可以检查 `.s` 文件来确切地了解你的 PHP 代码变成了什么:
```
elephc hello.php
cat hello.s
```
如果你添加 `--source-map`,elephc 还会生成 `hello.map`,这是一个紧凑的 JSON 伴生文件,它将生成的汇编行映射回 PHP 的行/列对。如果你添加 `--timings`,编译器会打印每个阶段的持续时间,例如词法分析、解析、早期优化、类型检查、常量传播、检查后修剪、控制流规范化、死代码消除、运行时缓存准备、代码生成、汇编和链接。
### 当前优化过程
elephc 在生成汇编之前已经执行了一个小型但有用的 AST 级别优化流程:
- **类型检查前的常量折叠**:当结果静态已知时,折叠标量算术、位运算、比较、逻辑运算、字符串字面量连接、标量转换、三元运算、空值合并、已知 `match` 表达式以及标量索引/关联数组字面量读取。
- **类型检查后的常量传播**:在直线代码中、在一致的 `if` / `switch` / `try` 合并点、在已知主体的 `switch` 路径中、在不抛出异常的 `try` 主体中(不会因不可达的 catch 而污染合并)、在统一的局部 `?:` / `match` 赋值中、在固定标量解构如 `[$a, $b] = [2, 3]` 中,以及在简单循环中(当未被修改的局部变量或稳定的 `for` 初始化赋值即使保守地使用嵌套 `switch`、`try/catch/finally`、`foreach`、其他简单嵌套循环写入、局部数组修改如 `$items[] = $i` / `$items[0] = $i`、局部属性写入如 `$box->last = $i` / `$box->items[] = $i` 或针对局部的失效如 `unset($tmp)` 时)可以证明是安全的情况下,转发标量局部值。它还使用局部循环路径摘要来处理已知的 `while(false)`、`do...while(false)`、`while(true)` / `for(;;)` break 退出,以及在标量值上一致的分支局部循环退出,这反过来解锁了后续表达式中的更多折叠,如 `$x ** $y`。
- **修剪后的控制流修剪**:移除常量死的 `if` / `elseif` / `while (false)` / `for (...; false; ...)` 分支,具体化常量 `switch` 执行,修剪 `match` 分支,并在终止构造(如 `return`、`throw`、`break` 和 `continue`)之后裁剪不可达的语句。
- **修剪后的控制流规范化**:规范化等价的残余形状,如嵌套的 `elseif` 链、合并的 `if` 头/尾、单 case 或仅 fallthrough 的 `switch` 外壳、规范的多 catch 处理器、折叠的外层 `finally` 包装器,以及相同的 `if` 分支,以便后续过程看到更少的结构不同但语义相同的树。
- **规范化后的死代码消除**:移除空的控制外壳,简化单路径条件,修剪布尔、严格标量、宽松相等和安全关系检查中的守卫矛盾,对局部 `if` / `switch` / `try` 形状使用轻量级 CFG 可达性分析,提升安全的非抛出 `try` 前缀,并在周围的表达式已经确定结果时,移除未使用的纯表达式语句和死纯子表达式。
- **用于纯度/可能抛出推理的局部效果摘要**:跟踪已知的纯且不抛出异常的内置函数、用户函数、静态方法、私有 `$this` 方法、闭包、一等公民可调用对象以及通过 `if` / `switch` / `try` 控制流合并的可调用别名,以便优化器可以更精确地简化 `try` 区域并修剪死处理器。
优化器被故意设计得保守。它尚未进行完整的函数级 CFG 定点传播、激进的全程序优化或汇编级别的窥孔重写,但它确实为已知的调用目标和结构化控制流计算效果摘要和局部 CFG 轻量级可达性,以便 AST 重写可以保持更精确而不变得有风险。
### 类型系统
静态类型系统在编译时跟踪这些运行时形状:
- **Int** — 64 位有符号整数
- **Float** — 64 位双精度
- **Str** — 指针 + 长度对
- **Bool** — `true`/`false`,强制转换为 0/1
- **Void / null** — 空哨兵值,强制转换为 0/""
- **Never** — 不返回的函数/方法/闭包返回类型
- **Iterable** — 类型擦除的数组 / `Traversable` 伪类型
- **Array** — 带推断元素类型的索引数组;异构有效载荷扩展为装箱的 `Mixed`
- **AssocArray** — 带键/值类型的关联数组
- **Buffer** — 用于热路径值的固定大小连续 `buffer` 存储
- **Mixed** — 用于异构数组值、联合存储和用户面对的 `mixed` 提示的装箱运行时标记有效载荷
- **Callable** — 闭包和可调用函数引用
- **Object** — 堆分配的类实例
- **Packed** — 与指针和缓冲区一起使用的名义打包记录元数据
- **Pointer** — 原始 64 位地址,可通过 `ptr_cast()` 可选标记
- **Resource** — 流句柄,如成功的 `fopen()` 结果和标准流
- **Union** — 声明的联合类型降低为装箱的标记运行时有效载荷
变量的类型在第一次赋值时设置。兼容的类型 (int/float/bool/null) 可以在彼此之间重新赋值。
## 错误信息
错误包含行号和列号,编译器会尝试恢复得足够远,以便在一次传递中报告多个独立的语法/语义错误。成功的编译也可能发出非致命警告,如未使用的变量/参数或不可达代码:
```
error[3:1]: Undefined variable: $x
error[5:7]: Type error: cannot reassign $x from Int to Str
error[2:1]: Required file not found: 'missing.php'
warning[9:5]: Unused variable: $tmp
warning[14:9]: Unreachable code
```
## 项目结构
源代码树的高层概览。代码库包含比此处显示的更聚焦的辅助子模块;请将其视为方向指南,而非逐字节的文件列表。
```
src/
├── lib.rs # Public module exports
├── main.rs # CLI binary entry point
├── cli.rs # Command-line argument parsing and options
├── pipeline.rs # Frontend/backend compilation pipeline
├── linker.rs # Assembler + linker invocation
├── timings.rs # Phase timing collection/reporting
├── span.rs # Source position tracking (line, col)
├── conditional/ # Build-time `ifdef` pass driven by --define
├── magic_constants.rs # Per-file PHP magic constant lowering
├── magic_constants/ # File/scope/trait magic-constant walkers
├── autoload/ # Composer/SPL AOT autoload indexing and file insertion
├── resolver/ # Include/require resolution, declaration discovery, once guards
├── runtime_cache.rs # Preassembled runtime object cache
├── source_map.rs # Assembly/source-map sidecar emission
├── termination.rs # Structured terminal-effect analysis
├── optimize.rs # Optimizer public entry points and effect context
├── optimize/ # AST optimizer: folding, propagation, pruning, normalization, dead-code elimination
├── names.rs # Qualified/FQN name model + symbol mangling helpers
├── name_resolver/ # Namespace/use resolution to canonical names
│
├── lexer/ # Source text → token stream
│ ├── token.rs # Token enum
│ ├── scan.rs # Main scanning loop, operators
│ ├── literals.rs # Literal scanning entry point
│ ├── literals/ # Identifier, number, and string scanners
│ └── cursor.rs # Byte-level source reader
│
├── parser/ # Tokens → AST (Pratt parser)
│ ├── ast/ # ExprKind, StmtKind, BinOp, CastType
│ ├── expr/ # Expression parsing helpers and Pratt parser passes
│ ├── stmt/ # Statement parsing, OOP, namespaces, FFI
│ └── control.rs # if, while, for, foreach, do-while, switch, try/catch/finally
│
├── types/ # Static type checking
│ ├── mod.rs # check() entry point and type exports
│ ├── model.rs # PhpType and TypeEnv
│ ├── result.rs # CheckResult and semantic metadata
│ ├── signatures.rs # Built-in and callable signatures
│ ├── call_args/ # Shared named/spread call planner
│ ├── schema.rs # Class/interface/enum metadata
│ ├── fibers.rs # Fiber callback validation
│ ├── traits.rs # Trait flattening and conflict resolution
│ ├── traits/ # Trait expansion, merge, and validation helpers
│ ├── warnings/ # Non-fatal diagnostics (unused vars, unreachable code)
│ └── checker/
│ ├── mod.rs # Type-checker orchestration
│ ├── builtin_interfaces.rs # Built-in SPL/core interface injection
│ ├── builtin_iterators.rs # Built-in Iterator / IteratorAggregate metadata
│ ├── builtin_json.rs # JsonException / JsonSerializable metadata
│ ├── builtin_spl_exceptions.rs # SPL exception hierarchy metadata
│ ├── builtin_stdclass.rs # stdClass dynamic-property metadata
│ ├── builtin_types/ # Built-in class/interface/enum metadata
│ ├── builtins/ # Built-in function type signatures
│ ├── callables/ # Callable values, first-class callables, and callback checks
│ ├── driver/ # Checker initialization and orchestration helpers
│ ├── functions/ # User function type inference
│ ├── inference/ # Focused inference helpers
│ ├── schema/ # Class/interface/trait/enum schema validation
│ ├── stmt_check/ # Statement-level checking helpers
│ ├── type_compat/ # Type compatibility and assignment rules
│ └── yield_validation/ # Generator/yield placement validation
│
├── codegen/ # AST → target assembly
│ ├── mod.rs # Pipeline entry, main/global codegen orchestration
│ ├── driver_support.rs # Pipeline glue and orchestration helpers
│ ├── prescan.rs # Pre-pass collecting program-wide codegen metadata
│ ├── program_usage.rs # Usage analysis feeding metadata emission
│ ├── expr.rs # Expression codegen dispatcher
│ ├── expr/ # Focused expression helpers (arrays, calls, objects, binops, ...)
│ ├── stmt.rs # Statement codegen dispatcher
│ ├── stmt/ # Focused statement helpers (arrays, control_flow, io, storage, ...)
│ ├── abi/ # Target-aware calling-convention, frame, and value helpers
│ ├── functions/ # User function emission, wrappers, and epilogue cleanup
│ ├── main_emission.rs # Top-level program emission
│ ├── class_methods.rs # Class/static method emission orchestration
│ ├── function_variants.rs # Include-loaded function dispatchers
│ ├── interface_wrappers.rs # Interface dispatch return-shape adapters
│ ├── callables.rs # Top-level callable metadata and indirect-call helpers
│ ├── ffi.rs # Extern function/global/class codegen
│ ├── reflection.rs # Shared ReflectionAttribute materialization helpers
│ ├── context.rs # Variables, labels, loop/finally stacks, ownership lattice
│ ├── data_section.rs # String/float literal .data section
│ ├── emit.rs # Assembly text buffer
│ ├── platform/ # Target parsing, syscall remapping, Linux transforms
│ │
│ ├── builtins/ # Built-in function codegen (one file per language function)
│ │ ├── strings/ # strlen, substr, strpos, explode, implode, ...
│ │ ├── arrays/ # count, array_push, array_pop, sort, ...
│ │ ├── math/ # abs, floor, pow, rand, fmod, ...
│ │ ├── types/ # is_int, gettype, empty, unset, settype, ...
│ │ ├── spl/ # spl_autoload_*, spl_classes, spl_object_id/hash
│ │ ├── io/ # fopen, fclose, fread, fwrite, fgets, var_dump, print_r, file_get_contents, ...
│ │ ├── pointers/ # ptr, ptr_get, ptr_set, ptr_read8, ptr_write8, ptr_offset, ...
│ │ └── system/ # exit, die, time, sleep, getenv, exec, ...
│ │
│ └── runtime/ # Runtime routines and target-specific emission helpers
│ ├── strings/ # itoa, concat, ftoa, strpos, str_replace, ...
│ ├── arrays/ # heap_alloc, array_new, array_push, sort, ...
│ ├── buffers/ # buffer_new, buffer_len, bounds and lifetime checks
│ ├── data/ # fixed and user-program runtime data/metadata
│ ├── exceptions.rs # exception runtime orchestration / re-exports
│ ├── exceptions/ # setjmp/longjmp-based exception helpers
│ ├── io/ # fopen, fclose, fread, fwrite, file_ops, ...
│ ├── objects/ # stdClass, dynamic property, mixed object/index helpers
│ ├── pointers/ # ptoa, ptr_check_nonnull, str_to_cstr, cstr_to_str
│ ├── system/ # build_argv, time, getenv, shell_exec
│ ├── fibers/ # Fiber stacks, context switch, entry trampoline, Fiber API
│ └── generators/ # Generator frame layout and __rt_gen_* helpers
│
└── errors/ # Error formatting with line:col
```
## 测试
跨词法分析器、解析器、代码生成和错误报告的 3000+ 测试。每个代码生成测试将内联 PHP 源代码编译为原生二进制文件,运行它并断言标准输出。
```
cargo test # all tests
cargo test -- --include-ignored # all tests, including ignored integration tests
cargo test test_my_feature # run specific tests
ELEPHC_PHP_CHECK=1 cargo test # cross-check output with PHP interpreter
./scripts/test-linux-arm64.sh # Linux ARM64 suite in Docker
./scripts/test-linux-x86_64.sh # Linux x86_64 suite in Docker
```
## 文档
**[docs/](docs/)** 目录是一个完整的 wiki,涵盖了编译器的方方面面。在其中你会找到:
- **PHP 语法参考** — 类型、运算符、控制结构、函数、类、命名空间,以及所有 290+ 个内置函数的签名和示例
- **编译器扩展** — 指针、`buffer`、`packed class`、使用 `extern` 的 FFI 以及使用 `ifdef` 的条件编译 —— 这些特性将 PHP 带入 Web 之外的领域
- **编译器内部原理** — 完整流程的逐步讲解,从词法分析到 Pratt 解析到类型检查再到代码生成和运行时结构
- **ARM64 入门** — 为从未接触过 ARM64 的人介绍 ARM64 汇编,外加 elephc 的 AArch64 后端使用的 ARM64 指令集快速参考
- **内存模型** — 栈、堆、连接缓冲区和哈希表在底层是如何工作的
如果你是编译器或汇编的新手,从顶部开始,逐步深入。无需预先具备底层知识基础。
关于可运行的语言示例,请参见 `examples/`。关于将 elephc 与 PHP 和等效 C 固定装置进行比较的基准测试工具和 CI 趋势制品,请参见 `benchmarks/README.md`。关于聚焦的性能比较,请参见 `benchmarks/hot-path-buffer-vs-arrays`。
## 许可证
MIT
标签:3D渲染, BSP遍历, DOOM游戏, HTTP解析, Linux ARM64, Linux x86_64, macOS ARM64, OpenVAS, PHP, PHP到原生, SEO优化, SOC Prime, TCP套接字, 二进制生成, 低级编程, 原生编译, 可视化界面, 开发工具, 异步事件循环, 异步服务器, 技术栈, 无运行时依赖, 游戏开发, 独立二进制, 碰撞检测, 系统编程, 编程语言, 编译器, 网络编程, 自动回退, 路由, 透视投影, 通知系统