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。 ![elephc HTTP 服务器 — ApacheBench 延迟](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/8c96382a8d150504.png) 参见 [showcases/http-server/](showcases/http-server/) 获取完整源代码和构建说明。 ## 用 PHP 渲染 DOOM 旗舰展示:一个实时 3D 渲染器,加载原始 DOOM WAD 文件并渲染 E1M1 —— BSP 遍历、透视投影、逐列雾效、区域光照、碰撞检测、台阶攀爬 —— 完全用 PHP 编写并编译为原生二进制文件。 ![用 PHP 渲染 DOOM E1M1](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/2714127025150511.gif) 参见 [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套接字, 二进制生成, 低级编程, 原生编译, 可视化界面, 开发工具, 异步事件循环, 异步服务器, 技术栈, 无运行时依赖, 游戏开发, 独立二进制, 碰撞检测, 系统编程, 编程语言, 编译器, 网络编程, 自动回退, 路由, 透视投影, 通知系统