#!/usr/bin/env bash

# Usage:
# test.sh LANGUAGE TEST
#   Run the TEST in LANGUAGE.
# test.sh -a
#   Build all tests.
# test.sh -b SOURCE_FILE...
#   Build a test from SOURCE_FILE(s).
# test.sh -c
#   Clean all executables.
# test.sh -v LANGUAGE TEST FILE
#   View the result from TEST in LANGUAGE stored in FILE.

readonly DIR=$(dirname "$(readlink -f "$0")")
cd $DIR

readonly MIL=000000
# Various preset values used as arguments.
readonly ITERS_1M=1$MIL
readonly ITERS_10M=10$MIL
readonly ITERS_100M=100$MIL
readonly ITERS_1000M=1000$MIL
readonly STACK_HEIGHT=100

# Build Test Programs:
# Mini-Make: TARGET SOURCE COMMAND ARGS...
mmake() (
	if [ ! -e "$1" -o "$1" -ot "$2" ]; then
		"${@:3}"
	fi
)

build() (
	case "$1" in
	*.cfa)
		# A symbolic link/local copy can be used as an override.
		cmd=./cfa
		if [ ! -x $cmd ]; then
			cmd=cfa
		fi
		mmake "${1%.cfa}" "$1" $cmd -DNDEBUG -nodebug -O3 "$1" -o "${1%.cfa}"
		;;
	*.cpp)
		mmake "${1%.cpp}-cpp" "$1" g++-10 -DNDEBUG -O3 "$1" -o "${1%.cpp}-cpp"
		;;
	*.java)
		mmake "${1%.java}.class" "$1" javac "$1"
		;;
	*)
		echo "Don't know how to build:" $1 >&2
		exit 2
		;;
	esac
)

if [ "-a" = "$1" ]; then
	for file in *.cfa *.cpp *.java; do
		build $file
	done
	exit 0
elif [ "-b" = "$1" ]; then
	for file in "${@:2}"; do
		build $file
	done
	exit 0
elif [ "-c" = "$1" ]; then
	rm $(basename -s ".cfa" -a *.cfa)
	rm $(basename -s ".cpp" -a *.cpp)
	rm *-cpp
	rm *.class
	exit 0
elif [ "-v" = "$1" -a 4 = "$#" ]; then
	TEST_LANG="$2"
	TEST_CASE="$3"
	VIEW_FILE="$4"
elif [ 2 -eq "$#" ]; then
	TEST_LANG="$1"
	TEST_CASE="$2"
else
	echo "Unknown call pattern." >&2
	exit 2
fi

# Run Test Programs:
# Used in place of unsupported language/test combinations.
unsupported() {
	echo "Run-Time: NA"
}

case "$TEST_CASE" in
raise-empty)
	CFAT="./throw-empty $ITERS_1M $STACK_HEIGHT"
	CFAR="./resume-empty $ITERS_10M $STACK_HEIGHT"
	CPP="./throw-empty-cpp $ITERS_1M $STACK_HEIGHT"
	JAVA="java ThrowEmpty $ITERS_1M $STACK_HEIGHT"
	PYTHON="./throw-empty.py $ITERS_1M $STACK_HEIGHT"
	;;
raise-detor)
	CFAT="./throw-detor $ITERS_1M $STACK_HEIGHT"
	CFAR="./resume-detor $ITERS_10M $STACK_HEIGHT"
	CPP="./throw-detor-cpp $ITERS_1M $STACK_HEIGHT"
	JAVA=unsupported
	PYTHON=unsupported
	;;
raise-finally)
	CFAT="./throw-finally $ITERS_1M $STACK_HEIGHT"
	CFAR="./resume-finally $ITERS_10M $STACK_HEIGHT"
	CPP=unsupported
	JAVA="java ThrowFinally $ITERS_1M $STACK_HEIGHT"
	PYTHON="./throw-finally.py $ITERS_1M $STACK_HEIGHT"
	;;
raise-other)
	CFAT="./throw-other $ITERS_1M $STACK_HEIGHT"
	CFAR="./resume-other $ITERS_10M $STACK_HEIGHT"
	CPP="./throw-other-cpp $ITERS_1M $STACK_HEIGHT"
	JAVA="java ThrowOther $ITERS_1M $STACK_HEIGHT"
	PYTHON="./throw-other.py $ITERS_1M $STACK_HEIGHT"
	;;
try-catch)
	CFAT="./try-catch $ITERS_1000M"
	CFAR="./try-resume $ITERS_1000M"
	CPP="./try-catch-cpp $ITERS_1000M"
	JAVA="java TryCatch $ITERS_1000M"
	PYTHON="./try-catch.py $ITERS_1000M"
	;;
try-finally)
	CFAT="./try-finally $ITERS_1000M"
	CFAR=unsupported
	CPP=unsupported
	JAVA="java TryFinally $ITERS_1000M"
	PYTHON="./try-finally.py $ITERS_1000M"
	;;
cond-match-all)
	CFAT="./cond-catch $ITERS_10M 1"
	CFAR="./cond-fixup $ITERS_100M 1"
	CPP="./cond-catch-cpp $ITERS_10M 1"
	JAVA="java CondCatch $ITERS_10M 1"
	PYTHON="./cond-catch.py $ITERS_10M 1"
	;;
cond-match-none)
	CFAT="./cond-catch $ITERS_10M 0"
	CFAR="./cond-fixup $ITERS_100M 0"
	CPP="./cond-catch-cpp $ITERS_10M 0"
	JAVA="java CondCatch $ITERS_10M 0"
	PYTHON="./cond-catch.py $ITERS_10M 0"
	;;
fixup-empty)
	CFAT="./fixup-empty-f $ITERS_10M $STACK_HEIGHT"
	CFAR="./fixup-empty-r $ITERS_10M $STACK_HEIGHT"
	CPP="./fixup-empty-cpp $ITERS_10M $STACK_HEIGHT"
	JAVA="java FixupEmpty $ITERS_10M $STACK_HEIGHT"
	PYTHON="./fixup-empty.py $ITERS_10M $STACK_HEIGHT"
	;;
fixup-other)
	CFAT="./fixup-other-f $ITERS_10M $STACK_HEIGHT"
	CFAR="./fixup-other-r $ITERS_10M $STACK_HEIGHT"
	CPP="./fixup-other-cpp $ITERS_10M $STACK_HEIGHT"
	JAVA="java FixupOther $ITERS_10M $STACK_HEIGHT"
	PYTHON="./fixup-other.py $ITERS_10M $STACK_HEIGHT"
	;;
*)
	echo "No such test: $TEST_CASE" >&2
	exit 2
	;;
esac

case "$TEST_LANG" in
cfa-t) CALL="$CFAT";;
cfa-r) CALL="$CFAR";;
cpp) CALL="$CPP";;
java) CALL="$JAVA";;
python) CALL="$PYTHON";;
*)
	echo "No such language: $TEST_LANG" >&2
	exit 2
	;;
esac

echo $CALL

if [ -n "$VIEW_FILE" ]; then
	grep -A 1 -B 0 "$CALL" "$VIEW_FILE" | sed -n -e 's!Run-Time (ns): !!;T;p'
	exit
fi

$CALL
