/***   prelude.c   ***/

#define bool char

#include "al/constant.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/*-----------------------------------------------------------------------*/
/* prototypes */
void init_AV(void);
int  askn(int);
void pos(int,int);
void DYAD(int,int,int,int,int);
void Fill(int,int[][3],int,int);
void STFN(int,int,int);
void P(int);
/*-----------------------------------------------------------------------*/

FILE *outfile;

#define in	2
#define rl	3
#define	bl	4
#define rw	5
#define ch	6
#define bt	7
#define st	9
#define cp	10
#define fl	12
#define ri	20
#define rr	21
#define rs	22
#define rc	23

int T0[][3] = {{   VOID,    0,     0},	/* 1				*/
#ifdef __TURBOC__
               {    INT,    0,    31},  /* 2  in  int_mode   bitswidth  */
#else
	       {    INT,   31,     0},	/* 2  in  int_mode   bitswidth	*/
#endif
	       {   REAL,    0,     0},	/* 3  rl real_mode   pi		*/
	       {   BOOL,    1,     0},	/* 4  bl bool_mode		*/
	       {    ROW,    0,     0},	/* 5  rw  row_mode		*/
	       {   CHAR,   32,     0},	/* 6  ch char_mode   blank	*/
#ifdef __TURBOC__
               {   BITS,   -1,    -1},  /* 7  bt bits_mode              */
#else
               {   BITS,   -1,     0},  /* 7  bt bits_mode              */
#endif
               {   VOID,    0,     0},  /* 8                            */
	       {    ROW,   14,     0},	/* 9  st string_mode		*/
	       { STRUCT,   16,     2},	/*10  cp cmpl_mode		*/
	       {    ROW,   18,     1},	/*11	 row_of_bool_mode	*/
	       {   BOOK,    0,     0},	/*12  fl 	     stand_in	*/
	       {   BOOK,    0,     0},	/*13		     stand_out	*/
	       {      1,   ch,     0},	/*14  string			*/
	       {      1,    0,     1},	/*15				*/
	       {      0,   rl,re_tag},	/*16  complex			*/
	       {      0,   rl,im_tag},	/*17				*/
	       {      1,   bl,     0},  /*18  row of bool		*/
	       {      1,    0,     1},  /*19				*/
	       {    REF,   in,     1},	/*20  ri			*/
	       {    REF,   rl,     1},	/*21  rr			*/
	       {    REF,   st,     1},	/*22  rs			*/
	       {    REF,   cp,     1}	/*23  rc			*/
};

int N0[][2] = {{pi_tag,rl},{stand_in,fl},{stand_out,fl+1},{bitswidth,in},
	       {blank_tag,ch}};

int T1[][3] = {{rr,in,rr},{rr,rl,rr},{rc,in,rc},{rc,rl,rc},
	       {rc,cp,rc},{ri,in,ri},{rs,ch,rs},{rs,st,rs}};

int T2[][3] = {{in,in,bl},{in,rl,bl},{rl,in,bl},{rl,rl,bl},
	       {ch,ch,bl},{ch,st,bl},{st,ch,bl},{st,st,bl},
	       {bt,bt,bl},{bl,bl,bl},{in,cp,bl},{cp,in,bl},
	       {rl,cp,bl},{cp,rl,bl},{cp,cp,bl}};

int T3[][3] = {{rl,in,rl},{cp,in,cp},{in,rl,rl},{rl,rl,rl},
	       {in,cp,cp},{rl,cp,cp},{cp,rl,cp},{cp,cp,cp},
	       {in,in,in},
	       {ch,ch,st},{ch,st,st},{st,ch,st},{st,st,st}};

int T4[][3] = {{in,in,cp},{in,rl,cp},{rl,in,cp},{rl,rl,cp}};

int Z;
int A[5000],B[5000],C[5000]; int FS;
int VIND[1000], LIND[1000]; int J, last_el, last_op;

void init_AV()
{int i;
	for(i=0;i<23;i++){
	    A[i+1]=T0[i][0]; B[i+1]=T0[i][1]; C[i+1]=T0[i][2];
	}; FS=24;
	for(i=0;i<5;i++){LIND[i+1]=N0[i][0]; VIND[i+1]=N0[i][1];};
	J=5; last_el=56; last_op=0;
};

int askn(n) int n;
{int i; i=FS; FS +=n; return(i);};

void pos(op,v) int op,v;
{	if(op!=last_op){last_op=op; last_el++;};
	++J; LIND[J]=last_el; VIND[J]=v;
};

void DYAD(op,m1,m2,mr,prio) int op,m1,m2,mr,prio;
{	Z=askn(3); A[Z]=OP; B[Z]=Z+1; C[Z]= prio;
	A[Z+1]=0; B[Z+1]=mr; C[Z+1]=op;
	A[Z+2]=m2; B[Z+2]=m1; C[Z+2]=0;
	pos(op,Z);
};

#define MONAD(op,m1,mr)	DYAD(op,m1,0,mr,10)

void Fill(n,T,op,prio) int n,op,prio; int T[][3];
{int i;
	for(i=0;i<n;i++)DYAD(op,T[i][0], T[i][1], T[i][2], prio);
};

