#!/usr/bin/env node /** * cli.js — Arboricx JS host shell via libarboricx C ABI. * * Usage: * node cli.js inspect * node cli.js run [args...] */ import { readFileSync } from 'node:fs'; import { init, free, loadBundleDefault, reduce, app, ofNumber, ofString, decode, decodeType, findLib, } from './lib.js'; // ── Commands ───────────────────────────────────────────────────────────────── function cmdInspect(bundlePath) { const ctx = init(); try { const bundle = readFileSync(bundlePath); console.log(`Bundle: ${bundlePath}`); console.log(`Size: ${bundle.length} bytes\n`); const term = loadBundleDefault(ctx, bundle); const result = reduce(ctx, term); const type = decodeType(ctx, result); let value; try { value = decode(ctx, result); } catch { value = '(raw tree)'; } console.log(`Type: ${type}`); console.log(`Value: ${value}`); } catch (e) { console.error(`Error: ${e.message}`); process.exit(1); } finally { free(ctx); } } function cmdRun(bundlePath, args) { const ctx = init(); try { const bundle = readFileSync(bundlePath); let term = loadBundleDefault(ctx, bundle); for (const arg of args) { const argTree = /^\d+$/.test(arg) ? ofNumber(ctx, BigInt(arg)) : ofString(ctx, arg); term = app(ctx, term, argTree); } const result = reduce(ctx, term); console.log(decode(ctx, result)); } catch (e) { console.error(`Error: ${e.message}`); process.exit(1); } finally { free(ctx); } } // ── Main ───────────────────────────────────────────────────────────────────── const args = process.argv.slice(2); const command = args[0]; switch (command) { case 'inspect': { if (args.length < 2) { console.error('Usage: node cli.js inspect '); process.exit(1); } cmdInspect(args[1]); break; } case 'run': { if (args.length < 2) { console.error('Usage: node cli.js run [args...]'); process.exit(1); } cmdRun(args[1], args.slice(2)); break; } default: console.log('Arboricx JS Host (via libarboricx FFI)'); console.log(''); console.log('Usage:'); console.log(' node cli.js inspect '); console.log(' node cli.js run [args...]'); break; }