/*****************************************************************************/
/*                                                                           */
/* File:        "DP_MAIN.C"                                                  */
/* Date:        12-18-89                                                     */
/* Last Change: Mar-07-92                                                    */
/* Author:      R. Hammer                                                    */
/*                                                                           */
/* Feb-01-92 Just : Macro WPRINT_ON and dependend include of                 */
/*                  "DP_UTIL.INC" added.                                     */
/* Feb-09-92 Just : Call to function 'd_remcast()' after work tree genera-   */
/*                  added.                                                   */
/* Mar-07-92 Just : macro 'NEW_PROTO' --> 'LINT_ARGS'                        */
/*                                                                           */
/*****************************************************************************/


#include <stdlib.h>
#include <stdio.h>
#include "impor.t"
#include    "option.h"
#include    "error.h"
#include    "scan.h"
#include    "symtab.h"
#include    "idtab.h"
#include    "optab.h"
#include    "blktab.h"
#include    "bintab.h"
#include    "std.h"
#include    "syntax.h"
#include    "seman.h"
#include    "arrx.h"

#include    "dp_nodes.h"
#include    "dp_alloc.h"
#include    "dp_error.h"
#include    "dp_tree.h"
#include    "dp_trans.h"
#include    "dp_check.h"
#include    "dp_gen.h"
#include "expor.t"
#include    "dp_main.h"
#include "implemen.t"


/* #define TRACE_ON */
/* #define WPRINT_ON */


#if defined(TRACE_ON) || defined(WPRINT_ON)
#include "dp_util.inc"
#endif
 


/*===========================================================================*/

#ifdef LINT_ARGS
binptr dotseman (binptr p)
                                            /* Dotexpresssion semantic check */
                                            /* ---            -----          */
#else
binptr dotseman (p)
  binptr  p;    /* Head of input tree  */
#endif

/*-----------------------------------------------------------------------------
 *
 *  This is the main function for dotprecision expression handling. Its input
 *  is the binary tree of a dotprecision expression with one of the sharp
 *  symbols as root. The following steps will be performed:
 *
 *  1. A working tree is build up with information about structure and
 *     arithmetical basetype stored in each node. Building the working
 *     tree is combined with performing the semantical checks. At its
 *     end the datatype of the dp-expression is to be deviated from the
 *     entries of the root node.
 *
 *  2. If no error was detected, some transformations on the working tree
 *     are to be done:
 *
 *        - Deletion of dyadic minus signs
 *        - Pushing monadic minus signs down to the leaves
 *        - Transforming the tree to a left linear form
 *
 *  3. Now C-Code for the dotexpression may be generated in two steps:
 *
 *        - Generation of dimensional checks
 *        - Transforming the arithmetical operations of the dotprecision
 *          expression into corresponding C-Statements
 *
 *     The resulting binary tree of the C-Statements is appended to the
 *     global pointer 'binstm'.
 *
 *  4. At the end the memory used by the working tree is deallocated.
 *
 *
 *  I/O - Parameters:
 *  -----------------
 *
 *     Name     |   Type   |   I/O   |   Meaning
 *     ---------|----------|---------|---------------------------------------
 *     p        |  binptr  |    I    |   Root of the original tree
 *
 *
 *  Global Parameters:
 *  ------------------
 *
 *     Name     |   Type   |   I/O   |   Meaning
 *     ---------|----------|---------|---------------------------------------
 *     binstm   |  binptr  |   I/O   |   Pointer where the generated C-State-
 *              |          |         |   ments are appended
 *
 *  Called Routines:
 *  ________________
 *
 *     Name               |   Short description
 *     -------------------|---------------------------------------------------
 *     d_maketree         |   Building up the working tree
 *     d_del_dymin        |   Deleting dyadic minus signs
 *     d_push_mminus      |   Pushing monadic minus signs down to the leaves
 *     d_make_linear_tree |   Transforming to a left linear tree
 *     d_sumnest          |   Testing for loops depending on the same loop 
 *                        |   variable
 *     d_gstment          |   Generating/Appending a new statement
 *     d_gscheck          |   Generating scalar checks
 *     d_gvcheck          |   Generating vector checks
 *     d_gmcheck          |   Generating matrix checks
 *     d_generate         |   Generating the C-Statements for the dotprecision
 *                        |   expression
 *     d_freetree         |   Deallocating the working tree
 *
 *---------------------------------------------------------------------------*/

