#!/bin/sh

# This is the main shell script to compile a Curry program into
# the various intermediate representations.
# see usage messages below for possible parameters

# the values of the following environment variables are required:
# PAKCSHOME

# define PAKCSRC
PAKCSRC=$HOME/.pakcsrc
if [ ! -f $PAKCSRC ] ; then
  PAKCSRC=$PAKCSHOME/pakcsrc
fi

# executable of the MCC parser:
MCCPARSER=$PAKCSHOME/mccparser/bin/cymake
if [ ! -f $MCCPARSER ] ; then # is the MCC parser installed?
  echo "ERROR: Incomplete PAKCS installation: $MCCPARSER missing!" >&2
  exit 1
fi

# Prepare flags for MCC parser:
MCCFLAGS=
# check flag "pakcsextensions" in pakcsrc:
for i in `sed -n '/^pakcsextensions=/p' < $PAKCSRC`
do 
  if [ xx`expr $i : '.*=\(.*\)'` = xxyes ] ; then
    MCCFLAGS="--extended"
  fi
done
# check flag "warnoverlapping" in pakcsrc:
for i in `sed -n '/^warnoverlapping=/p' < $PAKCSRC`
do 
  if [ xx`expr $i : '.*=\(.*\)'` = xxno ] ; then
    MCCFLAGS="$MCCFLAGS --no-overlap-warn"
  fi
done

TARGET=           # no default case: target language must be specified!
FORMATGENERAL=fcy # target format of imported modules
FORMATMAIN=fcy    # target format of main module
NOWARNS=
if [ -z "$PAKCSLIBPATH" ] ; then
  PAKCSLIBPATH="$PAKCSHOME/lib:$PAKCSHOME/lib/meta"
fi

case $1 in
  -fl   ) TARGET=fl   ; FORMATGENERAL=fl ; FORMATMAIN=fl ; shift ;;
  -fcy  ) TARGET=fcy  ; shift ;;
  -acy  ) TARGET=acy  ; FORMATMAIN=acy ; shift ;;
  -uacy ) TARGET=uacy ; FORMATMAIN=uacy ; shift ;;
  -html ) TARGET=html ; FORMATMAIN=html ; shift ;;
  -def  ) TARGET=def  ; FORMATGENERAL=fl ; FORMATMAIN=fl ; shift ;;
  -fint ) echo "ERROR: Target '-fint' no longer supported!" >&2 ; exit 1 ;;
  -ast  ) echo "ERROR: Target '-ast' no longer supported!" >&2 ; exit 1 ;;
  -cint ) echo "ERROR: Target '-cint' no longer supported!" >&2 ; exit 1 ;;
esac

if [ -z "$TARGET" ] ; then
  echo "ERROR: Target of the parser not specified!" >&2
  # remove all remaining args:
  set x x x x x x
  shift ; shift ; shift ; shift ; shift ; shift
fi

QUIET=
CONVERSION=no
NOWARNS=warns
FULLPATH=
TRANS=
OUTFILE=

while [ $# -gt 1 ] ; do
  case $1 in
    -q | -quiet ) QUIET=quiet ;;
    -o          ) shift ; OUTFILE=$1 ;;
    -nowarns    ) NOWARNS=nowarns ;;
    -path       ) shift ; CURRYPATH=$1 ; export CURRYPATH ;;
    -fullpath   ) shift ; FULLPATH=$1 ;;
    -fpopt | -compact | -compactexport | -compactmain:* ) FCYPP="$FCYPP $1 " ;;
    -fcypp      ) shift ; FCYPP="$FCYPP $1 " ;;
    *           ) echo ERROR: Illegal option: "$@" >&2 ; exit 1 ;;
  esac
  shift
done

if [ $# != 1 ] ; then
  echo >&2
  echo "Usage: parsecurry <Target type> [<Options>] <progname>" >&2
  echo >&2
  echo "Parse Curry program stored in <progname>.(l)curry" >&2
  echo "<Target type> is an element of:"  >&2
  echo "-fcy   : generate FlatCurry program in <progname>.fcy" >&2
  echo "-acy   : generate AbstractCurry program in <progname>.acy" >&2
  echo "-uacy  : generate untyped AbstractCurry program in <progname>.uacy" >&2
  echo "-html  : generate HTML representation of source program" >&2
  echo "-fl    : generate internal TasteCurry syntax in <progname>.fl" >&2
  echo "-def   : generate intermediate program for Curry2Java in <progname>.def" >&2
  echo >&2
  echo "<Options> is a sequence of:"  >&2
  echo "-q|-quiet       : work silently" >&2
  #echo "-nowarns        : suppress warnings of the parser" >&2
  echo "-o <file>       : write output into <file> (for target type -html)" >&2
  echo "-path <p>       : specify additional search path <p> for loading modules" >&2
  echo " (default search path = .:$PAKCSLIBPATH)" >&2
  echo "-fullpath <p>  : specify complete search path <p> for loading modules" >&2
  echo >&2
  echo "-fpopt         : apply function pattern optimization after parsing" >&2
  echo "-compact       : apply code compactification after parsing" >&2
  echo "-compactexport : apply code compactification w.r.t. exports after parsing" >&2
  echo "-compactmain:f : apply code compactification w.r.t. main function 'f' after parsing" >&2
  echo "-fcypp <c>     : apply command <c> to <progname> after parsing" >&2
  exit 1
fi
PROG=$1
PROGDIR=`dirname $PROG`
MODNAME=`basename $PROG`

# set up SEARCHPATH parameter for searching source files:
if [ -n "$FULLPATH" ] ; then
  SEARCHPATH=$FULLPATH
elif [ -z "$CURRYPATH" ] ; then
  SEARCHPATH="$PROGDIR:$PAKCSLIBPATH"
else
  SEARCHPATH="$PROGDIR:$CURRYPATH:$PAKCSLIBPATH"
fi

# compute actual directory of Curry program w.r.t. to SEARCHPATH
MAINDIR=
for d in `echo $SEARCHPATH | sed -e "s/:/ /g"`
do
  if [ -f "$d/$MODNAME.lcurry" ] ; then
    MAINDIR=$d
    SOURCESUFFIX=.lcurry
    break
  fi
  if [ -f "$d/$MODNAME.curry" ] ; then
    MAINDIR=$d
    SOURCESUFFIX=.curry
    break
  fi
done

if [ -z "$MAINDIR" ] ; then
   echo "ERROR: Program file '$PROG.curry' not found in path '$SEARCHPATH'!" >&2
   exit 1
fi

if [ -z "$OUTFILE" ] ; then
  OUTFILE=$MAINDIR/${MODNAME}_curry.html
fi

# delete old target file to avoid later problems...
if [ $FORMATGENERAL = "fl" ] ; then
  rm -f $PROG.fl
fi
case $TARGET in
  ast  ) rm -f $PROG.ast ;;
  cint ) rm -f $PROG.cint ;;
  acy  ) rm -f $PROG.acy ;;
  uacy ) rm -f $PROG.uacy ;;
  html ) rm -f $OUTFILE ;;
