git @ Cat's Eye Technologies Jaft / master src / jaftInterpreter.js
master

Tree @master (Download .tar.gz)

jaftInterpreter.js @masterraw · history · blame

#!/usr/bin/env node

// Copyright (c) 2026 Chris Pressey, Cat's Eye Technologies.
//
// SPDX-License-Identifier: LicenseRef-MIT-X-Jaft

import { readFileSync } from "fs";
import { bless } from "concoctor";
import { concoctJaft } from "./jaftConcoctor.js";

function parseArgs(argv) {
  const env = {};
  let isFunDef = false;
  let filenames = [];
  for (let i = 0; i < argv.length; i++) {
    const a = argv[i];
    if (a === "--expose") {
      const spec = argv[i + 1];
      if (!spec) continue;
      const idx = spec.indexOf(":");
      const name = spec.slice(0, idx).trim();
      let expr = spec.slice(idx + 1).trim();
      env[name] = bless(eval(expr));
      i++;
    } else if (a === "--fundef") {
      isFunDef = true;
    } else {
      filenames.push(a);
    }
  }
  return [filenames, isFunDef, env];
}

function main() {
  const args = process.argv.slice(2);
  const [filenames, isFunDef, env] = parseArgs(args);

  if (filenames.length === 0) {
    console.error("Error: No source file specified");
    console.error("Usage: npm run jafti <source-file> -- {options}");
    process.exit(1);
  }

  const sourceFile = filenames[0];

  try {
    const sourceCode =
      (isFunDef ? "" : "() => ") + readFileSync(sourceFile, "utf-8");
    const fn = concoctJaft(env, sourceCode);
    let value = null;
    if (isFunDef) {
      const inputText = readFileSync(0, "utf8").trim();
      value = JSON.parse(inputText);
    }
    const result = fn(value);
    console.log(JSON.stringify(result));
  } catch (error) {
    if (error.code === "ENOENT") {
      console.error(`Error: File not found: ${sourceFile}`);
    } else if (error.message) {
      console.error(`Error: ${error.message}`);
    } else {
      console.error("Error:", error);
    }
    process.exit(1);
  }
}

main();