#!/usr/bin/env node
// Test js_of_ocaml build of SX kernel
const path = require('path');
require(path.join(__dirname, '../_build/default/browser/sx_browser.bc.js'));

const sx = globalThis.SxKernel;
console.log('Engine:', sx.engine());

const tests = [
  ['(+ 1 2)', 3],
  ['(- 10 3)', 7],
  ['(* 6 7)', 42],
  ['(/ 10 2)', 5],
  ['(= 5 5)', true],
  ['(< 3 5)', true],
  ['(> 5 3)', true],
  ['(not false)', true],
  ['(inc 5)', 6],
  ['(dec 5)', 4],
  ['(len (list 1 2 3))', 3],
  ['(len "hello")', 5],
  ['(first (list 10 20))', 10],
  ['(nth "hello" 0)', 'h'],
  ['(nth "hello" 4)', 'o'],
  ['(str "a" "b")', 'ab'],
  ['(join ", " (list "a" "b" "c"))', 'a, b, c'],
  ['(let ((x 10) (y 20)) (+ x y))', 30],
  ['(if true "yes" "no")', 'yes'],
  ['(cond (= 1 2) "one" :else "other")', 'other'],
  ['(case 2 1 "one" 2 "two" :else "other")', 'two'],
  ['(render-to-html (list (quote div) "hello"))', '<div>hello</div>'],
  ['(render-to-html (list (quote span) (list (quote b) "bold")))', '<span><b>bold</b></span>'],
  // Lambda + closure
  ['(let ((add (fn (a b) (+ a b)))) (add 3 4))', 7],
  ['(let ((x 10)) (let ((f (fn () x))) (f)))', 10],
  // Higher-order
  ['(len (filter (fn (x) (> x 2)) (list 1 2 3 4 5)))', 3],
  // Recursion
  ['(let ((fact (fn (n) (if (<= n 1) 1 (* n (fact (- n 1))))))) (fact 5))', 120],
];

let passed = 0, failed = 0;
for (const [expr, expected] of tests) {
  try {
    const result = sx.eval(expr);
    const ok = typeof expected === 'object'
      ? result && result._type === expected._type
      : result === expected;
    if (ok) {
      passed++;
    } else {
      console.log(`  FAIL: ${expr} = ${JSON.stringify(result)} (expected ${JSON.stringify(expected)})`);
      failed++;
    }
  } catch (e) {
    console.log(`  ERROR: ${expr}: ${e.message || e}`);
    failed++;
  }
}

console.log(`${passed} passed, ${failed} failed`);
process.exit(failed > 0 ? 1 : 0);