esac

MCCSUFFIX=
MCCTARGET=
if [ $MCCPARSER ] ; then # should the MCC parser be used?
  case $TARGET in
    fcy  ) MCCTARGET=--flat ;;
    acy  ) MCCTARGET=--acy ;;
    uacy ) MCCTARGET=--uacy ;;
    html ) MCCTARGET=--html ; MCCFLAGS="$MCCFLAGS -o $OUTFILE" ;
                              MCCSUFFIX=$SOURCESUFFIX ;;
  esac
fi

if [ -z "$QUIET" ] ; then
  echo "Parsing '$MODNAME$SOURCESUFFIX'..." >&2
fi

if [ $FORMATGENERAL = "fl" ] ; then
  # try to use the curry2fl translator:
  $PAKCSHOME/bin/curry2fl $PROG
elif [ -n "$MCCTARGET" ] ; then
  # Use mcc front end:
  if [ -n "$FULLPATH" ] ; then
    PAKCSLIBPATH=$FULLPATH ; export PAKCSLIBPATH
    # if the complete load path is provided, supply directory info for main mod:
    $MCCPARSER $MCCFLAGS $MCCTARGET $MAINDIR/$MODNAME$MCCSUFFIX
    EXITCODE=$?
  else
    $MCCPARSER $MCCFLAGS $MCCTARGET $PROG$MCCSUFFIX
    EXITCODE=$?
  fi
  if [ $EXITCODE -gt 0 ] ; then
    rm -f $PROG.$TARGET # just to be sure that there is no buggy file
    exit $EXITCODE
  fi
fi

# apply optional transformations on FlatCurry representation:
if [ $TARGET = fcy ] ; then
  # find options in Curry source file:
  OPTIONLINE=`grep '^{-#.*PAKCS_OPTION_FCYPP' $MAINDIR/$MODNAME$SOURCESUFFIX | head -1`
  OPTIONS=`expr "$OPTIONLINE" : '{-#.*PAKCS_OPTION_FCYPP*\(.*\)#-}.*'`
  # add source file options to current preprocessing options:
  if [ -n "$OPTIONS" ] ; then
    FCYPP="$FCYPP $OPTIONS"
  fi

  if [ -z "$QUIET" -a -n "$FCYPP" ] ; then
    echo "Executing FlatCurry preprocessing options: $FCYPP"
  fi
  for T in $FCYPP ; do
    case $T in
      -fpopt         ) TCMD=$PAKCSHOME/tools/optimize/NonStrictOpt.state ;;
      -compact       ) TCMD=$PAKCSHOME/tools/optimize/CompactFlat.state ;;
      -compactexport ) TCMD="$PAKCSHOME/tools/optimize/CompactFlat.state -export" ;;
      -compactmain:* ) TCMD="$PAKCSHOME/tools/optimize/CompactFlat.state -main `expr $T : '-compactmain:\(.*\)'`" ;;
      *              ) TCMD=$T ;;
    esac
    $TCMD $PROG
    EXITCODE=$?
    if [ $EXITCODE -gt 0 ] ; then
      rm -f $PROG.$TARGET # just to be sure that there is no buggy file
      exit $EXITCODE
    fi
  done
fi

# compile into intermediate representation for Curry2Java:
if [ $TARGET = def ] ; then
  if [ ! -f $PROG.fl -o ! -f $PAKCSHOME/bin/tastecurry ] ; then
    exit 1
  fi
  if [ -f $PROG.def ] ; then
     if [ `ls -t $PROG.fl $PROG.def | head -1` = $PROG.def ] ; then
       if [ -z "$QUIET" ] ; then
         echo "Intermediate representation '$PROG.def' is up-to-date." >&2
       fi
       exit 0
     else
       #rm $PROG.def
       rm -rf $PROG.def $PROG.pizza $PROG.classes
     fi
  fi
  if [ -z "$QUIET" ]
  then
   echo "Compiling '$1.fl' into intermediate representation '$PROG.def'..." >&2
  fi
  echo "opt. read '$1'. trees('$1.def')." | \
         $PAKCSHOME/bin/tastecurry > /tmp/ERROR$$ 2>&1
  if [ `fgrep \* /tmp/ERROR$$ | wc -l` -gt 0 ]
  then
    # an error has occurred been detected by the TasteCurry interpreter:
    cat /tmp/ERROR$$
    rm /tmp/ERROR$$
    exit 1
  fi
  rm /tmp/ERROR$$
fi

