/*---------------------------------------------------------------------*/
/*    serrano/prgm/project/bigloo/runtime/Clib/capply.c                */
/*                                                                     */
/*    Author      :  Manuel Serrano                                    */
/*    Creation    :  Fri Mar 20 11:26:29 1992                          */
/*    Last change :  Fri Nov 14 17:33:09 2003 (serrano)                */
/*                                                                     */
/*    Le apply qui a lieu a runtime.                                   */
/*---------------------------------------------------------------------*/
#include <bigloo.h>

/*---------------------------------------------------------------------*/
/*    Les recuperations externes                                       */
/*---------------------------------------------------------------------*/
extern void c_error();
static char err_msg[ 10 ];
static obj_t arg[32];

/*---------------------------------------------------------------------*/
/*    apply ...                                                        */
/*    -------------------------------------------------------------    */
/*    Tous les tests d'arite ont ete expanses `inline'. On n'a plus    */
/*    qu'a faire l'appel.                                              */
/*---------------------------------------------------------------------*/
BGL_RUNTIME_DEF
obj_t
apply( obj_t function, obj_t args_list )
{
   long arity = PROCEDURE_ARITY(function);

   if (arity < 0)
   {
      long require;
      obj_t runner = args_list;
      long i = 0;

      require = -arity - 1;

      while (i < require)
      {
	 arg[i++] = CAR(runner);
         runner = CDR( runner );
      }
#define CALL( proc ) ((obj_t (*)())PROCEDURE_VA_ENTRY( proc ))
      switch (arity)
      {
         case -1:
            return CALL( function )(function, runner);
         
         case -2:
	    return CALL( function )(function, arg[ 0 ], runner);
         
         case -3:
	    return CALL( function )(function, arg[ 0 ], arg[ 1 ], runner);
         
		    
          case -4:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   runner);
		    
          case -5:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], runner);
		    
          case -6:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], runner);
		    
          case -7:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   runner);
		    
          case -8:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], runner);
		    
          case -9:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], runner);
		    
          case -10:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   runner);
		    
          case -11:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], runner);
		    
          case -12:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], runner);
		    
          case -13:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   runner);
		    
          case -14:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], runner);
		    
          case -15:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], runner);
		    
          case -16:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   runner);
		    
          case -17:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], runner);

          case -18:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16],runner);
	    
          case -19:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16],arg[17],runner);

          case -20:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16],arg[17],
				   arg[18],runner);

          case -21:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], runner);

          case -22:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20], runner);

          case -23:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], runner);

          case -24:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], arg[22], runner);

          case -25:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], arg[22], arg[23], runner);

          case -26:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], arg[22], arg[23],
				   arg[24], runner);

          case -27:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], arg[22], arg[23],
				   arg[24], arg[25], runner);

          case -28:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], arg[22], arg[23],
				   arg[24], arg[25], arg[26], runner);

          case -29:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], arg[22], arg[23],
				   arg[24], arg[25], arg[26],
				   arg[27], runner);

          case -30:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], arg[22], arg[23],
				   arg[24], arg[25], arg[26],
				   arg[27], arg[28], runner);

          case -31:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], arg[22], arg[23],
				   arg[24], arg[25], arg[26],
				   arg[27], arg[28], arg[29], runner);

          case -32:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], arg[22], arg[23],
				   arg[24], arg[25], arg[26],
				   arg[27], arg[28], arg[29],
				   arg[30], runner);

          case -33:
	    return CALL(function) (function, arg[0], arg[1], arg[2],
				   arg[3], arg[4], arg[5],
				   arg[6], arg[7], arg[8],
				   arg[9], arg[10], arg[11],
				   arg[12], arg[13], arg[14],
				   arg[15], arg[16], arg[17],
				   arg[18], arg[19], arg[20],
				   arg[21], arg[22], arg[23],
				   arg[24], arg[25], arg[26],
				   arg[27], arg[28], arg[29],
				   arg[30], arg[31], runner);

          default:
	     sprintf( err_msg, "%d", -arity );
	     c_error("too many arguments provided in apply (max 32)",
		     err_msg,
		     -6);
	    return BUNSPEC;
	 }
   }
   else
   {
      obj_t runner = args_list;
      long i = 0;
      
      while (i < arity)
      {
	 arg[i++] = CAR(runner);
	 runner = CDR(runner);
      }

#define APPLY( f ) ((obj_t (*)())PROCEDURE_ENTRY( f ))

      switch (i)
      {
         case 0:
	    return APPLY(function) (function);

         case 1:
	    return APPLY(function) (function, arg[0]);

         case 2:
	    return APPLY(function) (function, arg[0],
				    arg[1]);

         case 3:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2]);

         case 4:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3]);

         case 5:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4]);

         case 6:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5]);

         case 7:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6]);

         case 8:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7]);

         case 9:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8]);

         case 10:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9]);

         case 11:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10]);

         case 12:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11]);

         case 13:
	      return APPLY(function) (function, arg[0],
				      arg[1], arg[2], arg[3],
				      arg[4], arg[5], arg[6],
				      arg[7], arg[8], arg[9],
				      arg[10], arg[11], arg[12]);

         case 14:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13]);

         case 15:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14]);

         case 16:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15]);

         case 17:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16]);

         case 18:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17]);

         case 19:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18]);

         case 20:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19]);

         case 21:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20]);

         case 22:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21]);

         case 23:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21],
				    arg[22]);

         case 24:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21],
				    arg[22], arg[23]);

         case 25:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21],
				    arg[22], arg[23], arg[24]);

         case 26:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21],
				    arg[22], arg[23], arg[24],
				    arg[25]);

         case 27:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21],
				    arg[22], arg[23], arg[24],
				    arg[25], arg[26]);

         case 28:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21],
				    arg[22], arg[23], arg[24],
				    arg[25], arg[26], arg[27]);

         case 29:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21],
				    arg[22], arg[23], arg[24],
				    arg[25], arg[26], arg[27],
				    arg[28]);

         case 30:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21],
				    arg[22], arg[23], arg[24],
				    arg[25], arg[26], arg[27],
				    arg[28], arg[29]);

         case 31:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21],
				    arg[22], arg[23], arg[24],
				    arg[25], arg[26], arg[27],
				    arg[28], arg[29], arg[30]);

         case 32:
	    return APPLY(function) (function, arg[0],
				    arg[1], arg[2], arg[3],
				    arg[4], arg[5], arg[6],
				    arg[7], arg[8], arg[9],
				    arg[10], arg[11], arg[12],
				    arg[13], arg[14], arg[15],
				    arg[16], arg[17], arg[18],
				    arg[19], arg[20], arg[21],
				    arg[22], arg[23], arg[24],
				    arg[25], arg[26], arg[27],
				    arg[28], arg[29], arg[30],
				    arg[31]);

         default:
	    sprintf( err_msg, "%d", arity );
	    c_error("too many arguments provided in apply (max 32)",
		    err_msg,
		    -6);
	    return BUNSPEC;
      }
   }
}
