Added upstream from http://ftp.icm.edu.pl/pub/loglan/
[loglan.git] / sources / gen / lists.c
1 /*     Loglan82 Compiler&Interpreter
2      Copyright (C) 1993 Institute of Informatics, University of Warsaw
3      Copyright (C)  1993, 1994 LITA, Pau
4      
5      This program is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published by
7      the Free Software Foundation; either version 2 of the License, or
8      (at your option) any later version.
9      
10      This program is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13      GNU General Public License for more details.
14      
15 =======================================================================
16 */
17
18 #include <assert.h>
19 #include "glodefs.h"
20
21 #ifndef NO_PROTOTYPES
22
23 static void makereflist (protaddr);
24 static void makeprefseq (protaddr);
25 static void makeparlist (protaddr);
26 static void makevirtlist(protaddr);
27 static void makeit  (int,protaddr);
28
29 #else
30
31 static void makereflist();
32 static void makeprefseq();
33 static void makeparlist();
34 static void makevirtlist();
35 static void makeit();
36
37 #endif
38
39 logitem itemkind (i)
40               /* strongly implementation dependent, */
41               /*  given the address in symbol table */
42               /*  returns the kind of loglan item   */
43               /*  ctp */
44
45 int i ;
46
47    int         n ;
48    csti    trick ;
49
50        n = ipmem [ i ] ;
51
52 /*       WITH TRICK DO */
53        {
54          trick.t=iand(n,15);                   /* 000f */
55          /* bits 12..15 in 16-bits word */
56        
57          trick.zp=ishft(iand(n,15*16),-4);        /* 00f0 */
58          /* bits  8..11 in 16-bits word */
59        
60          trick.s=ishft(iand(n,7*256),-8); /* 0700 */
61
62          /* bits  5.. 7 in 16-bits word */
63
64          switch(trick.t)
65          {
66      case 2 : return(IRECORD) ;
67
68      case 3 : return(ICLASS) ;
69
70      case 5 : return(IPROCESS) ;
71
72      case 6 : return(IFMTYPE) ;
73
74      case 7 : return(ICOROUT) ;
75
76      default :
77      /*  4,8,9,10,11,12,13,14,15 */ break;
78
79      case 1 : switch(trick.zp)
80                    {
81            case 2  : return(IFMFUNC) ;
82
83              case 3  : return(IFMPROC);
84
85            case 5  : return(IPARIN);
86
87            case 6  : return(IPAROUT);
88
89            case 7  : return(IVAR);
90
91            case 8  : return(ICONST);
92
93            case 9  : return(IPARINOUT);
94
95            case 11 : return(ISIGNAL);
96
97
98
99            case 0 : switch(trick.s)
100                               {
101             case 0 : return(IBLOCK);
102
103             case 1 : return(IPREFBLOCK);
104
105             case 2 : return(IFUNC);
106
107             case 4 : return(IPROC);
108
109             case 7 : return(IHANDLER);
110
111
112             default /* 3,5,6*/ : break ;
113                } /* switch trick.s */
114                           default :
115            /* 1,4,10,12,13,14,15 */ break ;
116
117          } /* switch trick.zp */
118     } /* switch trick.t */;
119        } /* WITH */
120
121 } /* itemkind */
122
123
124
125 void reserve(n) address n;{ /* TEST IF THERE IS AT LEAST N EMPTY CELLS IN 'M' */
126   if((fre + n) > MEMLIMIT)  generror(TLDESCR); 
127 }
128
129
130
131 static void makereflist(prot) protaddr prot;{
132 /* PREPARES THE TABLE WITH OFFSETS OF REFERENCE VARIABLES */
133 /* FOR THE PROTOTYPE PROT                                 */
134
135   pointer       elem ;
136   int           n ;
137   bool          anytodo ;
138   dprotaddr     pref ;
139   pointprdsc    curr ;  /* cmb */
140
141   curr = prototype[ prot ] ;
142   if (curr->lthreflist > 0){
143     anytodo = TRUE ;
144     pref = prefix[ prot ] ;
145
146     if (pref != DUMMY)  /* prefixed unit */
147       if(( prototype[ pref ]->span != 0 )
148           && ( prototype[ pref ]->lthreflist == curr->lthreflist )){
149
150          /* prefix already processed and the same reference attributes */
151
152          anytodo = FALSE ;
153          curr->reflist = prototype[ pref ]->reflist ;
154       }
155
156     if(anytodo){
157       reserve(curr->lthreflist) ;
158       elem = listofref[ prot ] ;
159
160       /* COPY THESE OFFSETS */
161       for (n = curr->lthreflist-1; n>=0; n--)
162       {
163         m [ fre+n ] = ipmem[ (elem->ip) - 2 ] ; /* offset */
164 LOG(fre + n);     
165         elem = elem->prevelem ;
166       } /* COPYING */
167
168       curr->reflist = fre + base ;
169       fre += curr->lthreflist ;
170
171     } /* NOT DONE YET */
172   } /* IF NON EMPTY REFLIST  */
173 }
174
175    
176    
177 static void makeprefseq(prot) protaddr prot;{
178   int        n ;
179   dprotaddr  pa  ;
180   pointprdsc curr ;
181
182 /*         WITH PROTOTYPE[ PROT ]^ DO */
183
184   curr = prototype[ prot ] ;
185   reserve(curr->lthpreflist) ;
186   pa = prot ;
187     
188   for (n = (curr->lthpreflist) - 1; n >= 0 ; n--)
189   {
190     m[ fre + n ] = pa ;
191 LOG(fre + n);     
192     pa = prefix[ pa ] ;
193   }
194        
195   curr->preflist = fre + base ;
196   fre += curr->lthpreflist ;
197    
198 }
199
200
201
202 static void makeparlist(prot) protaddr prot;{
203 /* PREPARES TABLES WITH PARAMETERS OFFSETS AND DESCRIPTION ADDRESSES
204    FOR PROTOTYPE PROT */
205
206   longpointer  elem ;
207   int          ip , /* address in ipmem */
208                n ;
209   dprotaddr    pref;
210   bool         anytodo ;
211   pointprdsc   curr ;
212
213 /*         WITH PROTOTYPE[ PROT ] ^ DO */
214 {  curr = prototype[ prot ] ;
215   if (curr->lthparlist > 0)
216   {
217     /* TABLE WITH PARAMETERS OFFSETS */
218     reserve(curr->lthparlist) ;
219     curr->parlist = fre + base ;
220
221     if (curr->kind == HANDLER)
222     {
223       /* NO PARAMETER LIST IN IPMEM, USE ATTRIBUTE LIST*/
224       ip = ipmem[(curr->codeaddr) + 6 ] ;
225                                           /* FIRST ELEM. OF ATTRIBUTE LIST */
226       for (n = 0; (n <=(curr->lthparlist-1 )); n++)
227       {
228    m[ fre + n ] = ipmem[(ipmem[ ip ])-2 ] ; /* offset */
229 LOG(fre + n);     
230
231
232          ip = ipmem[ ip+1 ]; /* next */
233        } /* FOR */;
234
235        fre += curr->lthparlist;
236      } /* IF HANDLER */
237
238      else /* not handler */
239      {
240        anytodo = TRUE;
241        pref = prefix[ prot ];
242
243        if (pref != DUMMY)
244        if (( prototype[ pref ]->span != 0 ) /* prefix already processed */
245         && ( prototype[ pref ]->lthparlist == curr->lthparlist ))
246                   /* the same parameters */
247         {
248           curr->parlist=prototype[ pref ]->parlist;
249           anytodo=FALSE;
250         } 
251
252     if (anytodo)
253          {
254            /* COPY THESE OFFSETS USING PARAMETERS LIST FROM IPMEM */
255       ip=ipmem[ curr->codeaddr+3 ]; /* first parameter indirect address */
256
257            for (n=0;n <= (curr->lthparlist) - 1; n++)
258              m [ fre + n ] = ipmem[ ipmem[ ip+n ] - 2 ]; /* offset */
259 LOG(fre + n - 1);     
260
261            fre += curr->lthparlist;
262           } /* mb if anytodo (?) */
263
264                /* FOR PROCEDURE OR FUNCTION PREPARE TABLE WITH PARAMETERS
265                                                      DESCRIPTIONS ADDRESSES */
266           if( (curr->kind == LFUNCTION) || (curr->kind == LPROCEDURE)
267               || (curr->kind == PROCESS) )
268           {
269             reserve(curr->lthparlist);
270             curr->pfdescr=fre+base;
271             elem = listofpar[ prot ];
272
273             for (n=curr->lthparlist-1; n >= 0; n--)
274             {
275               m [ fre + n ] = elem->ip; /* description's address */
276 LOG(fre + n);     
277               elem=elem->prevelem;
278             } /* for */
279
280              fre += curr->lthparlist;
281           } /* FUNCTION,PROCEDURE,PROCESS */
282         } /* NOT HANDLER */
283       }  /* mb if lthparlist>0 ?? */
284     } /* WITH */
285
286   } /* makeparlist */
287
288 static void makeit(ipr,prot)
289  int       ipr ;
290  protaddr  prot ;
291   /* mb  added passing ipr,prot as parameters rather than globals  */
292    /* for the ipmem prototype 'ipr' creates the table with virtuals
293       prototypes numbers and assignes its address to virtlist of
294       'prot' . */
295 {
296   int    k,l,f ;
297
298   l=ipmem[ ipr+25 ]; /* length */
299   f=ipmem[ ipr+24 ]; /* first element address */
300   reserve(l);
301   prototype[ prot ]->virtlist=fre + base;
302   for (k=0; k<=l-1; k++)
303     m[ fre+k ]=ipmem[ (ipmem[ f+k ])-1  ]; /* virtual's prototype */
304 LOG(fre + k);     
305    fre+=l;
306    } /* makeit */
307
308 static void makevirtlist(prot) protaddr prot;{
309  /* MAKES A TABLE WITH PROTOTYPES NUMBERS FOR VIRTUAL */
310  /* PROCEDURES OR FUNCTIONS (IF NOT MADE YET).        */
311  /* PROPAGATES ITS ADDRESS THRU THE PREFIX SEQUENCE.  */
312
313  int  ipr ;
314  address     n ;
315  pointprdsc curr;
316  
317   {
318    curr = (prototype[prot]);
319    ipr = (int)(curr->codeaddr); /* address in ipmem */
320    if( ((curr->kind  == CLASS) || (curr->kind == LRECORD) ||
321           (curr->kind ==COROUTINE) || (curr->kind ==PROCESS) ||
322        (curr->kind == PREFBLOCK) || (curr->kind ==LFUNCTION) ||
323        (curr->kind ==LPROCEDURE))    /* VIRTUALS ALLOWED */
324       && (curr->virtlist == 0) /* not processed yet */
325       && (ipmem[ ipr + 25 ] != 0))
326    { /* not empty virtuals list */
327    while (ipmem[ ipr + 25 ] < 0)
328        /* LIST INHERITED FROM PREFIX, GO THERE */
329         ipr=ipmem[ ipr + 21 ];
330    /* THE OWN LIST OF IPR */
331    n = prototype[ ipmem[ ipr - 1 ] ]->virtlist ;
332    if (!n)  /* TABLE NOT MADE YET */
333       makeit(ipr, prot) ;
334    else
335     { curr->virtlist = n ;}
336    /* PROPAGATE IT UP THE PREFIX SEQUENCE TILL THE OWNER OF THE LIST */
337    ipr=(int)(curr->codeaddr); /* ipmem address for prot */
338    while (ipmem[ ipr+25 ] < 0)
339      {
340       ipr = (int)(ipmem[ ipr+21 ]); /* prefix */
341       prototype[ ipmem[ ipr-1 ] ]->virtlist = curr->virtlist;
342      }
343    } /* VIRTUALS ALLOWED AND EXIST, UNIT NOT PROCESSED */
344    } /* WITH */
345  } /* MAKEVIRTLIST */
346
347 void lists(){
348
349   /* PREPARATION OF : REFLIST, PARLIST, PARDESCRLIST, PREFLIST */
350   /* UNITS ARE PROCESSED IN A REVERSED ORDER                   */
351
352   protaddr    pr ;
353   dprotaddr   prfx ;
354   pointprdsc  pref ;
355   address     n ;
356   pointprdsc  curr ; /* gsg auxiliary for the Pascal WITH */
357
358   for(pr = lastprot; pr >=  MAINBLOCK; pr--){
359    curr = prototype[pr] ;
360    if(curr->span == 0){              /* ALREADY PROCESSED ? */
361                                      /* NOT PROCESSED YET   */
362      makeparlist(pr) ;
363      if(curr->kind == LFUNCTION){    /* SUPPLEMENT FUNCTION TYPE */
364        n = m[ curr->pfdescr - base + curr->lthparlist - 1 ] - base; /* result */
365        curr->nrarray = m[ n+1 ] ;
366        curr->finaltype = m[ n+2 ] ;
367      } /* SUPPLEMENT OF FUNCTION TYPE */
368
369      makereflist(pr) ;
370      makeprefseq(pr) ;
371      curr->span = 1 ; /* ==> processed */
372
373      /* GO UP THE PREFIX SEQUENCE */
374      prfx = prefix[ pr ] ;
375
376      while (prfx != DUMMY)
377      {  pref = prototype[ prfx ] ;
378  
379         if (pref->span != 0)
380           prfx = DUMMY ; /* FORCE EXIT */
381         else
382         { /* prefix not processed yet */
383           pref->span = 1 ; /* ==> processed */
384           pref->reflist = curr->reflist ;
385           pref->parlist = curr->parlist ;
386           pref->preflist = curr->preflist ;
387 /*CBC added copying of PFDESCR (formal parameter description list) */
388           pref->pfdescr = curr->pfdescr ;
389           prfx = prefix[ prfx ] ;
390         } /* PREFIX NOT PROCESSED */
391       } /* WHILE */
392
393    } /* NOT PROCESSED */
394      
395    makevirtlist(pr) ;
396  } /* for */
397
398 } /* Lists */
399
400
401 void handlers(){
402   protaddr prot;
403   address  pip,listfrompref;
404   int      h;
405
406   for (prot = MAINBLOCK; prot <= lastprot; prot++)
407   /*    WITH PROTOTYPE[  PROT  ] ^ DO */
408   {  if (prototype[prot]->kind == HANDLER)  /* SURELY NO OWN HANDLERS */
409        prototype[prot]->handlerlist = 0 ;
410      else
411      {
412        if (prototype[prot]->lthpreflist == 1)  /* NO PREFIX */
413          listfrompref = 0 ;
414        else
415          listfrompref = prototype[ prefix[ prot ] ]->handlerlist ;
416
417        pip = prototype[prot]->codeaddr ; /* prototype in ipmem */
418
419        if (ipmem[ pip + 19 ] == 0)  /* NO OWN HANDLERS */
420          prototype[prot]->handlerlist = listfrompref ;
421        else
422        { /* mb own handlers  possible */
423          reserve( 3 * ( ipmem[ pip + 19 ]) ) ;
424          prototype[prot]->handlerlist = fre + base ;
425          h = ipmem[ pip + 20 ] ;
426          /* first element of handler list in ipmem */
427   
428          do
429          { 
430            m[ fre ] = ipmem[ h ] ; /*signal identifier */
431 LOG(fre);     
432            m[ fre + 1 ] = ipmem[ (int)(ipmem[ h + 1 ]) - 1 ] ;
433 LOG(fre + 1); 
434       
435            /* handler prototype */
436            m[ fre + 2 ] = fre + 3 + base ; /* next */
437 LOG(fre + 2);     
438            h = ipmem[ h + 2 ] ;
439            fre += 3 ;
440          } while (h) ;
441   
442          m[ fre - 1 ] = listfrompref ;
443 LOG(fre - 1);     
444
445        } /* else */
446      } /* OWN HANDLERS */
447   } /* for */
448 } /* HANDLERS */
449
450
451
452 void primdescr(){
453 /* DESCRIPTIONS OF PRIMITIVE TYPES */
454
455   /*printf("primdescr: fre = %d\n", fre) ;  */
456   assert(fre == 0 && base > 0);
457   ipradr =base + fre ;
458   m[  fre + TINT  ] = PRIMITIVETYPE ;
459   m[  fre + TREAL  ] = PRIMITIVETYPE ;
460   m[  fre + TBOOLEAN ] = PRIMITIVETYPE ;
461   m[  fre + TCHAR  ]   = PRIMITIVETYPE ;
462   m[  fre + TCOROUT  ] = PURECOROUTINE ;
463   m[  fre + TPROCESS  ]= PUREPROCESS ;
464   m[  fre + TSTRING  ] = PRIMITIVETYPE ;
465   m[  fre + TFUNC2  ]  = FORMFUNC ;
466   m[  fre + TPROC2  ]  = FORMPROC ;
467   m[  fre + TFILE   ]  = FILETYPE ; /*DSW*/
468     
469   /*dsw*/ /* fre=fre+TPROC2+1; */
470
471   fre = fre + TFILE + 1 ; /*dsw*/
472
473   /* STORE ADDRESSES OF THESE TYPES DESCRIPTIONS */
474     
475   /*DSW&BC...*/
476   if (ipradr + TFILE > MAXINT - 1) generror(TLDESCR) ;
477
478   ipmem[ nrint + 2  ] = -(ipradr + TINT) ;
479   ipmem[ nrre + 2   ] = -(ipradr + TREAL) ;
480   ipmem[ nrbool + 2 ] = -(ipradr + TBOOLEAN) ;
481   ipmem[ nrchr + 2  ] = -(ipradr + TCHAR) ;
482   ipmem[ nrcor + 2  ] = -(ipradr + TCOROUT) ;
483   ipmem[ nrproc + 2 ] = -(ipradr + TPROCESS) ;
484   ipmem[ nrtext + 2 ] = -(ipradr + TSTRING) ;
485    
486 } /* PRIMDESCR */
487
488        
489        
490 void addtolist(head, i)    /* gsg ATTENTION !!! head is "var" parameter !!! */
491 /* ADD THE NEW ELEMENT WITH VALUE "I" TO THE LIST
492    REFERED BY "HEAD" */
493 /* head is passed by reference - it is an "inout" parameter */
494 /* so it is pointer to pointer to first item                */
495    
496 pointer *  head ;  /* i.e  item  **head */
497 int i ;
498 {
499   pointer elem ;
500        
501   elem = *head ;
502   (*head) = (pointer) new(*head) ;
503   (*head)->ip = i ;
504   (*head)->prevelem = elem ;
505       
506 } /* ADDTOLIST */
507
508       
509 void longaddtolist(head, i)   /* gsg ATTENTION !!! head is "var" parameter !!! */
510 /* ADD THE NEW ELEMENT WITH VALUE "I" TO THE LIST
511    REFERED BY "HEAD" */
512 longpointer * head ;
513 address i ;
514 {
515   longpointer  elem ;
516
517   elem = (*head) ;
518   (*head) = (longpointer) new(*head);
519   (*head)->ip = i ;
520   (*head)->prevelem = elem ;
521       
522 } /* longaddtolist */
523
524
525 void backpatch(i, a) int i; address a;{
526
527 /* SATISFY REFERENCES (IF ANY) TO THE TYPE WITH IPMEM ADDRESS I           */
528 /*         WITH THE VALUE A .                                             */
529 /* IPMEM(I+2) >= 0    ==> NO DESCRIPTION YET,                             */
530 /*                        IF IPMEM(I-2) >= 0 THEN NOT REFERED YET,        */
531 /*                        OTHERWISE = -LINK TO THE FIRST ELEMENT OF LIST  */
532 /* IPMEM(I+2) < 0     ==> DESCRIPTION ALREADY MADE                        */
533 /*                    AT ADDRESS = -IPMEM(I+2)                            */
534
535   address n,k;
536
537   /*DSW&BC...*/   if(a > MAXINT - 1) generror(TLDESCR);
538
539   /* ANY REFERENCES ? */
540   if(ipmem[ i - 2 ] < 0){ 
541     n = -ipmem[ i - 2 ];
542     ipmem[ i - 2 ] = 0;
543
544     while (n > 0){
545       k = n; 
546       n = - m[n];
547       m[ k ] = a;
548       LOG(k);
549     }
550   }
551   ipmem[ i + 2 ] = -a ; /* DESCR. ALREADY MADE */
552 }
553
554
555 void pdescr(){
556 /* FILLS THE PROTOTYPE OF UNIT.                        */
557 /*   FOR THE CLASS ALSO CREATES CLASS TYPE DESCRIPTION */
558
559   pointprdsc  prfx ; /* POINTER TO PREFIX DESCRIPTION      */
560   int         ip ;   /* ADDRESS IN IPMEM                   */
561   pointprdsc  curr ; /* gsg translation of the Pascal WITH */
562    
563   /*  WITH PROTOTYPE[  LASTPROT  ]^ DO */
564   {  curr = prototype[ lastprot ] ;
565      ip = curr->codeaddr ;
566       
567      if (lastprot == MAINBLOCK)
568        curr->slprototype = DUMMY ;
569      else
570        curr->slprototype = ipmem[ ipmem[ip-1]-1 ] ; /*PROTOTYPE NUMBER FOR SL*/
571  
572      ipmem[ ip - 1 ] = lastprot ;
573      curr->appetite = APINT + APINT ; /* 2 CELLS: OBJECT'S APPETITE, */
574                                       /*           PROTOTYPE ADDRESS */
575      curr->span = 0 ;
576      listofref[ lastprot ] = NULL ;
577      curr->lthreflist = 0 ;
578      listofpar[ lastprot ] = NULL ;
579      curr->lthparlist = 0 ;
580      curr->preflist = 0 ;
581      curr->lthpreflist = 1 ;
582      curr->lastwill = 0 ;
583      curr->handlerlist = 0 ;
584      curr->virtlist = 0 ;
585
586      /*CBC added virtual number ...*/
587      if (iand(ipmem[ ip ], 8 * 256) != 0)  /* virtual ? 0800 */
588        curr->virtnumber = ipmem[ ip + 27 ] ;  /* yes, store virtual number */
589      else
590        curr->virtnumber = -1 ;               /* no, flag that not virtual */
591      /*...CBC*/
592
593      prefix[ lastprot ] = DUMMY ;
594      
595      if ( (curr->kind  == CLASS) || (curr->kind == LRECORD) ||
596           (curr->kind ==COROUTINE) || (curr->kind ==PROCESS) ||
597           (curr->kind == PREFBLOCK) || (curr->kind ==LFUNCTION) ||
598           (curr->kind ==LPROCEDURE) )
599
600      { /* POSSIBLY PREFIXED */
601        if (ipmem[ ip + 21 ] != 0)
602        { /* PREFIXED UNIT */
603          prefix[ lastprot ] = ipmem[ ipmem[ ip + 21 ] - 1 ] ;
604          prfx = prototype[ prefix[ lastprot ] ] ;
605          curr->lthpreflist = prfx->lthpreflist + 1 ;
606          listofref[ lastprot ] = listofref[ prefix[ lastprot ] ] ;
607          curr->lthreflist = prfx->lthreflist ;
608          listofpar[ lastprot ] = listofpar[ prefix[ lastprot ] ] ;
609          curr->lthparlist = prfx->lthparlist ;
610          curr->appetite = prfx->appetite ;
611        } /* PREFIXED UNIT */
612
613        if ( (curr->kind  == CLASS) || (curr->kind == LRECORD) ||
614           (curr->kind ==COROUTINE) || (curr->kind ==PROCESS)      )
615        { /* CREATE CLASS TYPE */
616          reserve(2) ;
617          backpatch(ip, fre + base) ;
618          m[ fre++ ] = CLASSTYPE ;
619 LOG(fre - 1);     
620          m[ fre++ ]= lastprot ;
621 LOG(fre - 1);     
622          
623        } /* CLASS TYPE */
624      } /* POSSIBLE PREFIXED */
625   } /* WITH */
626        
627 } /* PDESCR */
628
629