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

build_root=$1
cli_dir="$build_root/src/cli"
php2ast="$cli_dir/phpefc-php2ast"
phpast2phpir="$cli_dir/phpefc-phpast2phpir"
phpir2valair="$cli_dir/phpefc-phpir2valair"
valair_optimize_typing="$cli_dir/phpefc-valair-optimize-typing"
valair_optimize_library="$cli_dir/phpefc-valair-optimize-library"
valair_optimize_precompute="$cli_dir/phpefc-valair-optimize-precompute"
valair2vala="$cli_dir/phpefc-valair2vala"

for tool in "$php2ast" "$phpast2phpir" "$phpir2valair" "$valair_optimize_typing" "$valair_optimize_library" "$valair_optimize_precompute" "$valair2vala"; do
    if [ ! -x "$tool" ]; then
        echo "missing built tool: $tool" >&2
        exit 99
    fi
done

work=${MESON_TEST_TMPDIR:-}
if [ -z "$work" ]; then
    work=$(mktemp -d)
    trap 'rm -rf "$work"' EXIT
fi
mkdir -p "$work"

src="$work/precompute-constant.php"
cat >"$src" <<'PHP'
<?php
echo constant("PHP_EOL");
PHP

phpast="$work/precompute-constant.phpast"
phpir="$work/precompute-constant.phpir"
valair="$work/precompute-constant.valair"
"$php2ast" "$src" "$phpast" >/dev/null
"$phpast2phpir" "$phpast" "$phpir" >/dev/null
"$phpir2valair" "$phpir" "$valair" >/dev/null

assert_precomputed_vala() {
    local vala=$1
    if grep -Fq 'phpfunc_constant' "$vala"; then
        echo "constant call remained in $vala" >&2
        cat "$vala" >&2
        exit 1
    fi
    if ! grep -Fq 'Zval.from_string("\n")' "$vala"; then
        echo "expected precomputed PHP_EOL newline Zval in $vala" >&2
        cat "$vala" >&2
        exit 1
    fi
}

# RuntimeEmbed generic constant() call.
embed_after="$work/precompute-constant.embed.afteropt.precompute"
embed_vala="$work/precompute-constant.embed.vala"
"$valair_optimize_precompute" "$valair" "$embed_after" >/dev/null
"$valair2vala" "$embed_after" "$embed_vala" >/dev/null
assert_precomputed_vala "$embed_vala"
if ! grep -a -Fq '// phpefc optimizer precompute result: 1 calls precomputed, 0 skipped' "$embed_after"; then
    echo 'expected precompute marker for RuntimeEmbed generic constant' >&2
    cat "$embed_after" >&2
    exit 1
fi

# RuntimeNativeStandard generic constant() call after library-embed2native.
typing_after="$work/precompute-constant.afteropt.typing-zval2static"
native_after="$work/precompute-constant.afteropt.library-embed2native"
native_generic_after="$work/precompute-constant.native-generic.afteropt.precompute"
native_generic_vala="$work/precompute-constant.native-generic.vala"
"$valair_optimize_typing" --suppress-warning "$valair" "$typing_after" >/dev/null
"$valair_optimize_library" --allowed-native-runtimes standard "$typing_after" "$native_after" >/dev/null
"$valair_optimize_precompute" "$native_after" "$native_generic_after" >/dev/null
"$valair2vala" "$native_generic_after" "$native_generic_vala" >/dev/null
assert_precomputed_vala "$native_generic_vala"

# RuntimeNativeStandard typed constant(string) call after final typing.
typed_after="$work/precompute-constant.afteropt.typing-zval2static-final"
native_typed_after="$work/precompute-constant.native-typed.afteropt.precompute"
native_typed_vala="$work/precompute-constant.native-typed.vala"
"$valair_optimize_typing" "$native_after" "$typed_after" >/dev/null 2>"$work/final-typing.stderr"
if ! grep -a -Fq 'PhpefRuntimeNativeStandard.phpfunc_constant_typed_zval_arg1_string' "$typed_after"; then
    echo 'expected final typing to create NativeStandard typed constant before precompute' >&2
    cat "$typed_after" >&2
    exit 1
fi
"$valair_optimize_precompute" "$typed_after" "$native_typed_after" >/dev/null
"$valair2vala" "$native_typed_after" "$native_typed_vala" >/dev/null
assert_precomputed_vala "$native_typed_vala"

printf 'ok - precompute folds Embed and NativeStandard constant PHP_EOL calls\n'
