From ea748b2e5ee2b0d798b0526aec2082857b077305 Mon Sep 17 00:00:00 2001 From: James Eversole Date: Mon, 11 May 2026 13:07:35 -0500 Subject: [PATCH] feat(php): Simple web demo --- ext/php/public/eval.php | 53 ++++++++++++++++++++++ ext/php/public/index.php | 30 +++++++++++++ ext/php/run.php | 87 ++++-------------------------------- ext/php/src/common.php | 81 +++++++++++++++++++++++++++++++++ flake.nix | 3 +- notes/php-cli-run-flags.md | 13 +++++- notes/recursive-consumers.md | 2 +- 7 files changed, 186 insertions(+), 83 deletions(-) create mode 100644 ext/php/public/eval.php create mode 100644 ext/php/public/index.php create mode 100644 ext/php/src/common.php diff --git a/ext/php/public/eval.php b/ext/php/public/eval.php new file mode 100644 index 0000000..c19ad73 --- /dev/null +++ b/ext/php/public/eval.php @@ -0,0 +1,53 @@ +getMessage(); +} diff --git a/ext/php/public/index.php b/ext/php/public/index.php new file mode 100644 index 0000000..7a05cd2 --- /dev/null +++ b/ext/php/public/index.php @@ -0,0 +1,30 @@ + + + + + + Arboricx Web + + + +

Arboricx Bundle Runner

+
+

+ +

+ +

+ +

+ +

+ +

+
+

+
+
diff --git a/ext/php/run.php b/ext/php/run.php
index 1275fa2..30ce434 100644
--- a/ext/php/run.php
+++ b/ext/php/run.php
@@ -11,89 +11,16 @@ declare(strict_types=1);
  *   php run.php inspect 
  */
 
-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);
     }
diff --git a/ext/php/src/common.php b/ext/php/src/common.php
new file mode 100644
index 0000000..b1b33f3
--- /dev/null
+++ b/ext/php/src/common.php
@@ -0,0 +1,81 @@
+