#!/bin/bash

shopt -s nullglob

# script to test your compiler project

option=$1
compilo=$2
score=0
max=0
verbose=0


echo "Testing $2"

echo

# rm -f syntax/bad/testfile-*.go
# rm -f syntax/good/testfile-*.go
# rm -f typing/bad/testfile-*.go
# rm -f typing/good/testfile-*.go
# ocamllex split.mll
# ocaml split.ml syntax/bad/bad.split
# ocaml split.ml syntax/good/good.split
# ocaml split.ml typing/bad/bad.split
# ocaml split.ml typing/good/good.split

# all tests are consistent with Go
test_go() {
for f in typing/bad/*.go; do
    if test $f == typing/bad/testfile-main-1.go; then continue; fi
    if go tool compile $f > /dev/null 2>&1 ; then
      echo "success of go on $f"; exit 1
    fi
done
for f in typing/good/*.go; do
    go tool compile $f > /dev/null ||
     (echo "failure of go on $f"; exit 1)
done
for f in exec/*.go; do
    go run $f > /dev/null ||
     (echo "failure of go on $f"; exit 1)
done
for f in exec-fail/*.go; do
    go tool compile $f > /dev/null ||
        (echo "failure of go on $f"; exit 1)
    if go run $f > /dev/null 2>&1 ; then
      echo "success of go on $f"; exit 1
    fi
done
}

compile () {
if [[ $verbose != 0 ]]; then
  echo $compilo $1 $2
  $compilo $1 $2;
else
  $compilo $1 $2 > /dev/null 2>&1;
fi;
}


# part 1: parsing

partie1 () {

score=0
max=0

echo "Part 1"

echo -n "bad ones "
for f in syntax/bad/*.go; do
    echo -n ".";
    max=`expr $max + 1`;
    compile --parse-only $f;
    case $? in
	"0")
	echo
	echo "FAILURE on "$f" (should fail)";;
	"1") score=`expr $score + 1`;;
	*)
	echo
	echo "FAILURE on "$f" (for a bad reason)";;
    esac
done
echo

echo -n "good ones "
for f in syntax/good/*.go typing/bad/*.go typing/good/*.go exec/*.go exec-fail/*.go; do
    echo -n ".";
    max=`expr $max + 1`;
    compile --parse-only $f;
    case $? in
	"1")
	echo
	echo "FAILURE on "$f" (should succeed)";;
	"0") score=`expr $score + 1`;;
	*)
	echo
	echo "FAILURE on "$f" (for a bad reason)";;
    esac
done
echo

percent=`expr 100 \* $score / $max`;

echo -n "Part 1: $score/$max : $percent%"; }

# part 2 : static typing


partie2 () {
echo
echo "Part 2"

score=0
max=0

echo -n "bad ones "
for f in typing/bad/*.go; do
    echo -n ".";
    max=`expr $max + 1`;
    compile --type-only $f;
    case $? in
	"0")
	echo
	echo "FAILURE on "$f" (should fail)";;
	"1") score=`expr $score + 1`;;
	*)
	echo
	echo "FAILURE on "$f" (for a bad reason)";;
    esac
done
echo

echo -n "good ones "
for f in typing/good/*.go exec/*.go exec-fail/*.go; do
    echo -n ".";
    max=`expr $max + 1`;
    compile --type-only $f;
    case $? in
	"1")
	echo
	echo "FAILURE on "$f" (should succeed)";;
	"0") score=`expr $score + 1`;;
	*)
	echo
	echo "FAILURE on "$f" (for a bad reason)";;
    esac
done
echo

percent=`expr 100 \* $score / $max`;

echo    "Part 2: $score/$max : $percent%";
}


# part 3 : code generation

partie3 () {

score_comp=0
score_out=0
score_test=0
max=0

echo
echo "Part 3"
echo "Execution (must succeed)"
echo "------------------------"

timeout="why3-cpulimit 30 0 -h"

for f in exec/*.go; do
    echo -n "."
    asm=exec/`basename $f .go`.s
    rm -f $asm
    expected=exec/`basename $f .go`.out
    max=`expr $max + 1`;
    if compile $f; then
	rm -f out
	score_comp=`expr $score_comp + 1`;
	if gcc -no-pie $asm && ./a.out > out; then
	    score_out=`expr $score_out + 1`;
	    if cmp --quiet out $expected; then
		score_test=`expr $score_test + 1`;
	    else
		echo
		echo "FAILURE: bad output for $f"
	    fi
	else
		echo
		echo "FAILURE of the generated code for $f"
	fi
    else
	echo
	echo "FAILURE of the compilation on $f (should succeed)"
    fi
done
echo

echo "Execution (must fail)"
echo "---------------------"

for f in exec-fail/*.go; do
    echo -n "."
    asm=exec-fail/`basename $f .go`.s
    rm -f $asm
    max=`expr $max + 1`;
    if compile $f && gcc -no-pie $asm; then
	score_comp=`expr $score_comp + 1`;
	if ./a.out > out; then
	    echo
	    echo "FAILURE : the generated code for $f should fail"
	else
		score_test=`expr $score_test + 1`;
	        score_out=`expr $score_out + 1`;
	fi
    else
	echo
	echo "FAILURE of the compilation on $f (must succeed)"
    fi
done

echo
percent=`expr 100 \* $score / $max`;

echo "Part 3:";
percent=`expr 100 \* $score_comp / $max`;
echo "Compilation: $score_comp/$max : $percent%";
percent=`expr 100 \* $score_out / $max`;
echo "Generated code: $score_out/$max : $percent%";
percent=`expr 100 \* $score_test / $max`;
echo "Code behavior: $score_test/$max : $percent%";}


case $option in
    "-1" )
        partie1;;
    "-2" )
        partie2;;
    "-3" )
        partie3;;
    "-v1" )
	verbose=1;
	partie1;;
    "-v2" )
    	verbose=1;
        partie2;;
    "-v3" )
    	verbose=1;
        partie3;;
    "-all" )
    	partie1;
    	partie2;
    	partie3;;
    "-go" )
        test_go;;
    * )
        echo "usage : $0 <option> <compiler>"
        echo "select one option among: "
        echo "-1      : test part 1"
        echo "-2      : test part 2"
        echo "-3      : test part 3"
        echo "-v1     : test part 1 (verbosely)"
        echo "-v2     : test part 2 (verbosely)"
        echo "-v3     : test part 3 (verbosely)"
        echo "-all    : test all parts";;

esac
echo
