#! /usr/bin/env bash
set +x

# This script iterates through each spec file and tries to build and run it.
#
# * `failed codegen` annotates specs that error in the compiler.
#   This is mostly caused by some API not being ported to wasm32 (either the spec
#   target itself or some tools used by the spec).
# * `failed linking` annotates specs that compile but don't link.
#   Most failures are caused by missing libraries (libxml2, libyaml, libgmp,
#   libllvm, libz, libssl).
# * `failed to run` annotates specs that compile and link but don't properly
#   execute.
#
# PREREQUISITES:
#
# - wasmtime (https://wasmtime.dev/)
#
# Note: Libs are downloaded from https://github.com/lbguilherme/wasm-libs
#
# USAGE:
#
# $ spec/generate_wasm32_spec.sh > spec/wasm32_std_spec.cr

WORK_DIR=$(mktemp -d)
function cleanup {
  rm -rf "$WORK_DIR"
}
trap cleanup EXIT

mkdir "$WORK_DIR"/wasm32-wasi-libs
curl -L https://github.com/lbguilherme/wasm-libs/releases/download/0.0.2/wasm32-wasi-libs.tar.gz | tar -C "$WORK_DIR"/wasm32-wasi-libs -xz
export CRYSTAL_LIBRARY_PATH="$WORK_DIR"/wasm32-wasi-libs

command="$0 $*"
echo "# This file is autogenerated by \`${command% }\`"
echo "# $(date --rfc-3339 seconds)"
echo

for spec in $(find "spec/std" -type f -iname "*_spec.cr" | LC_ALL=C sort); do
  require="require \"./${spec##spec/}\""
  target="$WORK_DIR/$spec.wasm"
  mkdir -p "$(dirname "$target")"

  if ! output=$(bin/crystal build "$spec" -o "$target" --target wasm32-wasi 2>&1); then
    if [[ "$output" =~ "execution of command failed" ]]; then
      echo "# $require (failed linking)"
    else
      echo "# $require (failed codegen)"
    fi
    continue
  fi

  wasmtime run "$target" > /dev/null; exit=$?

  if [ $exit -eq 0 ]; then
    echo "$require"
  else
    echo "# $require (failed to run)"
  fi
done
