#!/usr/bin/env bash
# run.sh - build and execute the nlg/ acceptance corpus.
#
# Each examples/<case>.el is a self-contained El program that calls NLG
# functions and prints a deterministic result line. Because El has no
# import system, the runner concatenates all NLG source modules above each
# test file before handing it to elc.
#
# Module load order (mirrors manifest.el dependency order):
#   language-profile  (no deps)
#   vocabulary        (no deps)
#   morphology        (depends on: language-profile)
#   morphology-XX     (depends on: morphology)  -- one per language
#   grammar           (depends on: language-profile)
#   realizer          (depends on: morphology, grammar, language-profile)
#   semantics         (depends on: grammar, realizer, language-profile)
#   nlg               (depends on: semantics, realizer)
#   <test>.el         (calls the above)

set -uo pipefail
cd "$(dirname "$0")"

EL_HOME="${EL_HOME:-$(cd ../.. && pwd)/el}"
ELC="${ELC:-${EL_HOME}/dist/platform/elc}"
RUNTIME_DIR="${EL_HOME}/runtime"
SRC_DIR="$(cd .. && pwd)/src"

if [ ! -x "${ELC}" ]; then
    echo "elc not found at ${ELC}" >&2
    exit 1
fi

# NLG source modules in manifest.el dependency order
NLG_MODULES=(
    "${SRC_DIR}/language-profile.el"
    "${SRC_DIR}/vocabulary.el"
    "${SRC_DIR}/morphology.el"
    # Living languages
    "${SRC_DIR}/morphology-es.el"
    "${SRC_DIR}/morphology-fr.el"
    "${SRC_DIR}/morphology-de.el"
    "${SRC_DIR}/morphology-ru.el"
    "${SRC_DIR}/morphology-ja.el"
    "${SRC_DIR}/morphology-fi.el"
    "${SRC_DIR}/morphology-ar.el"
    "${SRC_DIR}/morphology-hi.el"
    "${SRC_DIR}/morphology-sw.el"
    # Ancient / classical languages (still spoken or liturgical)
    "${SRC_DIR}/morphology-la.el"
    "${SRC_DIR}/morphology-he.el"
    # Dead languages
    "${SRC_DIR}/morphology-grc.el"
    "${SRC_DIR}/morphology-ang.el"
    "${SRC_DIR}/morphology-sa.el"
    "${SRC_DIR}/morphology-got.el"
    "${SRC_DIR}/morphology-non.el"
    "${SRC_DIR}/morphology-enm.el"
    "${SRC_DIR}/morphology-pi.el"
    "${SRC_DIR}/morphology-fro.el"
    "${SRC_DIR}/morphology-goh.el"
    "${SRC_DIR}/morphology-sga.el"
    "${SRC_DIR}/morphology-txb.el"
    "${SRC_DIR}/morphology-peo.el"
    "${SRC_DIR}/morphology-akk.el"
    "${SRC_DIR}/morphology-uga.el"
    "${SRC_DIR}/morphology-egy.el"
    "${SRC_DIR}/morphology-sux.el"
    "${SRC_DIR}/morphology-gez.el"
    "${SRC_DIR}/morphology-cop.el"
    # Higher layers
    "${SRC_DIR}/grammar.el"
    "${SRC_DIR}/realizer.el"
    "${SRC_DIR}/semantics.el"
    "${SRC_DIR}/nlg.el"
)

PASS=0
FAIL=0
FAILED_NAMES=()

run_nlg_case() {
    local name="$1"
    local src="$2"
    local expected="$3"

    local combined_src
    local out_c
    local out_bin
    combined_src="$(mktemp -t nlg_test.XXXXXX).el"
    out_c="$(mktemp -t nlg_test.XXXXXX).c"
    out_bin="$(mktemp -t nlg_test.XXXXXX)"

    # Concatenate modules + test file
    for mod in "${NLG_MODULES[@]}"; do
        cat "${mod}" >> "${combined_src}"
        echo "" >> "${combined_src}"
    done
    cat "${src}" >> "${combined_src}"

    if ! "${ELC}" "${combined_src}" > "${out_c}" 2>/tmp/nlg_test.elc.err; then
        echo "FAIL  ${name} - elc emit failed:"
        cat /tmp/nlg_test.elc.err | sed 's/^/      /'
        FAIL=$((FAIL+1))
        FAILED_NAMES+=("${name}")
        rm -f "${combined_src}" "${out_c}" "${out_bin}"
        return
    fi

    if ! cc -O2 -I "${RUNTIME_DIR}" "${out_c}" "${RUNTIME_DIR}/el_runtime.c" \
            -lcurl -lpthread -o "${out_bin}" 2>/tmp/nlg_test.cc.err; then
        echo "FAIL  ${name} - cc failed:"
        cat /tmp/nlg_test.cc.err | sed 's/^/      /'
        FAIL=$((FAIL+1))
        FAILED_NAMES+=("${name}")
        rm -f "${combined_src}" "${out_c}" "${out_bin}"
        return
    fi

    local got
    got="$("${out_bin}" 2>&1)"

    if [ "${got}" = "${expected}" ]; then
        echo "PASS  ${name}"
        PASS=$((PASS+1))
    else
        echo "FAIL  ${name}  expected: '${expected}', got: '${got}'"
        FAIL=$((FAIL+1))
        FAILED_NAMES+=("${name}")
    fi

    rm -f "${combined_src}" "${out_c}" "${out_bin}"
}

echo "==> Running nlg acceptance corpus"
echo

run_nlg_case "basic-sentence"    examples/basic-sentence.el    "I see the cat."
run_nlg_case "past-tense"        examples/past-tense.el        "She ran in the park."
run_nlg_case "question"          examples/question.el          "Do you see the dog?"
run_nlg_case "command"           examples/command.el           "Go home."
run_nlg_case "plural-noun"       examples/plural-noun.el       "cats|children|boxes|cities|fish|leaves"
run_nlg_case "verb-conjugation"  examples/verb-conjugation.el  "ran|walked|is|am|sleeping"
run_nlg_case "sem-assert"        examples/sem-assert.el        "She sleeps."
run_nlg_case "sem-query"         examples/sem-query.el         "Do you see?"
run_nlg_case "sem-describe"      examples/sem-describe.el      "The cat is big."
run_nlg_case "sem-greet"         examples/sem-greet.el         "Hello, Alice."

echo
echo "${PASS} passed, ${FAIL} failed"
if [ "${FAIL}" -gt 0 ]; then
    echo "failed: ${FAILED_NAMES[*]}"
    exit 1
fi
exit 0
