README.md (3432B)
Native PHP binding
64-bit PHP with the FFI extension uses the Haskell embedding ABI. The Nix package selects that runtime and extension:
nix build .#tricu-php .#tricu-php-tests --no-link
PHP=$(nix path-info .#tricu-php)
"$PHP/bin/tricu-php" run test/fixtures/id.arboricx id hello
"$PHP/bin/tricu-php" run test/fixtures/false.arboricx false --format bool
Require $PHP/share/tricu-php/src/ffi.php, then use Arboricx\Library:
$ctx = (new Arboricx\Library())->context();
try {
$number = $ctx->number('18446744073709551615');
echo $ctx->toNumber($number); // exact decimal string
} finally {
$ctx->close();
}
Library($path) selects a library explicitly. Default discovery checks TRICU_LIB
and the installed library beside the PHP sources. The header comes from the
installed package or the repository's Haskell interface. A selected process uses
one runtime-library path. Keep the complete native runtime closure; Nix retains it
automatically.
Handles are opaque FFI\CData uint64 scalars. Pass them back to context methods;
PHP integer casts are unnecessary. number accepts nonnegative PHP integers or
canonical decimal uint64 strings. toNumber always returns an exact decimal
string, including small numbers. This preserves unsigned values beyond PHP's
signed integer range. PHP strings carry both byte buffers (bytes/toBytes) and
strict UTF-8 text (string/toString), preserving embedded NULs.
loadBundle($bytes, $exportName) verifies a bundle and selects an explicit export.
apply suspends application; reduce demands only the outer constructor.
kind returns 0/1/2 for Leaf/Stem/Fork, and child returns an owned handle.
toBool checks the canonical boolean shapes. runIO returns an array with
outcome, value, and cleanup: outcome 0/1/2 means completed/failed/cancelled,
and both payload handles are owned. Task reasons stay opaque until observed;
ordinary error Results may be completion values. Boundary failures throw
Arboricx\TricuError with numeric status and diagnostic text.
Release intermediate handles in long-lived contexts. Explicit close releases all
remaining roots and is idempotent. Destruction also releases abandoned contexts.
Returned byte/text buffers are copied to PHP strings and freed in finally.
Native calls are synchronous. IO uses OS process authority; use trusted programs
or supervised processes with resource limits.
The Linux library is pinned in memory across dlclose, matching GHC's process
lifetime even when PHP releases a request-scoped FFI object. Checks cover CLI
execution and repeated uploads/errors in one PHP built-in server process.
Initialize GHC in the process that executes the bundle; after a fork, use a fresh
executable process for embedding.
The public/ example runs pure uploaded bundles with an explicit export and result
format. Requests select pure bundle execution. Run this example under external
process supervision with execution and memory limits for uploaded computations.
The CLI requires run BUNDLE EXPORT, accepts text arguments, and supports --io
and --format string|number|bool|bytes (default string; bytes render as hex).
-- ends option parsing. Terminal task failure/cancellation exits nonzero with
its reason left opaque. Fuel/collection helpers, implicit export
selection, heuristic decoding, and the old inspect CLI are retired here.