feat(php): Simple web demo
This commit is contained in:
@@ -11,89 +11,16 @@ declare(strict_types=1);
|
||||
* php run.php inspect <bundle.arboricx>
|
||||
*/
|
||||
|
||||
require __DIR__ . '/src/ffi.php';
|
||||
require __DIR__ . '/src/common.php';
|
||||
|
||||
use function Arboricx\{ctx_init, ctx_free, loadBundleDefault, ofNumber, ofString, app, reduce, toString, toBool, toNumber};
|
||||
|
||||
// ── Locate libarboricx.so ──────────────────────────────────────────────────
|
||||
|
||||
function findLib(): string
|
||||
{
|
||||
$env = getenv('ARBORICX_LIB');
|
||||
if ($env !== false && file_exists($env)) {
|
||||
return $env;
|
||||
}
|
||||
|
||||
$paths = [
|
||||
__DIR__ . '/../../zig/zig-out/lib/libarboricx.so',
|
||||
'/usr/local/lib/libarboricx.so',
|
||||
'/usr/lib/libarboricx.so',
|
||||
'./libarboricx.so',
|
||||
];
|
||||
foreach ($paths as $p) {
|
||||
if (file_exists($p)) {
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
||||
fwrite(STDERR, "Error: libarboricx.so not found.\nSet ARBORICX_LIB to its full path.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// ── Decode helpers ─────────────────────────────────────────────────────────
|
||||
|
||||
function decode(\FFI\CData $ctx, int $root): string
|
||||
{
|
||||
// Bool first: false is Leaf, which is also a valid empty string/list.
|
||||
try {
|
||||
return toBool($ctx, $root) ? 'true' : 'false';
|
||||
} catch (\Throwable $e) {
|
||||
try {
|
||||
return toString($ctx, $root);
|
||||
} catch (\Throwable $e2) {
|
||||
try {
|
||||
return (string) toNumber($ctx, $root);
|
||||
} catch (\Throwable $e3) {
|
||||
throw new \RuntimeException('could not decode result');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function decodeType(\FFI\CData $ctx, int $root): string
|
||||
{
|
||||
try {
|
||||
toBool($ctx, $root);
|
||||
return 'bool';
|
||||
} catch (\Throwable $e) {
|
||||
try {
|
||||
toString($ctx, $root);
|
||||
return 'string';
|
||||
} catch (\Throwable $e2) {
|
||||
try {
|
||||
toNumber($ctx, $root);
|
||||
return 'number';
|
||||
} catch (\Throwable $e3) {
|
||||
return 'unknown (raw tree)';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
use function Arboricx\{ctx_init, ctx_free, loadBundleDefault, ofNumber, ofString, app, reduce, toString, toBool, toNumber, findLib, decode, decodeType, readBundle};
|
||||
|
||||
// ── Commands ─────────────────────────────────────────────────────────────────
|
||||
|
||||
function readBundle(string $path): string
|
||||
function bail(string $msg): void
|
||||
{
|
||||
if (!file_exists($path)) {
|
||||
fwrite(STDERR, "Error: bundle not found: $path\n");
|
||||
exit(1);
|
||||
}
|
||||
$bytes = file_get_contents($path);
|
||||
if ($bytes === false) {
|
||||
fwrite(STDERR, "Error: could not read bundle: $path\n");
|
||||
exit(1);
|
||||
}
|
||||
return $bytes;
|
||||
fwrite(STDERR, "Error: $msg\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
function cmdRun(string $libPath, string $bundlePath, array $args): void
|
||||
@@ -109,6 +36,8 @@ function cmdRun(string $libPath, string $bundlePath, array $args): void
|
||||
|
||||
$result = reduce($ctx, $term, 1_000_000_000);
|
||||
echo decode($ctx, $result) . "\n";
|
||||
} catch (\Throwable $e) {
|
||||
bail($e->getMessage());
|
||||
} finally {
|
||||
ctx_free($ctx);
|
||||
}
|
||||
@@ -131,6 +60,8 @@ function cmdInspect(string $libPath, string $bundlePath): void
|
||||
$value = '(raw tree)';
|
||||
}
|
||||
echo " Type: $type\n Value: $value\n";
|
||||
} catch (\Throwable $e) {
|
||||
bail($e->getMessage());
|
||||
} finally {
|
||||
ctx_free($ctx);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user