{ tNODE   *work;     /* Working tree */
  binptr   help,     /* Pointer to a generated statement sequences */
           resvar;   /* pointer to the result variable */

  /* func dotseman */
  /*---------------*/
#ifdef TRACE_ON
  print("Start of 'dotseman()' !"); printline();
#endif

  if ( on_verbose && os_verbose )
    printf("Compiling #-expression in line %d at column %d ...\n",
           p->pos.line, p->pos.col);


  /*------------------------------*/
  /* handling for critical errors */
  /*------------------------------*/
  work = NULL;
  if(setjmp(d_critjmp)!=0)
    {
    if(work!=NULL)d_freetree(work);

#ifdef TRACE_ON
    print("End of 'dotseman()' !"); printline();
#endif
    return(anytype);
    }
  /*------------------------------*/


#ifdef TRACE_ON
  print("Trace 'd_maketree()'"); printline();
#endif

  work = d_maketree(p,NULL);       /* Building the working tree */


#ifdef TRACE_ON
  printf("\nArbeitsbaum ausgeben (j/n) ? ");
  switch(getchar())
    {
    case 'j' : case 'J' : d_workprint(work,0); break;
    default             : break;
    } getchar();
#endif

  if(    ( work->basetype  == no_arithtype )    /* Illegal basetype or */
      || ( work->basetype  == d_anyarith   )    /* structure occured   */
      || ( work->structure == no_structype )    /*---------------------*/
       
      || ( d_sumnest(work) )  )                 /* Nested loops depending on */
                              /* the same loop variable     */
                              /*---------------------------*/

     /*------------------------------------------------------*/ 
     /* An error was detected previously, so we do not go on */
     /*------------------------------------------------------*/
     
     {
#ifdef TRACE_ON
     print("End of 'dotseman()'");
#endif
     return(anytype);
     }

  else
    {

    /* Performing some transformations */
    /*---------------------------------*/


#ifdef TRACE_ON
    print("Trace 'd_remcast()'"); printline();
#endif
    d_remcast(work);



#ifdef TRACE_ON
    print("Trace 'd_del_dymin()'"); printline();
#endif

    d_del_dymin(work);


#ifdef TRACE_ON
    print("Trace 'd_push_mminus()'"); printline();
#endif

    d_push_mminus(work);


#ifdef TRACE_ON
  printf("\nArbeitsbaum ausgeben (j/n) ? ");
  switch(getchar())
    {
    case 'j' : case 'J' : d_workprint(work,0); break;
    default             : break;
    } getchar();
#endif



#ifdef TRACE_ON
    print("Trace 'd_make_linear_tree()'"); printline();
#endif

    d_make_linear_tree(work);


#ifdef TRACE_ON
  printf("\nArbeitsbaum ausgeben (j/n) ? ");
  switch(getchar())
    {
    case 'j' : case 'J' : d_workprint(work,0); break;
    default             : break;
    } getchar();
#endif



    /* Set reference elements and generate dimension checks */
    /*------------------------------------------------------*/

    switch (work->structure)
      {
      case d_matrix:
           help = d_gmcheck(work);
           break;

      case d_vector:
           help = d_gvcheck(work);
           break;

      case d_scalar:
           help = d_gscheck(work);
           break;
      }
    d_gstment(&binstm,help);


    /* Code generation for dotexpressions */
    /*------------------------------------*/

#ifdef TRACE_ON
    print("Trace 'd_generate()'"); printline();
#endif

        d_generate(work,&help,&resvar);
        d_gstment(&binstm,help);


    /* Deallocation of the memory used by the working tree */
    /*-----------------------------------------------------*/

    help = binfather(p);
    if( p == binleft(help) )
        {
        bintdelete(&p);
        binllink(help,NIL);
        (void) binlside(help,resvar);
        }
    else
        {
        bintdelete(&p);
        binrlink(help,NIL);
        (void) binappend(help,resvar);
        }

    d_freetree(work);
#ifdef TRACE_ON
    print("End of 'dotseman()' !"); printline();
#endif
    return(binright(resvar));

    } /* else */

} /* func dotseman */
  /*---------------*/

/*===========================================================================*/