void STFN(fn,m1,mr) int fn,m1,mr;
{ Z=askn(m1?3:2); A[Z]=PROC; B[Z]=Z+1; C[Z]=m1?1:0; A[Z+1]=0; B[Z+1]=mr;
  C[Z+1]=fn; if(m1)B[Z+2]=m1; pos(fn,Z);
};

#define ST(fn)	STFN(fn,rl,rl)
#define SF(fn)	STFN(fn,fl,void_mode)

int count=12;
void P(i) int i;
{	if((++count)>11){count=0;printf("\n");};
	printf("%6d",i); putc(i>>8,outfile); putc(i&0377,outfile);
};

#define nl  count=12

int main(argc,argv) int argc; char *argv[];
{int i;
	if(argc<2){fprintf(stderr,"args: %%prelude\n"); exit(1);};
	init_AV();

	DYAD(plusto_ST,ch,rs,rs,1); DYAD(plusto_ST,st,rs,rs,1);

	Fill(8,T1,plusab_ST,1);
	Fill(6,T1, minab_ST,1);
	Fill(6,T1,timeab_ST,1);
	DYAD(overab_ST,ri,in,ri,1); DYAD(modab_ST,ri,in,ri,1);
	Fill(5,T1, divab_ST,1);

	DYAD( or_ST,bl,bl,bl,2); DYAD( or_ST,bt,bt,bt,2);
	DYAD(and_ST,bl,bl,bl,3); DYAD(and_ST,bt,bt,bt,3);

	Fill(15,T2,  eq_ST,4); Fill(15,T2,     ne_ST,4);
	Fill( 8,T2,less_ST,5); Fill( 8,T2,greater_ST,5);
	Fill( 9,T2,  le_ST,5); Fill( 9,T2,     ge_ST,5);

	Fill(13,T3, plus_ST,6);
	    MONAD( plus_ST,in,in); MONAD(plus_ST,rl,rl); MONAD(plus_ST,cp,cp);
	Fill( 9,T3,  min_ST,6);
	    MONAD(  min_ST,in,in); MONAD( min_ST,rl,rl); MONAD( min_ST,cp,cp);
	Fill( 9,T3,times_ST,7);
	    DYAD(times_ST,in,ch,st,7); DYAD(times_ST,in,st,st,7);
	    DYAD(times_ST,ch,in,st,7); DYAD(times_ST,st,in,st,7);
	Fill( 8,T3,  div_ST,7);
	    DYAD(  div_ST,in,in,rl,7);
	DYAD(over_ST,in,in,in,7);
	DYAD( mod_ST,in,in,in,7);
	DYAD(elem_ST,in,bt,bl,7);

	Fill(4,T4,  plit_ST,9);

	Fill(2,T3,    up_ST,8);
	    DYAD(   up_ST,in,in,in,8); DYAD(up_ST,bt,in,bt,8);
	DYAD(down_ST,bt,in,bt,8);
	DYAD( lwb_ST,in,rw,in,8); MONAD(lwb_ST,rw,in);
	DYAD( upb_ST,in,rw,in,8); MONAD(upb_ST,rw,in);

/*----------------------------------------------------------------------*/

	MONAD(   not_ST,bl,bl); MONAD(  not_ST,bt,bt);
	MONAD(   abs_ST,bl,in); MONAD(  abs_ST,bt,in); MONAD( abs_ST,in,in);
	MONAD(   abs_ST,rl,rl); MONAD(  abs_ST,cp,rl); MONAD( abs_ST,ch,in);
	MONAD(   odd_ST,in,bl);
	MONAD(  sign_ST,in,in); MONAD( sign_ST,rl,in);
	MONAD(entier_ST,rl,in); MONAD(round_ST,rl,in);
	MONAD(    re_ST,cp,rl); MONAD(   im_ST,cp,rl);
	MONAD(  conj_ST,cp,cp); MONAD(  arg_ST,cp,rl);
	MONAD(  repr_ST,in,ch);
	MONAD(   bin_ST,in,bt);

/*----------------------------------------------------------------------*/

	ST(   sqrt_ST); ST(   exp_ST); ST(    log_ST);
	ST(    cos_ST); ST(arccos_ST); ST(    sin_ST);
	ST( arcsin_ST); ST(   tan_ST); ST( arctan_ST);

	SF(  print_ST); SF(  read_ST); SF(  write_ST);
	SF(newline_ST); SF( space_ST); SF(newpage_ST);

	STFN(random_ST,0,rl);
	STFN(bitspack_ST,row_of_bool_mode,bt);

/*----------------------------------------------------------------------*/

	outfile = fopen(argv[1],"wb");
	if(outfile==NULL){
	    fprintf(stderr,"cannot open %s\n",argv[1]); exit(1);
	};

	P(J); P(FS); nl;
	for(i=1;i<=J;i++){P(LIND[i]); P(VIND[i]);}; nl;
	for(i=1;i<FS;i++){P(A[i]);P(B[i]);P(C[i]);};
	printf("\n\n***** END *****\n");
	fclose(outfile);
	return 0;
};



