#!/bin/bash

checkdir=_check_builds


# TODO: rewrite in OCaml or something better than sh

shopt -s nullglob

# script de test

compilo=../../heptc
coption=

# compilateurs utilises pour les tests de gen. de code

CAMLC=ocamlc
JAVAC=javac
LUSTREC=lustre
CC="gcc -std=c99"

# par defaut : pas de test de generation de code

caml=0
java=0
lustre=0
c=0
minils=0
vhdl=0

score=0
max=0
verbose=0
clean=0

compile () {
  args_comp=""

  assert_node=$(eval grep CHECK $1 | awk '{ print $3 }')

  if [ -n "$assert_node" ]; then
    args_comp="-assert $assert_node"
  fi

  if [ $verbose != 0 ]; then
    args_comp="$args_comp -v"
  fi

  if grep "node main()" $1 >/dev/null; then
      args_comp="$args_comp -s main"
  fi

  if [ $verbose != 0 ]; then
    logfile=`basename $1`.log
    echo "Compile -i $coption $args_comp $1"
    $compilo $coption -I good $args_comp $1 >$logfile 2>&1
  else
    if [ $2 == 1 ]; then
      $compilo $coption -I good $args_comp $1 >/dev/null 2>&1
    else
      $compilo $coption -I good $args_comp $1 2>&1
    fi
  fi
  failed=$?

  return $failed
}

launch_check () {

  score=0
  max=0

  if [ $clean = 1 ]; then
    rm -r $checkdir
    exit 0
  fi

  if [ ! -d $checkdir ]; then
    mkdir $checkdir
  fi
  cd $checkdir

  # les mauvais
  echo "Tests bads"
  for f in ../bad/*.ept ; do
    if [ $verbose = 0 ]; then
      echo -n "."
    fi
    max=`expr $max + 1`;
    if compile $f 1; then
      echo
      echo "ERROR on "$f" (should fail to compile)";
    else
      score=`expr $score + 1`;
    fi
  done
  echo
  echo "Tests goods"
  for f in ../good/*.ept; do
    echec=0
    if [ $verbose = 0 ]; then
      echo -n "."
    fi
    max=`expr $max + 1`;
    base_f=`basename $f .ept`
    if compile $f 0; then
      echec=0
    else
      echec=1
    fi
    # Compil. minils ?
    if [[ ($echec == 0) && ($minils == 1) ]]; then
      if $MLC ${base_f}.mls > /dev/null 2>&1; then
        echec=0
      else
        echec=2
      fi
    fi
    # Compil. java ?
    if [[ ($echec == 0) && ($java == 1) ]]; then
      pushd "${base_f}" > /dev/null
      for java_file in *.java ; do
        if $JAVAC -warn:-unused -sourcepath .:..:../t1 ${java_file} > /dev/null
        then
          echec=0
        else
          echec=3
        fi
      done
      popd > /dev/null
    fi
    # Compil. caml ?
    if [[ ($echec == 0) && ($caml == 1) ]]; then
      if $CAMLC -c ${base_f}.ml > /dev/null; then
        echec=0
      else
        echec=4
      fi
    fi
    # Compil. c ?
    if [[ ($echec == 0) && ($c == 1) ]]; then
        pushd ${base_f}_c >/dev/null
        for cf in *.c; do
            if $CC -I ../t1_c -c $cf >/dev/null 2>&1; then
                echec=$echec
            else
                echec=5
            fi
        done

        if [ $echec != 5 ]; then
            if egrep "(node main\(\))|(CHECK)" ../${base_f}.ept >/dev/null 2>&1
            then
                if $CC *.o -o ${base_f} 2>&1; then
                    echec=0
                else
                    echec=6
                fi

                if [ $echec != 6 ]; then
                    step_count=`grep CHECK ../$base_f.ept | awk '{ print $4 }'`
                    if [ -n "$step_count" ]; then
                        if ./${base_f} $step_count >/dev/null 2>&1; then
                            echec=0
                        else
                            echec=7
                        fi
                    fi
                fi
            fi
        fi
        popd >/dev/null
    fi
    # Compil. VHDL ?
    if [[ ($echec == 0) && ($vhdl == 1) ]]; then
      pushd ${base_f}_vhdl > /dev/null
      for vhdl_file in *.vhd; do
        if $VHDLC -a ${vhdl_file} && $VHDLC -e ${vhdl_file} > /dev/null 2>&1
        then
          echec=${echec}
        else
          echec=8
        fi
      done
    fi

    if [[ $echec == 0 ]]; then
      score=`expr $score + 1`;
    else
      echo
      echo "ERROR on \"$f\" (should compile)";
      case $echec in
        1 )
          echo "Compilation failed.";;
        2 )
          echo "Compilation to Minils failed.";;
        3 )
          echo "Compilation to Java failed.";;
        4 )
          echo "Compilation to Caml failed.";;
        5 )
          echo "C compilation failed.";;
        6 )
          echo "Link failure.";;
        7 )
          echo "Run-time assertion failure.";;
      esac
    fi
  done
  echo

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

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

activate_clean () {
  clean=1
}

activate_minils () {
  minils=1
}

activate_java () {
  java=1
  coption="$coption -target java"
}

activate_caml () {
    caml=1
    coption="$coption -target caml"
}

activate_vhdl () {
    vhdl=1
    coption="$coption -target vhdl"
}

activate_c () {
  c=1
  coption="$coption -target c"
}

activate_all () {
  activate_java
  activate_c
}

activate_tomato () {
    coption="$coption -tomato"
}

activate_cse () {
    coption="$coption -cse"
}

activate_inter () {
    coption="$coption -inter"
}

activate_boolean () {
    coption="$coption -bool"
}

activate_deadcode () {
    coption="$coption -deadcode"
}

# -1, -2, -3, -v1, -v2, -v3 kept for backward compatibility
# (to be suppressed)
while [ $# -gt 0 ]; do
  case $1 in
    "-clean" )
      activate_clean
      shift;;
    "-v" )
      verbose=1;
      shift;;
    "-all" )
      activate_all
      shift;;
    "-java" )
      activate_java
      shift;;
    "-c" )
      activate_c
      shift;;
    "-caml" )
      activate_caml
      shift;;
    "-vhdl" )
      activate_vhdl
      shift;;
    "-mls" )
      activate_minils
      shift;;
    "-tomato" )
      activate_tomato
      shift;;
    "-cse" )
      activate_cse
      shift;;
    "-inter" )
      activate_inter
      shift;;
    "-bool" )
      activate_boolean
      shift;;
    "-deadcode" )
      activate_deadcode
      shift;;
    "-h" )
      echo "usage : $0 <options> <compilo>"
      echo "options : "
      echo "-clean    : clean build dir"
      echo "-java     : test of code generation (java code)"
      echo "-caml     : test of code generation (caml code)"
      echo "-lustre   : test of code generation (lustre code)"
      echo "-vhdl     : test of code generation (vhdl)"
      echo "-bool     : test of boolean translation"
      echo "-deadcode : test of deadcode removal"
      echo "-inter    : test of intermediate equations removal"
      echo "-tomato   : test of automata minimization"
      echo "-cse      : test of common sub-expression elimination"
      echo "-c        : test of code generation (c code)"
      echo "-all      : test all"
      echo "-v        : verbose"
      exit 0;;
    * )
      compilo=$1
      shift
      coption="$coption $*"
      break
  esac
done
launch_check
echo