#!/usr/bin/env bash

# This script runs the regression tests in src/regression.
# It also compiles the tests in benchmark/tests

set -e

name=`basename $0`

usage () {
	echo >&2 "usage: $name [-cross target] [-run-only target] [mlton flags ...]"
	exit 1
}

cross='no'
fail='no'
runOnly='no'
while [ "$#" -gt 0 ]; do
	case "$1" in
	-cross)
		cross='yes'
		shift
		if [ "$#" = 0 ]; then
			usage
		fi
		crossTarget="$1"
		shift
		;;
	-fail)
		fail='yes'
		shift
		;;
	-run-only)
		runOnly='yes'
		shift
		if [ "$#" = 0 ]; then
			usage
		fi
		crossTarget="$1"
		shift
		;;
	*)
		flags="$@"
		break
		;;
	esac
done

dir=`dirname $0`
src=`cd $dir/.. && pwd`
bin="$src/build/bin"
mlton="$bin/mlton"
flags="-warn-match false $flags"
if [ $cross = 'yes' ]; then
	flags="$flags -target $crossTarget -stop g"
fi
cont='callcc.sml callcc2.sml callcc3.sml'
intInf='conv.sml conv2.sml harmonic.sml int-inf.*.sml slow.sml slower.sml smith-normal-form.sml'
signal='finalize.sml signals.sml suspend.sml'
thread='thread0.sml thread1.sml thread2.sml mutex.sml prodcons.sml same-fringe.sml timeout.sml'
world='world1.sml world2.sml world3.sml world4.sml world5.sml world6.sml'
tmp=/tmp/z.regression.$$
PATH=$bin:.:$PATH

compFail () {
	echo "compilation of $f failed with $flags"
}

$mlton -verbose 1 || echo 'no mlton present'
echo "flags = $flags"

cd $src/regression

if [ "$fail" = 'yes' ]; then
	for f in `ls fail/*.sml`; do
		echo "testing $f"
		( $mlton $flags $extraFlags -stop tc $f >/dev/null 2>&1 &&
			echo "compilation of $f should have failed but did not" ) ||
			true
	done
	exit 0
fi

for f in `ls *.sml`; do
	f=`basename $f .sml`
	case "$f" in
	serialize)
		echo "skipping $f"
	;;
	*)
		echo "testing $f"
		case "$f" in
		exnHistory*)
			extraFlags="-exn-history true"
		;;
		*)
			extraFlags=""
		;;
		esac
		case "$runOnly" in
		no)
			$mlton $flags $extraFlags $f.sml
			if [ "$?" -ne '0' ] || 
				[ "$cross" = 'no' -a ! -x "$f" ]; then
				compFail $f
			fi
		;;
		yes)
			gcc -o $f -w -O1				\
				-I "$src/build/lib/include"		\
				-L "$src/build/lib/$crossTarget"	\
				-L /usr/pkg/lib				\
				$f.[0-9].[cS]				\
				-lmlton -lgmp -lgdtoa -lm
		;;
		esac
		if [ ! -r $f.nonterm -a $cross = 'no' -a -x $f ]; then
			( ./$f || echo 'Nonzero exit status.' ) >$tmp 2>&1 
			if [ -r $f.ok ] && ! diff $f.ok $tmp ; then
				echo "difference with $flags"
			fi
		fi
	;;
	esac
done
if [ "$cross" = 'yes' -o "$runOnly" = 'yes' ]; then
 	exit 0
fi
make clean >/dev/null
cd $src/benchmark/tests
for f in `ls *.sml`; do
	f=`basename $f .sml`
	tmpf=/tmp/$f.$$
	case "$f" in
	fxp)
		echo "skipping $f"
	;;
	*)
			echo "testing $f"
		echo "val _ = Main.doit 0" | cat $f.sml - > $tmpf.sml
		$mlton -output $tmpf $flags $tmpf.sml
		if [ $? -ne 0 ]; then
			compFail $f
		fi
		rm -f $tmpf $tmpf.sml
	;;
	esac
done 
make clean > /dev/null
cd $src
for f in mllex mlyacc mlprof; do
    tmpf=/tmp/$f.$$
    cd $src/$f
    case "$f" in
    foobar)
	    echo "skipping $f"
    ;;
    *)
	    echo "testing $f"
	    gmake -W $f >/dev/null
	    $mlton $flags -output $tmpf $f.cm
	    if [ $? -ne 0 ]; then
			compFail $f
	    fi
	    rm -f $tmpf
    ;;
    esac
done

rm -f $tmp
