#!/usr/bin/env bash
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"

make -C "$ROOT" -s >/dev/null

BIN="$ROOT/flowlog"

fail() {
  echo "fail: $1" >&2
  exit 1
}

mk_nested_term() {
  local depth="$1"
  local t="x"
  local i
  for (( i = 0; i < depth; i++ )); do
    t="f($t)"
  done
  printf '%s' "$t"
}

tmpdir="$(mktemp -d -t flowlog_depth_limits.XXXXXX)"
cleanup() {
  rm -rf "$tmpdir" >/dev/null 2>&1 || true
}
trap cleanup EXIT

LIMITED_BIN="$tmpdir/flowlog_limited"
cc -O2 -Wall -Wextra -pthread \
  -DFLOWLOG_DEPTH_LIMIT=16 \
  -DFLOWLOG_SOLVE_DEPTH_LIMIT=32 \
  -DFLOWLOG_TRACE_MAX_DEPTH=16 \
  "$ROOT/flowlog.c" -lm -o "$LIMITED_BIN"

term="$(mk_nested_term 120)"
goal="X=$term,write(X),nl,halt."

out="$("$BIN" --engine interp -g "$goal" | tr -d '\r')"
if grep -q '\.\.\.' <<<"$out"; then
  fail "default_depth_limit_should_be_unlimited"
fi

out="$("$LIMITED_BIN" --engine interp -g "$goal" | tr -d '\r')"
if ! grep -q '\.\.\.' <<<"$out"; then
  fail "explicit_depth_limit_should_cap_output"
fi

TRACE_PROG="$tmpdir/trace_depth.pl"
cat > "$TRACE_PROG" <<'PL'
deep(0) :- throw(oops).
deep(N) :- N > 0, N1 is N - 1, deep(N1).
PL

out="$("$BIN" --trace -f -g "deep(20)." "$TRACE_PROG" 2>&1 | tr -d '\r')"
if grep -q 'trace overflow' <<<"$out"; then
  fail "default_trace_depth_should_be_unlimited"
fi

out="$("$LIMITED_BIN" --trace -f -g "deep(20)." "$TRACE_PROG" 2>&1 | tr -d '\r')"
if ! grep -q 'trace overflow' <<<"$out"; then
  fail "explicit_trace_depth_should_cap_stack"
fi

echo "ok"
