PHP host shell cleanup and docs

This commit is contained in:
2026-05-10 14:52:24 -05:00
parent fa58f4ef3a
commit 1885c9b4ba
4 changed files with 103 additions and 431 deletions

View File

@@ -9,7 +9,6 @@ declare(strict_types=1);
* Usage:
* php run.php run <bundle.arboricx> <arg> [arg ...]
* php run.php inspect <bundle.arboricx>
* php run.php repl
*
* The "run" command:
* 1. Reads the .arboricx bundle as raw bytes
@@ -27,71 +26,52 @@ require __DIR__ . '/src/functions.php';
require __DIR__ . '/src/codecs.php';
require __DIR__ . '/src/kernel.php';
use function Arboricx\{app, apply_, reduce, ofString, ofNumber, ofBytes, ofList,
formatTree, decodeResult, unwrapResult,
unwrapHostValue, decodeHostPayload,
isLeaf, isStem, isFork,
HOST_STRING_TAG, HOST_NUMBER_TAG, HOST_BOOL_TAG,
HOST_LIST_TAG, HOST_BYTES_TAG, HOST_TREE_TAG,
use function Arboricx\{app, reduce, ofString, ofNumber, ofBytes, ofList,
formatTree, unwrapResult, unwrapHostValue, decodeHostPayload,
getRunArboricxToString};
// ── Commands ─────────────────────────────────────────────────────────────────
function debugTime(string $label): void
function readBundle(string $path): string
{
static $start = null;
static $last = null;
$now = microtime(true);
if ($start === null) {
$start = $now;
$last = $now;
if (!file_exists($path)) {
fwrite(STDERR, "Error: bundle not found: $path\n");
exit(1);
}
fwrite(STDERR, sprintf("[%.3fs +%.3fs] %s\n", $now - $start, $now - $last, $label));
$last = $now;
$bytes = file_get_contents($path);
if ($bytes === false) {
fwrite(STDERR, "Error: could not read bundle: $path\n");
exit(1);
}
return $bytes;
}
function cmdRun(string $bundlePath, array $args): void
{
debugTime('start');
if (!file_exists($bundlePath)) {
fwrite(STDERR, "Error: bundle file not found: $bundlePath\n");
exit(1);
}
$bundleBytes = file_get_contents($bundlePath);
debugTime('read bundle bytes');
if ($bundleBytes === false) {
fwrite(STDERR, "Error: could not read bundle file: $bundlePath\n");
exit(1);
}
$bundleBytes = readBundle($bundlePath);
$kernel = getRunArboricxToString();
debugTime('loaded kernel');
if ($kernel === null) {
fwrite(STDERR, "Error: runArboricxToString kernel not configured (empty ternary string)\n");
fwrite(STDERR, "Set KERNEL_RUN_ARBORICX_TO_STRING constant in kernel.php\n");
fwrite(STDERR, "Error: runArboricxToString kernel not configured\n");
exit(1);
}
$bundleTree = ofBytes($bundleBytes);
debugTime('encoded bundle bytes');
$argTrees = [];
foreach ($args as $arg) {
$argTrees[] = encodeArg($arg);
}
$argsTree = ofList($argTrees);
debugTime('encoded args');
// Kernel application: runArboricxToString bundle args
$expr = app(app($kernel, $bundleTree), $argsTree);
debugTime('built expression');
fwrite(STDERR, "Reducing kernel application...\n");
$result = reduce($expr, 1_000_000_000);
debugTime('reduced kernel application');
// The kernel returns an ok/err pair. On ok, the value is a
// Host ABI envelope: Fork(tag_number, payload_tree).
[$kind, $value, $rest] = unwrapResult($result);
debugTime('unwrapped result');
if ($kind === 'error') {
fwrite(STDERR, "Error detail: $rest\n");
exit(1);
@@ -105,11 +85,9 @@ function cmdRun(string $bundlePath, array $args): void
}
[$tag, $payload] = unwrapHostValue($value);
debugTime('unwrapped host value');
try {
$decoded = decodeHostPayload($tag, $payload);
debugTime('decoded payload');
echo $decoded['value'] . "\n";
} catch (\Throwable $e) {
fwrite(STDERR, "Host ABI decode error: " . $e->getMessage() . "\n");
@@ -118,34 +96,14 @@ function cmdRun(string $bundlePath, array $args): void
}
}
/**
* Encode a command-line argument into a Tree Calculus value.
*
* - Numeric strings (digits only) → tree number
* - Everything else → tree string
*/
function encodeArg(string $arg): int
{
if (ctype_digit($arg) || ($arg !== '0' && preg_match('/^-?\d+$/', $arg))) {
return ofNumber((int)$arg);
}
return ofString($arg);
return ctype_digit($arg) ? ofNumber((int)$arg) : ofString($arg);
}
function cmdInspect(string $bundlePath): void
{
// Minimal inspection: just read the bundle as bytes and print its size.
// Full parsing is done by the kernel, not the host shell.
if (!file_exists($bundlePath)) {
fwrite(STDERR, "Error: bundle file not found: $bundlePath\n");
exit(1);
}
$bundleBytes = file_get_contents($bundlePath);
if ($bundleBytes === false) {
fwrite(STDERR, "Error: could not read bundle file: $bundlePath\n");
exit(1);
}
$bundleBytes = readBundle($bundlePath);
$bytes = strlen($bundleBytes);
echo "Bundle: $bundlePath\n";
echo "Size: $bytes bytes\n";
@@ -179,61 +137,6 @@ function cmdInspect(string $bundlePath): void
}
}
function cmdRepl(): void
{
echo "Arboricx PHP REPL\n";
echo "Commands:\n";
echo " run <bundle> [args...] — Run a bundle\n";
echo " inspect <bundle> — Inspect a bundle\n";
echo " exit — Exit\n";
echo "\n";
$kernel = getRunArboricxToString();
if ($kernel === null) {
fwrite(STDERR, "Warning: kernel not configured\n");
}
while (true) {
$prompt = "arboricx> ";
fwrite(STDOUT, $prompt);
$line = trim(fgets(STDIN));
if ($line === '' || $line === 'exit' || $line === 'quit') {
break;
}
$parts = preg_split('/\s+/', $line, 2);
if (!$parts) {
continue;
}
$cmd = $parts[0];
switch ($cmd) {
case 'run':
if (!isset($parts[1])) {
fwrite(STDERR, "Usage: run <bundle> [args...]\n");
break;
}
$cmdRun($parts[1], array_slice($parts, 2));
break;
case 'inspect':
if (!isset($parts[1])) {
fwrite(STDERR, "Usage: inspect <bundle>\n");
break;
}
cmdInspect($parts[1]);
break;
case 'help':
echo "Commands:\n";
echo " run <bundle> [args...] — Run a bundle\n";
echo " inspect <bundle> — Inspect a bundle\n";
echo " exit — Exit\n";
break;
default:
fwrite(STDERR, "Unknown command: $cmd\n");
}
}
}
// ── Main ─────────────────────────────────────────────────────────────────────
$argv = $_SERVER['argv'] ?? [];
@@ -244,7 +147,6 @@ if ($argc < 2) {
echo "\nUsage:\n";
echo " php run.php run <bundle.arboricx> [args...]\n";
echo " php run.php inspect <bundle.arboricx>\n";
echo " php run.php repl\n";
exit(0);
}
@@ -264,11 +166,8 @@ switch ($command) {
}
cmdInspect($argv[2]);
break;
case 'repl':
cmdRepl();
break;
default:
echo "Unknown command: $command\n";
echo "Usage: php run.php run|inspect|repl ...\n";
echo "Usage: php run.php run|inspect ...\n";
exit(1);
}