diff --git a/ext/php/run.php b/ext/php/run.php index 36bde0f..82bc289 100644 --- a/ext/php/run.php +++ b/ext/php/run.php @@ -9,7 +9,6 @@ declare(strict_types=1); * Usage: * php run.php run [arg ...] * php run.php inspect - * 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 [args...] — Run a bundle\n"; - echo " inspect — 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 [args...]\n"); - break; - } - $cmdRun($parts[1], array_slice($parts, 2)); - break; - case 'inspect': - if (!isset($parts[1])) { - fwrite(STDERR, "Usage: inspect \n"); - break; - } - cmdInspect($parts[1]); - break; - case 'help': - echo "Commands:\n"; - echo " run [args...] — Run a bundle\n"; - echo " inspect — 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 [args...]\n"; echo " php run.php inspect \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); } diff --git a/ext/php/src/codecs.php b/ext/php/src/codecs.php index 37e22cc..2e144c8 100644 --- a/ext/php/src/codecs.php +++ b/ext/php/src/codecs.php @@ -54,6 +54,9 @@ function toList(int $tree): array return [true, $rest]; } +/** + * Strings are lists of byte values (each character encoded as a number tree). + */ function ofString(string $s): int { $bytes = []; @@ -104,6 +107,12 @@ function unwrapResult(int $tree): array return $isTrue ? ['ok', $value, $rest] : ['err', $value, $rest]; } +/** + * Host ABI tag constants. + * + * The kernel wraps successful results in a host value envelope: + * Fork(tag_number, payload_tree) + */ const HOST_TREE_TAG = 0; const HOST_STRING_TAG = 1; const HOST_NUMBER_TAG = 2; @@ -129,26 +138,6 @@ function isBool(int $tree): bool return isLeaf($tree) || (isStem($tree) && isLeaf(stemChild($tree))); } -function isNumber(int $tree): bool -{ - [$ok, $_] = toNumber($tree); - return $ok; -} - -function isList(int $tree): bool -{ - [$ok, $_] = toList($tree); - return $ok; -} - -function isString(int $tree): bool -{ - [$ok, $elements] = toList($tree); - if (!$ok) return false; - foreach ($elements as $elem) if (!isNumber($elem)) return false; - return true; -} - function decodeHostPayload(int $tag, int $payload): array { switch ($tag) { @@ -178,26 +167,4 @@ function decodeHostPayload(int $tag, int $payload): array } } -function decodeResult(int $tree): string -{ - $tree = reduce($tree); - if (isLeaf($tree)) return 't'; - [$ok, $str] = toString($tree); - if ($ok && $str !== '') { - $valid = true; - for ($i = 0; $i < strlen($str); $i++) { - $n = ord($str[$i]); - if ($n < 32 || $n > 126) { $valid = false; break; } - } - if ($valid) return '"' . $str . '"'; - } - - [$ok, $num] = toNumber($tree); - if ($ok) return (string)$num; - - [$ok, $xs] = toList($tree); - if ($ok) return '[' . implode(', ', array_map(fn($x) => decodeResult($x), $xs)) . ']'; - - return formatTree($tree); -} diff --git a/ext/php/src/functions.php b/ext/php/src/functions.php index 6da59ef..3b92245 100644 --- a/ext/php/src/functions.php +++ b/ext/php/src/functions.php @@ -5,27 +5,26 @@ declare(strict_types=1); namespace Arboricx; /** - * Arena-backed Tree Calculus representation. + * Arena-backed Tree Calculus graph. * - * Node refs are ints: - * 0 = Leaf + * Nodes are integers (refs) into four parallel arrays: + * tag 0 = Leaf * tag 1 = Stem(child) * tag 2 = Fork(left, right) - * tag 3 = App(function, argument) -- evaluator-internal thunk - * tag 4 = Ind(target) -- update-in-place indirection + * tag 3 = App(function, argument) -- evaluator thunk + * tag 4 = Ind(target) -- update-in-place indirection for sharing + * + * Using ints instead of objects keeps the hot path allocation-free + * and lets us do cheap pointer-equality (same ref == same subtree). */ - $GLOBALS['ARB_TAG'] = [0 => 0]; $GLOBALS['ARB_A'] = [0 => 0]; $GLOBALS['ARB_B'] = [0 => 0]; $GLOBALS['ARB_NEXT'] = 1; -$GLOBALS['ARB_CONS_CACHE'] = []; function spendFuel(int &$fuel): void { - if ($fuel <= 0) { - throw new \RuntimeException('fuel exhausted'); - } + if ($fuel <= 0) throw new \RuntimeException('fuel exhausted'); $fuel--; } @@ -38,14 +37,10 @@ function newNode(int $tag, int $a, int $b = 0): int return $id; } -function updateInd(int $node, int $target): void -{ - if ($node === 0 || $node === $target) return; - $GLOBALS['ARB_TAG'][$node] = 4; - $GLOBALS['ARB_A'][$node] = $target; - $GLOBALS['ARB_B'][$node] = 0; -} - +/** + * Chase indirection (tag 4) chains to the real node. + * Self-loops are treated as terminal to avoid infinite loops. + */ function deref(int $t): int { while ($t !== 0 && ($GLOBALS['ARB_TAG'][$t] ?? -1) === 4) { @@ -56,63 +51,43 @@ function deref(int $t): int return $t; } +/** + * Overwrite a node with an indirection to its reduced form. + * This short-circuits future reads so shared sub-terms are only + * reduced once. + */ +function setInd(int $o, int $t): void +{ + if ($o !== $t) { + $GLOBALS['ARB_TAG'][$o] = 4; + $GLOBALS['ARB_A'][$o] = $t; + } +} + function leaf(): int { return 0; } -function stem(int $child): int { return newNode(1, $child); } -function fork(int $left, int $right): int { return newNode(2, $left, $right); } -function appNode(int $f, int $x): int { return newNode(3, $f, $x); } -function tree(): int { return 0; } +function stem(int $c): int { return newNode(1, $c); } +function fork(int $l, int $r): int { return newNode(2, $l, $r); } +function app(int $f, int $x): int { return newNode(3, $f, $x); } function tag(int $t): int { $t = deref($t); return $GLOBALS['ARB_TAG'][$t] ?? -1; } -function argA(int $t): int { $t = deref($t); return $GLOBALS['ARB_A'][$t]; } -function argB(int $t): int { $t = deref($t); return $GLOBALS['ARB_B'][$t]; } - function isLeaf(int $t): bool { return deref($t) === 0; } function isStem(int $t): bool { return tag($t) === 1; } function isFork(int $t): bool { return tag($t) === 2; } function isApp(int $t): bool { return tag($t) === 3; } -function isTree(int $t): bool { $tag = tag($t); return $tag === 0 || $tag === 1 || $tag === 2; } -function isTerm(int $t): bool { $tag = tag($t); return $tag === 0 || $tag === 1 || $tag === 2 || $tag === 3; } -function stemChild(int $t): int { return argA($t); } -function forkLeft(int $t): int { return argA($t); } -function forkRight(int $t): int { return argB($t); } -function appFunc(int $t): int { return argA($t); } -function appArg(int $t): int { return argB($t); } - -function app(int $f, int $x): int { return appNode($f, $x); } - -function newStemFast(int $child, array &$TAG, array &$A, array &$B): int -{ - $id = $GLOBALS['ARB_NEXT']++; - $TAG[$id] = 1; - $A[$id] = $child; - $B[$id] = 0; - return $id; -} - -function newForkFast(int $left, int $right, array &$TAG, array &$A, array &$B): int -{ - $id = $GLOBALS['ARB_NEXT']++; - $TAG[$id] = 2; - $A[$id] = $left; - $B[$id] = $right; - return $id; -} - -function newAppFast(int $f, int $x, array &$TAG, array &$A, array &$B): int -{ - $id = $GLOBALS['ARB_NEXT']++; - $TAG[$id] = 3; - $A[$id] = $f; - $B[$id] = $x; - return $id; -} - -function apply_(int $a, int $b, int $fuel = 100_000_000_000_000_000): int -{ - return reduce(app($a, $b), $fuel); -} +function stemChild(int $t): int { $t = deref($t); return $GLOBALS['ARB_A'][$t]; } +function forkLeft(int $t): int { $t = deref($t); return $GLOBALS['ARB_A'][$t]; } +function forkRight(int $t): int { $t = deref($t); return $GLOBALS['ARB_B'][$t]; } +function appFunc(int $t): int { $t = deref($t); return $GLOBALS['ARB_A'][$t]; } +function appArg(int $t): int { $t = deref($t); return $GLOBALS['ARB_B'][$t]; } +/** + * Reduce a term to weak-head normal form (WHNF). + * + * The evaluator is iterative (no PHP stack growth) and reduces + * left-to-right: function first, then argument when needed. + * Fuel prevents infinite loops on divergent terms. + */ function reduce(int $term, int $fuel = 100_000_000_000_000_000): int { return whnf($term, $fuel); @@ -125,122 +100,71 @@ function whnf(int $term, int &$fuel): int $B =& $GLOBALS['ARB_B']; while (true) { - // deref term - while ($term !== 0 && $TAG[$term] === 4) { - $term = $A[$term]; - } - - if ($TAG[$term] !== 3) { - return $term; - } + $term = deref($term); + if ($TAG[$term] !== 3) return $term; $orig = $term; $f = whnf($A[$term], $fuel); $x = $B[$term]; - // deref function result - while ($f !== 0 && $TAG[$f] === 4) { - $f = $A[$f]; - } + $f = deref($f); $ftag = $TAG[$f]; // apply Leaf b = Stem b if ($f === 0) { - $result = newStemFast($x, $TAG, $A, $B); - if ($orig !== $result) { $TAG[$orig] = 4; $A[$orig] = $result; $B[$orig] = 0; } - return $result; + $r = newNode(1, $x); setInd($orig, $r); return $r; } // apply (Stem a) b = Fork a b if ($ftag === 1) { - $result = newForkFast($A[$f], $x, $TAG, $A, $B); - if ($orig !== $result) { $TAG[$orig] = 4; $A[$orig] = $result; $B[$orig] = 0; } - return $result; + $r = newNode(2, $A[$f], $x); setInd($orig, $r); return $r; } - if ($ftag !== 2) { - throw new \RuntimeException('apply: function did not reduce to tree'); - } + if ($ftag !== 2) throw new \RuntimeException('apply: function did not reduce to tree'); $left = whnf($A[$f], $fuel); $right = $B[$f]; - - // deref left - while ($left !== 0 && $TAG[$left] === 4) { - $left = $A[$left]; - } + $left = deref($left); $ltag = $TAG[$left]; // apply (Fork Leaf a) _ = a if ($left === 0) { - $term = $right; - if ($orig !== $term) { $TAG[$orig] = 4; $A[$orig] = $term; $B[$orig] = 0; } - spendFuel($fuel); - continue; + $term = $right; setInd($orig, $term); spendFuel($fuel); continue; } // apply (Fork (Stem a) b) c = (a c) (b c) if ($ltag === 1) { - $term = newAppFast( - newAppFast($A[$left], $x, $TAG, $A, $B), - newAppFast($right, $x, $TAG, $A, $B), - $TAG, $A, $B - ); - if ($orig !== $term) { $TAG[$orig] = 4; $A[$orig] = $term; $B[$orig] = 0; } - spendFuel($fuel); - continue; + $term = newNode(3, newNode(3, $A[$left], $x), newNode(3, $right, $x)); + setInd($orig, $term); spendFuel($fuel); continue; } - if ($ltag !== 2) { - throw new \RuntimeException('apply: invalid Fork left child'); - } + if ($ltag !== 2) throw new \RuntimeException('apply: invalid Fork left child'); $arg = whnf($x, $fuel); - while ($arg !== 0 && $TAG[$arg] === 4) { - $arg = $A[$arg]; - } + $arg = deref($arg); $atag = $TAG[$arg]; // apply (Fork (Fork a b) c) Leaf = a if ($arg === 0) { - $term = $A[$left]; - if ($orig !== $term) { $TAG[$orig] = 4; $A[$orig] = $term; $B[$orig] = 0; } - spendFuel($fuel); - continue; + $term = $A[$left]; setInd($orig, $term); spendFuel($fuel); continue; } // apply (Fork (Fork a b) c) (Stem u) = b u if ($atag === 1) { - $term = newAppFast($B[$left], $A[$arg], $TAG, $A, $B); - if ($orig !== $term) { $TAG[$orig] = 4; $A[$orig] = $term; $B[$orig] = 0; } - spendFuel($fuel); - continue; + $term = newNode(3, $B[$left], $A[$arg]); + setInd($orig, $term); spendFuel($fuel); continue; } // apply (Fork (Fork a b) c) (Fork u v) = (c u) v if ($atag === 2) { - $term = newAppFast( - newAppFast($right, $A[$arg], $TAG, $A, $B), - $B[$arg], - $TAG, $A, $B - ); - if ($orig !== $term) { $TAG[$orig] = 4; $A[$orig] = $term; $B[$orig] = 0; } - spendFuel($fuel); - continue; + $term = newNode(3, newNode(3, $right, $A[$arg]), $B[$arg]); + setInd($orig, $term); spendFuel($fuel); continue; } throw new \RuntimeException('apply: argument did not reduce to tree'); } } -function normalize(int $term, int &$fuel): int -{ - $term = whnf($term, $fuel); - if (isStem($term)) return stem(normalize(stemChild($term), $fuel)); - if (isFork($term)) return fork(normalize(forkLeft($term), $fuel), normalize(forkRight($term), $fuel)); - return $term; -} - function same_tree(int $a, int $b): bool { $a = deref($a); $b = deref($b); @@ -253,13 +177,6 @@ function same_tree(int $a, int $b): bool return false; } -function typeTag(int $t): string -{ - return match (tag($t)) { - 0 => 'leaf', 1 => 'stem', 2 => 'fork', 3 => 'app', 4 => 'ind', default => 'unknown' - }; -} - function formatTree(int $t, int $depth = 0): string { $t = deref($t); diff --git a/ext/php/src/kernel.php b/ext/php/src/kernel.php index 83bb70c..c9dcfbf 100644 --- a/ext/php/src/kernel.php +++ b/ext/php/src/kernel.php @@ -5,160 +5,49 @@ declare(strict_types=1); namespace Arboricx; /** - * kernel.php — Hardcoded tricu kernel entrypoints. + * Kernel loader. * - * The kernel is the self-hosted Arboricx runtime written in Tree Calculus, - * compiled to a raw Tree Calculus term. We hardcode it as a **ternary string** - * and parse it on demand. + * The kernel is the self-hosted Arboricx runtime compiled to a raw Tree + * Calculus term. It is shipped as a ternary string and parsed on demand. * - * Ternary string format (from Research.hs toTernaryString): - * '0' → Leaf - * '1' ++ rest → Stem(parse(rest)) - * '2' ++ rest → Fork(parse(rest), parse(rest)) - * - * The Kernel class holds these constants and exposes them as Tree values. + * Ternary string format (matches Research.hs toTernaryString): + * '0' → Leaf + * '1' rest → Stem(parse(rest)) + * '2' l r → Fork(parse(l), parse(r)) */ -use function Arboricx\{leaf, stem, fork, isLeaf, isStem, isFork}; +use function Arboricx\{leaf, stem, fork}; -// ── Kernel constants ──────────────────────────────────────────────────────── - -// ── File loading ──────────────────────────────────────────────────────────── - -/** - * Load a kernel ternary string from a .ternary file. - * - * Convention: ext/php/src/kernel_.ternary - * - * @param string $name e.g. 'run_arboricx_to_string' - * @return string The ternary string, or '' if file not found - */ function loadKernelTernary(string $name): string { - // Determine the base directory: go up from this file to ext/php/src/ - $dir = dirname(__FILE__); - $file = $dir . '/' . $name . '.ternary'; - if (file_exists($file)) { - $content = file_get_contents($file); - if ($content !== false) { - return trim($content); - } - } - return ''; + $file = __DIR__ . '/' . $name . '.ternary'; + if (!file_exists($file)) return ''; + $content = file_get_contents($file); + return $content !== false ? trim($content) : ''; } -// ── Kernel constants (fallbacks — actual values loaded from .ternary files) ─ - -/** - * runArboricxToString — the primary Host ABI entrypoint. - * - * This is the compiled Tree Calculus term for: - * - * runArboricxToString = (bs args : - * bindResult (runArboricxArgsByName [] bs args) - * (value rest : - * wrapHostValue hostString? hostString value rest)) - * - * Loaded from ext/php/src/kernel_run_arboricx_to_string.ternary - * if it exists, otherwise falls back to the constant below. - * - * @var string - */ -const KERNEL_RUN_ARBORICX_TO_STRING = ''; - -/** - * runArboricxByNameToString — named-export variant. - * - * runArboricxByNameToString = (nameBytes bs args : ...) - * - * Loaded from ext/php/src/kernel_run_arboricx_by_name_to_string.ternary - * if it exists, otherwise falls back to the constant below. - * - * @var string - */ -const KERNEL_RUN_ARBORICX_BY_NAME_TO_STRING = ''; - -// ── Parser ────────────────────────────────────────────────────────────────── - -/** - * Parse a ternary string into a Tree Calculus value. - * - * Grammar: - * term → '0' → Leaf - * → '1' term → Stem(term) - * → '2' term term → Fork(term, term) - * - * @param string $s The ternary string to parse - * @param int &$pos Current position (passed by reference) - * @return int The parsed Tree value node id - */ function parseTernary(string $s, int &$pos = 0): int { if ($pos >= strlen($s)) { throw new \RuntimeException('parseTernary: unexpected end of string'); } - - $char = $s[$pos]; - $pos++; - + $char = $s[$pos++]; return match ($char) { '0' => leaf(), '1' => stem(parseTernary($s, $pos)), '2' => fork(parseTernary($s, $pos), parseTernary($s, $pos)), - default => throw new \RuntimeException( - "parseTernary: unexpected char '$char' at position $pos" - ), + default => throw new \RuntimeException("parseTernary: unexpected char '$char' at position $pos"), }; } -// ── Kernel accessors ──────────────────────────────────────────────────────── - -/** - * Get the runArboricxToString kernel tree. - * - * Tries loading from ext/php/src/kernel_run_arboricx_to_string.ternary first, - * then falls back to the KERNEL_RUN_ARBORICX_TO_STRING constant. - * - * Returns the parsed Tree Calculus value, or null if not configured. - */ function getRunArboricxToString(): ?int { - // Try file first $term = loadKernelTernary('kernel_run_arboricx_to_string'); - if ($term === '') { - $term = KERNEL_RUN_ARBORICX_TO_STRING; - } - if ($term === '') { - return null; - } + if ($term === '') return null; $pos = 0; $tree = parseTernary($term, $pos); if ($pos !== strlen($term)) { - throw new \RuntimeException('kernel ternary has trailing data: parsed ' . $pos . ' of ' . strlen($term) . ' bytes'); - } - return $tree; -} - -/** - * Get the runArboricxByNameToString kernel tree. - * - * Tries loading from ext/php/src/kernel_run_arboricx_by_name_to_string.ternary - * first, then falls back to the KERNEL_RUN_ARBORICX_BY_NAME_TO_STRING constant. - */ -function getRunArboricxByNameToString(): ?int -{ - // Try file first - $term = loadKernelTernary('kernel_run_arboricx_by_name_to_string'); - if ($term === '') { - $term = KERNEL_RUN_ARBORICX_BY_NAME_TO_STRING; - } - if ($term === '') { - return null; - } - $pos = 0; - $tree = parseTernary($term, $pos); - if ($pos !== strlen($term)) { - throw new \RuntimeException('kernel ternary has trailing data: parsed ' . $pos . ' of ' . strlen($term) . ' bytes'); + throw new \RuntimeException("kernel ternary has trailing data: parsed $pos of " . strlen($term) . ' bytes'); } return $tree; }