// PHPLANG — PHP IN RUST

phplang v0.1.0 · PHP on fusevm · lex/parse → AST → bytecode → tracing Cranelift JIT · PhpHost object heap · the first compiled standalone PHP runtime · binary php · a fusevm language host (with zshrs, stryke, awkrs, pythonrs, rubylang) · MIT · in active development

Report GitHub Issues
// Color scheme

>_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.

ComponentStateNotes
Two-mode lexer / parser → ASTImplementedInline-HTML passthrough, <?php>/<?=, all comment forms, $var interpolation (src/lexer.rs, src/parser.rs).
AST → fusevm bytecode loweringImplementedNative arithmetic + CallBuiltin dispatch; no local VM (src/compiler.rs).
Scalars, strings, castsImplementedint/float/bool/string/null; (int)/(float)/(string)/(bool) casts.
Operators & comparisonImplemented+ - * / % **, concat ., compound assign, ++/--, loose/strict compare, && || and or, ?:/elvis, ??.
Arrays (indexed / assoc / append)ImplementedOrdered on the PhpHost heap; index read/write, $a[] = append (src/host.rs).
Control flowImplementedif/elseif/else, while, do…while, for, foreach, switch (fall-through), break/continue/return, match.
User functionsImplementedPositional parameters and recursion.
Standard library (~90 functions)ImplementedString, array, math, and type/util families (str_*, array_*, sprintf, json_encode, var_dump, …) in src/builtins.rs.
Differential parity fuzzerImplementedSeed-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 / closuresPlannedOO, closures/arrow functions, references, try/catch, generators, superglobals, default/variadic/typed params, deep lvalues.
Bytecode cache / AOT / LSP / DAPPlannedPresent 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