>_PHPLANG REFERENCE
A compiled PHP runtime written in Rust. Source is lexed and parsed to an AST, lowered to fusevm bytecode, and executed on the same language-agnostic VM + tracing Cranelift JIT that hosts zshrs, stryke, awkrs, pythonrs, and rubylang, over a PhpHost object heap. To our knowledge the first compiled standalone PHP runtime. The binary is php. In active development.
What it is
phplang runs PHP programs as ordinary compiled bytecode: it lexes and parses the source in two modes (inline-HTML passthrough plus <?php … ?> code), lowers it to fusevm instructions, and lets the shared engine execute and JIT-compile them. There is no bespoke interpreter loop — arithmetic lowers to native fusevm ops so the tracing Cranelift JIT can compile hot loops, while PHP-specific behaviour (loose comparison, string↔number coercion, array semantics, the standard library) is served by the PhpHost object heap.
It is another language hosted on fusevm, the shared bytecode VM and Cranelift JIT behind zshrs, stryke, awkrs, pythonrs, and rubylang. phplang carries no VM or JIT of its own.
Architecture
The pipeline mirrors how the sibling frontends host their languages:
PHP source → lexer (two-mode) → parser (AST) → lower to fusevm bytecode → fusevm VM + Cranelift JIT
│
PhpHost object heap (arrays, builtins, numeric hook)
fusevm-hosted
No local vm.rs / jit.rs. PHP is lowered to fusevm bytecode and executed on the shared tracing Cranelift JIT (fusevm with the jit feature).
Native arithmetic + numeric hook
+ - * lower to native fusevm ops so the JIT can trace hot loops; a strict numeric hook supplies PHP coercion when an operand is a string/array/null or an i64 op overflows.
Two-mode lexer
Inline HTML passes straight through; <?php … ?> and <?= switch to code mode. #, //, and /* */ comments are recognised.
Arrays on the heap
PHP arrays are heap objects in PhpHost, travelling as Value::Obj(u32) handles; insertion order is preserved (an IndexMap), observable in foreach/print_r.
Example
<?php
function fib($n) { return $n < 2 ? $n : fib($n - 1) + fib($n - 2); }
echo implode(", ", array_map("fib", range(0, 10))), "\n";
// => 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
$a = ["b" => 2, "a" => 1];
ksort($a);
echo json_encode($a), "\n"; // => {"a":1,"b":2}
$total = 0;
foreach ([1, 2, 3, 4] as $x) { $total += $x; }
echo $total, "\n"; // => 10
echo match (2) { 1 => "one", 2 => "two", default => "?" }, "\n"; // => two
Usage
php script.php # run a file php -r 'echo 1 + 1;' # run a one-liner (no <?php tag needed) php -a # interactive REPL (persistent state per line) php --dump-bytecode f.php # print the lowered fusevm bytecode
A man/php.1 man page and runnable examples/*.php ship with the crate.
Status & roadmap
A working core, grown outward from the sibling frontends. The table reflects the current state of the tree; a few documented deviations from reference PHP are noted below.
| Component | State | Notes |
|---|---|---|
| Two-mode lexer / parser → AST | Implemented | Inline-HTML passthrough, <?php>/<?=, all comment forms, $var interpolation (src/lexer.rs, src/parser.rs). |
| AST → fusevm bytecode lowering | Implemented | Native arithmetic + CallBuiltin dispatch; no local VM (src/compiler.rs). |
| Scalars, strings, casts | Implemented | int/float/bool/string/null; (int)/(float)/(string)/(bool) casts. |
| Operators & comparison | Implemented | + - * / % **, concat ., compound assign, ++/--, loose/strict compare, && || and or, ?:/elvis, ??. |
| Arrays (indexed / assoc / append) | Implemented | Ordered on the PhpHost heap; index read/write, $a[] = append (src/host.rs). |
| Control flow | Implemented | if/elseif/else, while, do…while, for, foreach, switch (fall-through), break/continue/return, match. |
| User functions | Implemented | Positional parameters and recursion. |
| Standard library (~90 functions) | Implemented | String, array, math, and type/util families (str_*, array_*, sprintf, json_encode, var_dump, …) in src/builtins.rs. |
| Differential parity fuzzer | Implemented | Seed-deterministic snippets diffed against the reference php; delta-debugged repros (src/bin/parity_fuzz.rs). Dev tool — needs php on PATH, never in CI. |
| Classes / traits / namespaces / closures | Planned | OO, closures/arrow functions, references, try/catch, generators, superglobals, default/variadic/typed params, deep lvalues. |
| Bytecode cache / AOT / LSP / DAP | Planned | Present in sibling frontends; not wired in phplang yet. |
Documented deviations (in-code): array semantics are reference-based rather than PHP's copy-on-write; array_pop/array_shift await a host by-reference delete; a match with no arm and no default yields null instead of throwing \UnhandledMatchError; loose comparison follows a simplified model.
Building from source
phplang builds as a standalone Rust crate (an explicit empty [workspace] keeps it independent of the meta repo):
# clone git clone https://github.com/MenkeTechnologies/phplang cd phplang # build (produces target/debug/php + parity-fuzz) cargo build # run a file, a one-liner, or the REPL ./target/debug/php script.php ./target/debug/php -r 'echo array_sum(range(1, 100));' ./target/debug/php -a # run tests cargo test
fusevm is pulled from crates.io with the jit feature.
License
phplang is MIT licensed — free and open source. See LICENSE.
Repository & links
- Engineering report — report.html (architecture, fusevm hosting, roadmap, dependency posture)
- Source — github.com/MenkeTechnologies/phplang
- Issues — github.com/MenkeTechnologies/phplang/issues
- The shared VM — fusevm (also behind
zshrs,stryke,awkrs,pythonrs,rubylang)