#!/usr/bin/env node
/**
 * test-named-let-set.js — WASM kernel tests for set! inside named let loops.
 *
 * FAILING: set! inside named let body does not persist mutations to
 * the enclosing scope. This breaks tokenize-sx → highlight → source display.
 */
const { createSxEnv } = require('./sx-harness');

let passed = 0, failed = 0;
const origLog = console.log;
const origErr = console.error;

function test(name, expr, expected) {
  let env;
  try {
    // Fresh env per test to avoid cross-contamination
    // But creating env is slow, so we'll reuse one below
  } catch(e) {}
}

async function main() {
  origLog('=== Named Let + set! Tests (WASM kernel) ===\n');
  const t0 = Date.now();

  const env = await createSxEnv({});

  function check(name, expr, expected) {
    const result = env.eval(expr);
    const expectedStr = JSON.stringify(expected);
    const resultVal = result?.items ? result.items : result;
    const resultStr = JSON.stringify(resultVal);
    if (resultStr === expectedStr) {
      passed++;
      origLog(`  \u2713 ${name}`);
    } else {
      failed++;
      origErr(`  \u2717 ${name}: expected ${expectedStr}, got ${resultStr}`);
    }
  }

  // ---- Baselines (should pass) ----
  origLog('Baselines:');
  check('set! in plain let',
    '(let ((x 0)) (set! x 42) x)', 42);

  check('named let without set! (functional accumulator)',
    '(trampoline (let loop ((i 0) (acc 0)) (if (< i 5) (loop (+ i 1) (+ acc i)) acc)))', 10);

  check('append! on outer binding (no named let)',
    '(let ((xs (list))) (append! xs 1) (append! xs 2) xs)', [1, 2]);

  // ---- Named let + set! (the broken cases) ----
  origLog('\nNamed let + set!:');
  check('set! counter in named let loop',
    '(let ((x 0)) (let loop () (when (< x 5) (set! x (+ x 1)) (loop))) x)', 5);

  check('set! counter in named let loop (with param)',
    '(let ((total 0)) (let loop ((i 1)) (when (<= i 10) (set! total (+ total i)) (loop (+ i 1)))) total)', 55);

  check('set! list via append in named let',
    '(let ((acc (list))) (let loop ((i 0)) (when (< i 3) (set! acc (append acc (list i))) (loop (+ i 1)))) acc)', [0, 1, 2]);

  check('append! in named let',
    '(let ((acc (list)) (i 0)) (let loop () (when (< i 3) (append! acc i) (set! i (+ i 1)) (loop))) acc)', [0, 1, 2]);

  check('set! string concat in named let',
    '(let ((result "")) (let loop ((i 0)) (when (< i 3) (set! result (str result (str i))) (loop (+ i 1)))) result)', "012");

  // ---- Nested named let ----
  origLog('\nNested:');
  check('set! in nested named let',
    '(let ((count 0)) (let outer ((i 0)) (when (< i 3) (let inner ((j 0)) (when (< j 2) (set! count (+ count 1)) (inner (+ j 1)))) (outer (+ i 1)))) count)', 6);

  env.close();

  const dt = Date.now() - t0;
  origLog(`\n=== ${passed} passed, ${failed} failed (${dt}ms) ===`);
  process.exit(failed > 0 ? 1 : 0);
}

main().catch(e => { origErr(e); process.exit(1); });
