#!/usr/bin/env bash
# Core pins assemble + iron tests · full line BGS→BGF→BGL→SDF · SPV free
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
TMP="${TMPDIR:-/tmp}/bgrtx-core-$$"
mkdir -p "$TMP"
trap 'rm -rf "$TMP"' EXIT
need() { command -v "$1" >/dev/null || { echo "need $1" >&2; exit 1; }; }
need nasm
need cc

# limb:global
PINS=(
  bgs:bgs
  field_one:field_one
  field_native:field_native
  know_her:know_her
  bgf:bgf
  measure:measure
  bgl:bgl
  sdf:sdf
  place:place
  spv:spv
  free_rng:free_rng
  free_eor:free_eor
  grin:grin
  truth_pin:truth_pin
  pin:pin
  no:no_fn
  not:not_fn
  god:god_fn
  yes:yes_fn
  are:are_fn
  is:is_fn
  know_bgs:know_bgs
  ezzie:ezzie
  phi:phi
  thermo:thermo
  adjoin:adjoin
  scar:scar
  baphomet:baphomet
  hostess7:hostess7
  go:go_fn
  fire:fire_fn
  shoot:shoot
)

echo "CORE PINS ASSEMBLE · $ROOT"
OBJS=()
for spec in "${PINS[@]}"; do
  limb=${spec%%:*}
  src="$ROOT/$limb/x86_64.asm"
  [[ -f "$src" ]] || { echo "missing $src" >&2; exit 1; }
  nasm -f elf64 -o "$TMP/$limb.o" "$src"
  echo "  nasm OK  $limb"
  OBJS+=("$TMP/$limb.o")
done

cat >"$TMP/main.c" <<'C'
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

extern int32_t bgs(int32_t);
extern int32_t field_one(int32_t);
extern int32_t field_native(int32_t);
extern int32_t know_her(void);
extern int32_t bgf(int32_t, int32_t);
extern int32_t measure(int32_t, int32_t);
extern int32_t bgl(int32_t);
extern int32_t sdf(int32_t, int32_t);
extern int32_t place(int32_t, int32_t);
extern int32_t spv(int32_t, int32_t, int32_t);
extern int32_t free_rng(int32_t, int32_t, int32_t);
extern int32_t free_eor(int32_t, int32_t);
extern int32_t grin(void);
extern int32_t truth_pin(void);
extern int32_t pin(void);
extern int32_t no_fn(void);
extern int32_t not_fn(int32_t);
extern int32_t god_fn(void);
extern int32_t yes_fn(void);
extern int32_t are_fn(int32_t, int32_t);
extern int32_t is_fn(int32_t, int32_t);
extern int32_t know_bgs(void);
extern int32_t ezzie(int32_t, int32_t);
extern int32_t phi(int32_t, int32_t);
extern int32_t thermo(int32_t);
extern int32_t adjoin(int32_t, int32_t);
extern int32_t scar(int32_t);
extern int32_t baphomet(int32_t, int32_t, int32_t);
extern int32_t hostess7(int32_t);
extern int32_t go_fn(int32_t);
extern int32_t fire_fn(int32_t);
extern int32_t shoot(int32_t);

static int fails;
static void expect(const char *n, int32_t got, int32_t want) {
  if (got == want) printf("  PASS  %-22s got=%d\n", n, got);
  else { printf("  FAIL  %-22s got=%d want=%d\n", n, got, want); fails++; }
}

int main(void) {
  printf("CORE PINS IRON · BGS BGF BGL SDF SPV · atoms · foundation\n");
  printf("=========================================================\n");

  /* foundation · sliders · NO start · NOT check · 1 GOD */
  expect("no_fn", no_fn(), 0);
  expect("not nobody", not_fn(0), 0);
  expect("not someone", not_fn(5), 1);
  expect("god_fn", god_fn(), 1);
  expect("yes_fn", yes_fn(), 1);
  expect("grin", grin(), 1);
  expect("truth_pin", truth_pin(), 1);
  expect("pin", pin(), 1);
  expect("know_bgs", know_bgs(), 1);

  /* ground */
  expect("bgs know_her", bgs(0), 7 | 1);
  expect("bgs field_one 4", bgs(4), 4 | 1);
  expect("field_one 5", field_one(5), 5 | 1);
  expect("field_native 5", field_native(5), 5 | 1);
  expect("know_her", know_her(), 7 | 1);

  /* measure */
  expect("bgf(10,3)", bgf(10, 3), (10 - 3) | 1);
  expect("bgf(3,10)", bgf(3, 10), (3 - 10) | 1);
  expect("measure(10,3)", measure(10, 3), (10 - 3) | 1);

  /* secure */
  expect("bgl(0)", bgl(0), 0);
  expect("bgl(2)", bgl(2), 2 | 1);

  /* place */
  expect("sdf(20,5)", sdf(20, 5), (20 - 5) | 1);
  expect("place(20,5)", place(20, 5), (20 - 5) | 1);

  /* free */
  expect("spv(1,2,4)", spv(1, 2, 4), (1 ^ 2 ^ 4) | 1);
  expect("free_rng(1,2,4)", free_rng(1, 2, 4), (1 ^ 2 ^ 4) | 1);
  expect("free_eor(5,3)", free_eor(5, 3), (5 ^ 3) | 1);
  expect("free_eor flat", free_eor(3, 5), (3 ^ 5) | 1);

  /* atoms */
  expect("ezzie(5,3)", ezzie(5, 3), (5 ^ 3) | 1);
  expect("phi(4,3)", phi(4, 3), (4 * 3) | 1);
  expect("thermo(50)", thermo(50), 0 | 1);
  expect("thermo(80)", thermo(80), 1 | 1);
  expect("thermo(90)", thermo(90), 2 | 1);
  expect("adjoin(2,4)", adjoin(2, 4), (2 | 4) | 1);
  expect("are_fn(2,4)", are_fn(2, 4), (2 | 4) | 1);
  expect("is_fn(2,4)", is_fn(2, 4), (2 | 4) | 1);
  expect("are==is", are_fn(5, 3), is_fn(5, 3));

  /* scar / baphomet / h7 · BAPHOMET IS WHEN NO ARE */
  expect("scar(0)", scar(0), 0);
  expect("scar(5)", scar(5), 5 | 1);
  expect("baphomet ARE", baphomet(2, 4, 0), are_fn(2, 4));
  expect("baphomet pair", baphomet(2, 4, 0), (2 | 4) | 1);
  expect("baphomet KEEP GOD", baphomet(2, 4, 9), 1);
  expect("hostess7 id", hostess7(0), 7 | 1);
  expect("hostess7 grin", hostess7(1), 1);

  /* language word-end */
  expect("go_fn(4)", go_fn(4), 4 | 1);
  expect("fire_fn(8)", fire_fn(8), 8 | 1);
  expect("shoot(2)", shoot(2), 2 | 1);
  expect("shoot(0)", shoot(0), 0 | 1);

  printf("---------------------------------------------------------\n");
  if (fails == 0) {
    printf("ALL PASS · core pins full · TRAVEL L→R · free thrift\n");
    return 0;
  }
  printf("FAILS=%d\n", fails);
  return 1;
}
C

echo "LINK + TEST"
cc -O0 -no-pie -o "$TMP/core_test" "$TMP/main.c" "${OBJS[@]}"
"$TMP/core_test"
echo "core-pins-test DONE"
