[project @ 2000-03-24 14:32:03 by sewardj]
[ghc-hetmet.git] / ghc / interpreter / storage.c
1
2 /* --------------------------------------------------------------------------
3  * Primitives for manipulating global data structures
4  *
5  * The Hugs 98 system is Copyright (c) Mark P Jones, Alastair Reid, the
6  * Yale Haskell Group, and the Oregon Graduate Institute of Science and
7  * Technology, 1994-1999, All rights reserved.  It is distributed as
8  * free software under the license in the file "License", which is
9  * included in the distribution.
10  *
11  * $RCSfile: storage.c,v $
12  * $Revision: 1.55 $
13  * $Date: 2000/03/24 14:32:03 $
14  * ------------------------------------------------------------------------*/
15
16 #include "hugsbasictypes.h"
17 #include "storage.h"
18 #include "connect.h"
19 #include "errors.h"
20 #include "object.h"
21 #include <setjmp.h>
22
23 /*#define DEBUG_SHOWUSE*/
24
25 /* --------------------------------------------------------------------------
26  * local function prototypes:
27  * ------------------------------------------------------------------------*/
28
29 static Int    local hash                ( String );
30 static Int    local saveText            ( Text );
31 static Module local findQualifier       ( Text );
32 static Void   local hashTycon           ( Tycon );
33 static List   local insertTycon         ( Tycon,List );
34 static Void   local hashName            ( Name );
35 static List   local insertName          ( Name,List );
36 static Void   local patternError        ( String );
37 static Bool   local stringMatch         ( String,String );
38 static Bool   local typeInvolves        ( Type,Type );
39 static Cell   local markCell            ( Cell );
40 static Void   local markSnd             ( Cell );
41 static Cell   local lowLevelLastIn      ( Cell );
42 static Cell   local lowLevelLastOut     ( Cell );
43
44
45 /* --------------------------------------------------------------------------
46  * Text storage:
47  *
48  * provides storage for the characters making up identifier and symbol
49  * names, string literals, character constants etc...
50  *
51  * All character strings are stored in a large character array, with textHw
52  * pointing to the next free position.  Lookup in the array is improved using
53  * a hash table.  Internally, text strings are represented by integer offsets
54  * from the beginning of the array to the string in question.
55  *
56  * Where memory permits, the use of multiple hashtables gives a significant
57  * increase in performance, particularly when large source files are used.
58  *
59  * Each string in the array is terminated by a zero byte.  No string is
60  * stored more than once, so that it is safe to test equality of strings by
61  * comparing the corresponding offsets.
62  *
63  * Special text values (beyond the range of the text array table) are used
64  * to generate unique `new variable names' as required.
65  *
66  * The same text storage is also used to hold text values stored in a saved
67  * expression.  This grows downwards from the top of the text table (and is
68  * not included in the hash table).
69  * ------------------------------------------------------------------------*/
70
71 #define TEXTHSZ 512                     /* Size of Text hash table         */
72 #define NOTEXT  ((Text)(~0))            /* Empty bucket in Text hash table */
73 static  Text    textHw;                 /* Next unused position            */
74 static  Text    savedText = TEXT_SIZE;  /* Start of saved portion of text  */
75 static  Text    nextNewText;            /* Next new text value             */
76 static  Text    nextNewDText;           /* Next new dict text value        */
77 static  char    text[TEXT_SIZE];        /* Storage of character strings    */
78 static  Text    textHash[TEXTHSZ][NUM_TEXTH]; /* Hash table storage        */
79
80 String textToStr(t)                    /* find string corresp to given Text*/
81 Text t; {
82     static char newVar[16];
83
84     if (isText(t))                              /* standard char string    */
85         return text + t - TEXT_BASE_ADDR;
86     if (isInventedDictVar(t)) {
87         sprintf(newVar,"d%d",
88                 t-INDVAR_BASE_ADDR);            /* dictionary variable     */
89         return newVar;
90     }
91     if (isInventedVar(t)) {
92         sprintf(newVar,"v%d",
93                 t-INVAR_BASE_ADDR);             /* normal variable         */
94        return newVar;
95     }
96     internal("textToStr");
97 }
98
99 String identToStr(v) /*find string corresp to given ident or qualified name*/
100 Cell v; {
101     if (!isPair(v)) {
102         internal("identToStr");
103     }
104     switch (fst(v)) {
105         case VARIDCELL  :
106         case VAROPCELL  : 
107         case CONIDCELL  :
108         case CONOPCELL  : return text+textOf(v);
109
110         case QUALIDENT  : {   Text pos = textHw;
111                               Text t   = qmodOf(v);
112                               while (pos+1 < savedText && text[t]!=0) {
113                                   text[pos++] = text[t++];
114                               }
115                               if (pos+1 < savedText) {
116                                   text[pos++] = '.';
117                               }
118                               t = qtextOf(v);
119                               while (pos+1 < savedText && text[t]!=0) {
120                                   text[pos++] = text[t++];
121                               }
122                               text[pos] = '\0';
123                               return text+textHw;
124                           }
125     }
126     internal("identToStr2");
127     return 0; /* NOTREACHED */
128 }
129
130 Text inventText()     {                 /* return new unused variable name */
131    if (nextNewText >= INVAR_BASE_ADDR+INVAR_MAX_AVAIL)
132       internal("inventText: too many invented variables");
133    return nextNewText++;
134 }
135
136 Text inventDictText() {                 /* return new unused dictvar name  */
137    if (nextNewDText >= INDVAR_BASE_ADDR+INDVAR_MAX_AVAIL)
138      internal("inventDictText: too many invented variables");
139    return nextNewDText++;
140 }
141
142 Bool inventedText(t)                    /* Signal TRUE if text has been    */
143 Text t; {                               /* generated internally            */
144     return isInventedVar(t) || isInventedDictVar(t);
145 }
146
147 #define MAX_FIXLIT 100
148 Text fixLitText(t)                /* fix literal text that might include \ */
149 Text t; {
150     String   s = textToStr(t);
151     char     p[MAX_FIXLIT];
152     Int      i;
153     for(i = 0;i < MAX_FIXLIT-2 && *s;s++) {
154       p[i++] = *s;
155       if (*s == '\\') {
156         p[i++] = '\\';
157       } 
158     }
159     if (i < MAX_FIXLIT-2) {
160       p[i] = 0;
161     } else {
162         ERRMSG(0) "storage space exhausted for internal literal string"
163         EEND;
164     }
165     return (findText(p));
166 }
167 #undef MAX_FIXLIT
168
169 static Int local hash(s)                /* Simple hash function on strings */
170 String s; {
171     int v, j = 3;
172
173     for (v=((int)(*s))*8; *s; s++)
174         v += ((int)(*s))*(j++);
175     if (v<0)
176         v = (-v);
177     return(v%TEXTHSZ);
178 }
179
180 Text findText(s)                       /* Locate string in Text array      */
181 String s; {
182     int    h       = hash(s);
183     int    hashno  = 0;
184     Text   textPos = textHash[h][hashno];
185
186 #   define TryMatch     {   Text   originalTextPos = textPos;              \
187                             String t;                                      \
188                             for (t=s; *t==text[textPos]; textPos++,t++)    \
189                                 if (*t=='\0')                              \
190                                     return originalTextPos+TEXT_BASE_ADDR; \
191                         }
192 #   define Skip         while (text[textPos++]) ;
193
194     while (textPos!=NOTEXT) {
195         TryMatch
196         if (++hashno<NUM_TEXTH)         /* look in next hashtable entry    */
197             textPos = textHash[h][hashno];
198         else {
199             Skip
200             while (textPos < textHw) {
201                 TryMatch
202                 Skip
203             }
204             break;
205         }
206     }
207
208 #undef TryMatch
209 #undef Skip
210
211     textPos = textHw;                  /* if not found, save in array      */
212     if (textHw + (Int)strlen(s) + 1 > savedText) {
213         ERRMSG(0) "Character string storage space exhausted"
214         EEND;
215     }
216     while ((text[textHw++] = *s++) != 0) {
217     }
218     if (hashno<NUM_TEXTH) {            /* updating hash table as necessary */
219         textHash[h][hashno] = textPos;
220         if (hashno<NUM_TEXTH-1)
221             textHash[h][hashno+1] = NOTEXT;
222     }
223
224     return textPos+TEXT_BASE_ADDR;
225 }
226
227 static Int local saveText(t)            /* Save text value in buffer       */
228 Text t; {                               /* at top of text table            */
229     String s = textToStr(t);
230     Int    l = strlen(s);
231     if (textHw + l + 1 > savedText) {
232         ERRMSG(0) "Character string storage space exhausted"
233         EEND;
234     }
235     savedText -= l+1;
236     strcpy(text+savedText,s);
237     return savedText;
238 }
239
240
241 static int fromHexDigit ( char c )
242 {
243    switch (c) {
244       case '0': case '1': case '2': case '3': case '4':
245       case '5': case '6': case '7': case '8': case '9':
246          return c - '0';
247       case 'a': case 'A': return 10;
248       case 'b': case 'B': return 11;
249       case 'c': case 'C': return 12;
250       case 'd': case 'D': return 13;
251       case 'e': case 'E': return 14;
252       case 'f': case 'F': return 15;
253       default: return -1;
254    }
255 }
256
257
258 /* returns findText (unZencode s) */
259 Text unZcodeThenFindText ( String s )
260 {
261    unsigned char* p;
262    Int            n, nn, i;
263    Text           t;
264
265    assert(s);
266    nn = 100 + 10 * strlen(s);
267    p = malloc ( nn );
268    if (!p) internal ("unZcodeThenFindText: malloc failed");
269    n = 0;
270
271    while (1) {
272       if (!(*s)) break;
273       if (n > nn-90) internal ("unZcodeThenFindText: result is too big");
274       if (*s != 'z' && *s != 'Z') {
275          p[n] = *s; n++; s++; 
276          continue;
277       }
278       s++;
279       if (!(*s)) goto parse_error;
280       switch (*s++) {
281          case 'Z': p[n++] = 'Z'; break;
282          case 'C': p[n++] = ':'; break;
283          case 'L': p[n++] = '('; break;
284          case 'R': p[n++] = ')'; break;
285          case 'M': p[n++] = '['; break;
286          case 'N': p[n++] = ']'; break;
287          case 'z': p[n++] = 'z'; break;
288          case 'a': p[n++] = '&'; break;
289          case 'b': p[n++] = '|'; break;
290          case 'd': p[n++] = '$'; break;
291          case 'e': p[n++] = '='; break;
292          case 'g': p[n++] = '>'; break;
293          case 'h': p[n++] = '#'; break;
294          case 'i': p[n++] = '.'; break;
295          case 'l': p[n++] = '<'; break;
296          case 'm': p[n++] = '-'; break;
297          case 'n': p[n++] = '!'; break;
298          case 'p': p[n++] = '+'; break;
299          case 'q': p[n++] = '\\'; break;
300          case 'r': p[n++] = '\''; break;
301          case 's': p[n++] = '/'; break;
302          case 't': p[n++] = '*'; break;
303          case 'u': p[n++] = '^'; break;
304          case 'v': p[n++] = '%'; break;
305          case 'x':
306             if (!s[0] || !s[1]) goto parse_error;
307             if (fromHexDigit(s[0]) < 0 || fromHexDigit(s[1]) < 0) goto parse_error;
308             p[n++] = 16 * fromHexDigit(s[0]) + fromHexDigit(s[1]);
309             p += 2; s += 2;
310             break;
311          case '0': case '1': case '2': case '3': case '4':
312          case '5': case '6': case '7': case '8': case '9':
313             i = 0;
314             s--;
315             while (*s && isdigit((int)(*s))) {
316                i = 10 * i + (*s - '0');
317                s++;
318             }
319             if (*s != 'T') goto parse_error;
320             s++;
321             p[n++] = '(';
322             while (i > 0) { p[n++] = ','; i--; };
323             p[n++] = ')';
324             break;
325          default: 
326             goto parse_error;
327       }      
328    }
329    p[n] = 0;
330    t = findText(p);
331    free(p);
332    return t;
333
334   parse_error:
335    free(p);
336    fprintf ( stderr, "\nstring = `%s'\n", s );
337    internal ( "unZcodeThenFindText: parse error on above string");
338    return NIL; /*notreached*/
339 }
340
341
342 Text enZcodeThenFindText ( String s )
343 {
344    unsigned char* p;
345    Int            n, nn;
346    Text           t;
347    char toHex[16] = "0123456789ABCDEF";
348
349    assert(s);
350    nn = 100 + 10 * strlen(s);
351    p = malloc ( nn );
352    if (!p) internal ("enZcodeThenFindText: malloc failed");
353    n = 0;
354    while (1) {
355       if (!(*s)) break;
356       if (n > nn-90) internal ("enZcodeThenFindText: result is too big");
357       if (*s != 'z' 
358           && *s != 'Z'
359           && (isalnum((int)(*s)) || *s == '_')) { 
360          p[n] = *s; n++; s++;
361          continue;
362       }
363       if (*s == '(') {
364          int tup = 0;
365          char num[12];
366          s++;
367          while (*s && *s==',') { s++; tup++; };
368          if (*s != ')') internal("enZcodeThenFindText: invalid tuple type");
369          s++;
370          p[n++] = 'Z';
371          sprintf(num,"%d",tup);
372          p[n] = 0; strcat ( &(p[n]), num ); n += strlen(num);
373          p[n++] = 'T';
374          continue;         
375       }
376       switch (*s++) {
377          case '(': p[n++] = 'Z'; p[n++] = 'L'; break;
378          case ')': p[n++] = 'Z'; p[n++] = 'R'; break;
379          case '[': p[n++] = 'Z'; p[n++] = 'M'; break;
380          case ']': p[n++] = 'Z'; p[n++] = 'N'; break;
381          case ':': p[n++] = 'Z'; p[n++] = 'C'; break;
382          case 'Z': p[n++] = 'Z'; p[n++] = 'Z'; break;
383          case 'z': p[n++] = 'z'; p[n++] = 'z'; break;
384          case '&': p[n++] = 'z'; p[n++] = 'a'; break;
385          case '|': p[n++] = 'z'; p[n++] = 'b'; break;
386          case '$': p[n++] = 'z'; p[n++] = 'd'; break;
387          case '=': p[n++] = 'z'; p[n++] = 'e'; break;
388          case '>': p[n++] = 'z'; p[n++] = 'g'; break;
389          case '#': p[n++] = 'z'; p[n++] = 'h'; break;
390          case '.': p[n++] = 'z'; p[n++] = 'i'; break;
391          case '<': p[n++] = 'z'; p[n++] = 'l'; break;
392          case '-': p[n++] = 'z'; p[n++] = 'm'; break;
393          case '!': p[n++] = 'z'; p[n++] = 'n'; break;
394          case '+': p[n++] = 'z'; p[n++] = 'p'; break;
395          case '\'': p[n++] = 'z'; p[n++] = 'q'; break;
396          case '\\': p[n++] = 'z'; p[n++] = 'r'; break;
397          case '/': p[n++] = 'z'; p[n++] = 's'; break;
398          case '*': p[n++] = 'z'; p[n++] = 't'; break;
399          case '^': p[n++] = 'z'; p[n++] = 'u'; break;
400          case '%': p[n++] = 'z'; p[n++] = 'v'; break;
401          default: s--; p[n++] = 'z'; p[n++] = 'x';
402                        p[n++] = toHex[(int)(*s)/16];
403                        p[n++] = toHex[(int)(*s)%16];
404                   s++; break;
405       }
406    }
407    p[n] = 0;
408    t = findText(p);
409    free(p);
410    return t;
411 }
412
413
414 Text textOf ( Cell c )
415 {
416    Int  wot = whatIs(c);
417    Bool ok = 
418           (wot==VARIDCELL
419            || wot==CONIDCELL
420            || wot==VAROPCELL
421            || wot==CONOPCELL
422            || wot==STRCELL
423            || wot==DICTVAR
424            || wot==IPCELL
425            || wot==IPVAR
426           );
427    if (!ok) {
428       fprintf(stderr, "\ntextOf: bad tag %d\n",wot );
429       internal("textOf: bad tag");
430    }
431    return snd(c);
432 }
433
434 /* --------------------------------------------------------------------------
435  * Ext storage:
436  *
437  * Currently, the only attributes that we store for each Ext value is the
438  * corresponding Text label.  At some later stage, we may decide to cache
439  * types, predicates, etc. here as a space saving gesture.  Given that Text
440  * comparison is cheap, and that this is an experimental implementation, we
441  * will use a straightforward linear search to locate Ext values from their
442  * corresponding Text labels; a hashing scheme can be introduced later if
443  * this turns out to be a problem.
444  * ------------------------------------------------------------------------*/
445
446 #if TREX
447 Text  DEFTABLE(tabExt,NUM_EXT);         /* Storage for Ext names           */
448 Ext   extHw;
449
450 Ext mkExt(t)                            /* Allocate or find an Ext value   */
451 Text t; {
452     Ext e = EXTMIN;
453     for (; e<extHw; e++)
454         if (t==extText(e))
455             return e;
456     if (extHw-EXTMIN >= NUM_EXT) {
457         ERRMSG(0) "Ext storage space exhausted"
458         EEND;
459     }
460     extText(extHw) = t;
461     return extHw++;
462 }
463 #endif
464
465
466 /* --------------------------------------------------------------------------
467  * Expandable symbol tables.  A template, which is instantiated for the name, 
468  * tycon, class, instance and module tables.  Also, potentially, TREX Exts.
469  * ------------------------------------------------------------------------*/
470
471 #define EXPANDABLE_SYMBOL_TABLE(type_name,struct_name,                  \
472                                 proc_name,free_proc_name,               \
473                                 free_list,tab_name,tab_size,err_msg,    \
474                                 TAB_INIT_SIZE,TAB_MAX_SIZE,             \
475                                 TAB_BASE_ADDR)                          \
476                                                                         \
477              struct struct_name* tab_name  = NULL;                      \
478              int                 tab_size  = 0;                         \
479       static type_name           free_list = TAB_BASE_ADDR-1;           \
480                                                                         \
481       void free_proc_name ( type_name n )                               \
482       {                                                                 \
483          assert(TAB_BASE_ADDR <= n);                                    \
484          assert(n < TAB_BASE_ADDR+tab_size);                            \
485          assert(tab_name[n-TAB_BASE_ADDR].inUse);                       \
486          tab_name[n-TAB_BASE_ADDR].inUse = FALSE;                      \
487          /*tab_name[n-TAB_BASE_ADDR].nextFree = free_list; */               \
488          /*free_list = n;*/                                                 \
489       }                                                                 \
490                                                                         \
491       type_name proc_name ( void )                                      \
492       {                                                                 \
493          Int    i;                                                      \
494          Int    newSz;                                                  \
495          struct struct_name* newTab;                                    \
496          struct struct_name* temp;                                      \
497          try_again:                                                     \
498          if (free_list != TAB_BASE_ADDR-1) {                            \
499             type_name t = free_list;                                    \
500             free_list = tab_name[free_list-TAB_BASE_ADDR].nextFree;     \
501             assert (!(tab_name[t-TAB_BASE_ADDR].inUse));                \
502             tab_name[t-TAB_BASE_ADDR].inUse = TRUE;                     \
503             return t;                                                   \
504          }                                                              \
505                                                                         \
506          newSz = (tab_size == 0 ? TAB_INIT_SIZE : 2 * tab_size);        \
507          if (newSz > TAB_MAX_SIZE) goto cant_allocate;                  \
508          newTab = malloc(newSz * sizeof(struct struct_name));           \
509          if (!newTab) goto cant_allocate;                               \
510          for (i = 0; i < tab_size; i++)                                 \
511             newTab[i] = tab_name[i];                                    \
512          for (i = tab_size; i < newSz; i++) {                           \
513             newTab[i].inUse = FALSE;                                    \
514             newTab[i].nextFree = i-1+TAB_BASE_ADDR;                     \
515          }                                                              \
516          /* fprintf(stderr, "Expanding " #type_name                     \
517             "table to size %d\n", newSz );*/                    \
518          newTab[tab_size].nextFree = TAB_BASE_ADDR-1;                   \
519          free_list = newSz-1+TAB_BASE_ADDR;                             \
520          tab_size = newSz;                                              \
521          temp = tab_name;                                               \
522          tab_name = newTab;                                             \
523          if (temp) free(temp);                                          \
524          goto try_again;                                                \
525                                                                         \
526          cant_allocate:                                                 \
527          ERRMSG(0) err_msg                                              \
528          EEND;                                                          \
529       }                                                                 \
530
531
532
533 EXPANDABLE_SYMBOL_TABLE(Name,strName,allocNewName,freeName,
534                         nameFL,tabName,tabNameSz,
535                         "Name storage space exhausted",
536                         NAME_INIT_SIZE,NAME_MAX_SIZE,NAME_BASE_ADDR)
537
538
539 EXPANDABLE_SYMBOL_TABLE(Tycon,strTycon,allocNewTycon,freeTycon,
540                         tyconFL,tabTycon,tabTyconSz,
541                         "Type constructor storage space exhausted",
542                         TYCON_INIT_SIZE,TYCON_MAX_SIZE,TYCON_BASE_ADDR)
543
544
545 EXPANDABLE_SYMBOL_TABLE(Class,strClass,allocNewClass,freeClass,
546                         classFL,tabClass,tabClassSz,
547                         "Class storage space exhausted",
548                         CCLASS_INIT_SIZE,CCLASS_MAX_SIZE,CCLASS_BASE_ADDR)
549
550
551 EXPANDABLE_SYMBOL_TABLE(Inst,strInst,allocNewInst,freeInst,
552                         instFL,tabInst,tabInstSz,
553                         "Instance storage space exhausted",
554                         INST_INIT_SIZE,INST_MAX_SIZE,INST_BASE_ADDR)
555
556
557 EXPANDABLE_SYMBOL_TABLE(Module,strModule,allocNewModule,freeModule,
558                         moduleFL,tabModule,tabModuleSz,
559                         "Module storage space exhausted",
560                         MODULE_INIT_SIZE,MODULE_MAX_SIZE,MODULE_BASE_ADDR)
561
562 #ifdef DEBUG_STORAGE
563 struct strName* generate_name_ref ( Cell nm )
564 {
565    assert(isName(nm));
566    nm -= NAME_BASE_ADDR;
567    assert(tabName[nm].inUse);
568    assert(isModule(tabName[nm].mod));
569    return & tabName[nm]; 
570 }
571 struct strTycon* generate_tycon_ref ( Cell tc )
572 {
573    assert(isTycon(tc) || isTuple(tc));
574    tc -= TYCON_BASE_ADDR;
575    assert(tabTycon[tc].inUse);
576    assert(isModule(tabTycon[tc].mod));
577    return & tabTycon[tc]; 
578 }
579 struct strClass* generate_cclass_ref ( Cell cl )
580 {
581    assert(isClass(cl));
582    cl -= CCLASS_BASE_ADDR;
583    assert(tabClass[cl].inUse);
584    assert(isModule(tabClass[cl].mod));
585    return & tabClass[cl]; 
586 }
587 struct strInst* generate_inst_ref ( Cell in )
588 {  
589    assert(isInst(in));
590    in -= INST_BASE_ADDR;
591    assert(tabInst[in].inUse);
592    assert(isModule(tabInst[in].mod));
593    return & tabInst[in]; 
594 }
595 struct strModule* generate_module_ref ( Cell mo )
596 {  
597    assert(isModule(mo));
598    mo -= MODULE_BASE_ADDR;
599    assert(tabModule[mo].inUse);
600    return & tabModule[mo]; 
601 }
602 #endif
603
604
605 /* --------------------------------------------------------------------------
606  * Tycon storage:
607  *
608  * A Tycon represents a user defined type constructor.  Tycons are indexed
609  * by Text values ... a very simple hash function is used to improve lookup
610  * times.  Tycon entries with the same hash code are chained together, with
611  * the most recent entry at the front of the list.
612  * ------------------------------------------------------------------------*/
613
614 #define TYCONHSZ 256                            /* Size of Tycon hash table*/
615      //#define tHash(x) (((x)-TEXT_BASE_ADDR)%TYCONHSZ)/* Tycon hash function     */
616 static int tHash(Text x)
617 {
618    int r;
619    assert(isText(x) || inventedText(x));
620    x -= TEXT_BASE_ADDR;
621    if (x < 0) x = -x;
622    r= x%TYCONHSZ;
623    assert(r>=0);
624    assert(r<TYCONHSZ);
625    return r;
626 }
627 static  Tycon    tyconHash[TYCONHSZ];           /* Hash table storage      */
628 int RC_T ( int x ) 
629 {
630    assert (x >= 0 && x < TYCONHSZ);
631    return x;
632 }
633 Tycon newTycon ( Text t )               /* add new tycon to tycon table    */
634 {
635     Int   h                      = tHash(t);
636     Tycon tc                     = allocNewTycon();
637     tabTycon
638       [tc-TYCON_BASE_ADDR].tuple = -1;
639     tabTycon
640       [tc-TYCON_BASE_ADDR].mod   = currentModule;
641     tycon(tc).text               = t;   /* clear new tycon record          */
642     tycon(tc).kind               = NIL;
643     tycon(tc).defn               = NIL;
644     tycon(tc).what               = NIL;
645     tycon(tc).conToTag           = NIL;
646     tycon(tc).tagToCon           = NIL;
647     tycon(tc).itbl               = NULL;
648     tycon(tc).arity              = 0;
649     module(currentModule).tycons = cons(tc,module(currentModule).tycons);
650     tycon(tc).nextTyconHash      = tyconHash[RC_T(h)];
651     tyconHash[RC_T(h)]                 = tc;
652     return tc;
653 }
654
655 Tycon findTycon(t)                      /* locate Tycon in tycon table     */
656 Text t; {
657     Tycon tc = tyconHash[RC_T(tHash(t))];
658 assert(isTycon(tc) || isTuple(tc) || isNull(tc));
659     while (nonNull(tc) && tycon(tc).text!=t)
660         tc = tycon(tc).nextTyconHash;
661     return tc;
662 }
663
664 Tycon addTycon(tc)  /* Insert Tycon in tycon table - if no clash is caused */
665 Tycon tc; {
666     Tycon oldtc; 
667     assert(isTycon(tc) || isTuple(tc));
668     oldtc = findTycon(tycon(tc).text);
669     if (isNull(oldtc)) {
670         hashTycon(tc);
671         module(currentModule).tycons=cons(tc,module(currentModule).tycons);
672         return tc;
673     } else
674         return oldtc;
675 }
676
677 static Void local hashTycon(tc)         /* Insert Tycon into hash table    */
678 Tycon tc; {
679    Text t;
680    Int  h;
681    assert(isTycon(tc) || isTuple(tc));
682    {int i; for (i = 0; i < TYCONHSZ; i++)
683        assert (tyconHash[i] == 0 
684                || isTycon(tyconHash[i])
685                || isTuple(tyconHash[i]));
686    }
687    t = tycon(tc).text;
688    h = tHash(t);
689    tycon(tc).nextTyconHash = tyconHash[RC_T(h)];
690    tyconHash[RC_T(h)]            = tc;
691 }
692
693 Tycon findQualTycon(id) /*locate (possibly qualified) Tycon in tycon table */
694 Cell id; {
695     if (!isPair(id)) internal("findQualTycon");
696     switch (fst(id)) {
697         case CONIDCELL :
698         case CONOPCELL :
699             return findTycon(textOf(id));
700         case QUALIDENT : {
701             Text   t  = qtextOf(id);
702             Module m  = findQualifier(qmodOf(id));
703             List   es = NIL;
704             if (isNull(m)) return NIL;
705             for(es=module(m).exports; nonNull(es); es=tl(es)) {
706                 Cell e = hd(es);
707                 if (isPair(e) && isTycon(fst(e)) && tycon(fst(e)).text==t) 
708                     return fst(e);
709             }
710             return NIL;
711         }
712         default : internal("findQualTycon2");
713     }
714     return NIL; /* NOTREACHED */
715 }
716
717 Tycon addPrimTycon(t,kind,ar,what,defn) /* add new primitive type constr   */
718 Text t;
719 Kind kind;
720 Int  ar;
721 Cell what;
722 Cell defn; {
723     Tycon tc        = newTycon(t);
724     tycon(tc).line  = 0;
725     tycon(tc).kind  = kind;
726     tycon(tc).what  = what;
727     tycon(tc).defn  = defn;
728     tycon(tc).arity = ar;
729     return tc;
730 }
731
732 static List local insertTycon(tc,ts)    /* insert tycon tc into sorted list*/
733 Tycon tc;                               /* ts                              */
734 List  ts; {
735     Cell   prev = NIL;
736     Cell   curr = ts;
737     String s    = textToStr(tycon(tc).text);
738
739     while (nonNull(curr) && strCompare(s,textToStr(tycon(hd(curr)).text))>=0) {
740         if (hd(curr)==tc)               /* just in case we get duplicates! */
741             return ts;
742         prev = curr;
743         curr = tl(curr);
744     }
745     if (nonNull(prev)) {
746         tl(prev) = cons(tc,curr);
747         return ts;
748     }
749     else
750         return cons(tc,curr);
751 }
752
753 List addTyconsMatching(pat,ts)          /* Add tycons matching pattern pat */
754 String pat;                             /* to list of Tycons ts            */
755 List   ts; {                            /* Null pattern matches every tycon*/
756     Tycon tc;                           /* (Tycons with NIL kind excluded) */
757     for (tc = TYCON_BASE_ADDR;
758          tc < TYCON_BASE_ADDR+tabTyconSz; ++tc)
759         if (tabTycon[tc-TYCON_BASE_ADDR].inUse)
760            if (!pat || stringMatch(pat,textToStr(tycon(tc).text)))
761                if (nonNull(tycon(tc).kind))
762                   ts = insertTycon(tc,ts);
763     return ts;
764 }
765
766 Text ghcTupleText_n ( Int n )
767 {
768     Int i;
769     Int x = 0; 
770     char buf[104];
771     if (n < 0 || n >= 100) internal("ghcTupleText_n");
772     if (n == 1) internal("ghcTupleText_n==1");
773     buf[x++] = '(';
774     for (i = 1; i <= n-1; i++) buf[x++] = ',';
775     buf[x++] = ')';
776     buf[x++] = 0;
777     return findText(buf);
778 }
779
780 Text ghcTupleText(tup)
781 Tycon tup; {
782     if (!isTuple(tup)) {
783        assert(isTuple(tup));
784     }
785     return ghcTupleText_n ( tupleOf(tup) );
786 }
787
788
789 Tycon mkTuple ( Int n )
790 {
791    Int i;
792    if (n >= NUM_TUPLES)
793       internal("mkTuple: request for tuple of unsupported size");
794    for (i = TYCON_BASE_ADDR;
795         i < TYCON_BASE_ADDR+tabTyconSz; i++)
796       if (tabTycon[i-TYCON_BASE_ADDR].inUse)
797          if (tycon(i).tuple == n) return i;
798    internal("mkTuple: request for non-existent tuple");
799 }
800
801
802 /* --------------------------------------------------------------------------
803  * Name storage:
804  *
805  * A Name represents a top level binding of a value to an identifier.
806  * Such values may be a constructor function, a member function in a
807  * class, a user-defined or primitive value/function.
808  *
809  * Names are indexed by Text values ... a very simple hash functions speeds
810  * access to the table of Names and Name entries with the same hash value
811  * are chained together, with the most recent entry at the front of the
812  * list.
813  * ------------------------------------------------------------------------*/
814
815 #define NAMEHSZ  256                            /* Size of Name hash table */
816 //#define nHash(x) (((x)-TEXT_BASE_ADDR)%NAMEHSZ) /* hash fn :: Text->Int    */
817 static int nHash(Text x)
818 {
819    assert(isText(x) || inventedText(x));
820    x -= TEXT_BASE_ADDR;
821    if (x < 0) x = -x;
822    return x%NAMEHSZ;
823 }
824 static  Name     nameHash[NAMEHSZ];             /* Hash table storage      */
825 int RC_N ( int x ) 
826 {
827    assert (x >= 0 && x < NAMEHSZ);
828    return x;
829 }
830 void hashSanity ( void )
831 {
832    Int i, j;
833    for (i = 0; i < TYCONHSZ; i++) {
834       j = tyconHash[i];
835       while (nonNull(j)) {
836          assert(isTycon(j) || isTuple(j));
837          j = tycon(j).nextTyconHash;
838       }
839    }
840    for (i = 0; i < NAMEHSZ; i++) {
841       j = nameHash[i];
842       while (nonNull(j)) {
843          assert(isName(j));
844          j = name(j).nextNameHash;
845       }
846    }
847 }
848
849 Name newName ( Text t, Cell parent )    /* Add new name to name table      */
850 {
851     Int h = nHash(t);
852     Name nm = allocNewName();
853     tabName
854        [nm-NAME_BASE_ADDR].mod  = currentModule;
855     name(nm).text               = t;    /* clear new name record           */
856     name(nm).line               = 0;
857     name(nm).syntax             = NO_SYNTAX;
858     name(nm).parent             = parent;
859     name(nm).arity              = 0;
860     name(nm).number             = EXECNAME;
861     name(nm).defn               = NIL;
862     name(nm).stgVar             = NIL;
863     name(nm).callconv           = NIL;
864     name(nm).type               = NIL;
865     name(nm).primop             = NULL;
866     name(nm).itbl               = NULL;
867     module(currentModule).names = cons(nm,module(currentModule).names);
868     name(nm).nextNameHash       = nameHash[RC_N(h)];
869     nameHash[RC_N(h)]                 = nm;
870     return nm;
871 }
872
873 Name findName(t)                        /* Locate name in name table       */
874 Text t; {
875     Name n = nameHash[RC_N(nHash(t))];
876 assert(isText(t));
877 assert(isName(n) || isNull(n));
878     while (nonNull(n) && name(n).text!=t)
879         n = name(n).nextNameHash;
880     return n;
881 }
882
883 Name addName(nm)                        /* Insert Name in name table - if  */
884 Name nm; {                              /* no clash is caused              */
885     Name oldnm; 
886     assert(isName(nm));
887     oldnm = findName(name(nm).text);
888     if (isNull(oldnm)) {
889         hashName(nm);
890         module(currentModule).names=cons(nm,module(currentModule).names);
891         return nm;
892     } else
893         return oldnm;
894 }
895
896 static Void local hashName(nm)          /* Insert Name into hash table     */
897 Name nm; {
898     Text t;
899     Int  h;
900     assert(isName(nm));
901     t = name(nm).text;
902     h = nHash(t);
903     name(nm).nextNameHash = nameHash[RC_N(h)];
904     nameHash[RC_N(h)]           = nm;
905 }
906
907 Name findQualName(id)              /* Locate (possibly qualified) name*/
908 Cell id; {                         /* in name table                   */
909     if (!isPair(id))
910         internal("findQualName");
911     switch (fst(id)) {
912         case VARIDCELL :
913         case VAROPCELL :
914         case CONIDCELL :
915         case CONOPCELL :
916             return findName(textOf(id));
917         case QUALIDENT : {
918             Text   t  = qtextOf(id);
919             Module m  = findQualifier(qmodOf(id));
920             List   es = NIL;
921             if (isNull(m)) return NIL;
922             for(es=module(m).exports; nonNull(es); es=tl(es)) {
923                 Cell e = hd(es);
924                 if (isName(e) && name(e).text==t) 
925                     return e;
926                 else if (isPair(e) && DOTDOT==snd(e)) {
927                     List subentities = NIL;
928                     Cell c = fst(e);
929                     if (isTycon(c)
930                         && (tycon(c).what==DATATYPE || tycon(c).what==NEWTYPE))
931                         subentities = tycon(c).defn;
932                     else if (isClass(c))
933                         subentities = cclass(c).members;
934                     for(; nonNull(subentities); subentities=tl(subentities)) {
935                        if (!isName(hd(subentities)))
936                             internal("findQualName3");
937                         if (name(hd(subentities)).text == t)
938                             return hd(subentities);
939                     }
940                 }
941             }
942             return NIL;
943         }
944         default : internal("findQualName2");
945     }
946     return 0; /* NOTREACHED */
947 }
948
949
950 Name nameFromStgVar ( StgVar v )
951 {
952    Int n;
953    for (n = NAME_BASE_ADDR;
954         n < NAME_BASE_ADDR+tabNameSz; n++)
955       if (tabName[n-NAME_BASE_ADDR].inUse)
956          if (name(n).stgVar == v) return n;
957    return NIL;
958 }
959
960 void* getHugs_AsmObject_for ( char* s )
961 {
962    StgVar v;
963    Text   t = findText(s);
964    Name   n = NIL;
965    for (n = NAME_BASE_ADDR; 
966         n < NAME_BASE_ADDR+tabNameSz; n++)
967       if (tabName[n-NAME_BASE_ADDR].inUse)
968          if (name(n).text == t) break;
969    if (n == NAME_BASE_ADDR+tabNameSz) {
970       fprintf ( stderr, "can't find `%s' in ...\n", s );
971       internal("getHugs_AsmObject_for(1)");
972    }
973    v = name(n).stgVar;
974    if (!isStgVar(v) || !isPtr(stgVarInfo(v)))
975       internal("getHugs_AsmObject_for(2)");
976    return ptrOf(stgVarInfo(v));
977 }
978
979 /* --------------------------------------------------------------------------
980  * Primitive functions:
981  * ------------------------------------------------------------------------*/
982
983 Module findFakeModule ( Text t )
984 {
985    Module m = findModule(t);
986    if (nonNull(m)) {
987       if (!module(m).fake) internal("findFakeModule");
988    } else {
989       m = newModule(t);
990       module(m).fake = TRUE;
991    }
992    return m;
993 }
994
995
996 Name addWiredInBoxingTycon
997         ( String modNm, String typeNm, String constrNm,
998           Int rep, Kind kind )
999 {
1000    Name   n;
1001    Tycon  t;
1002    Text   modT  = findText(modNm);
1003    Text   typeT = findText(typeNm);
1004    Text   conT  = findText(constrNm);
1005    Module m     = findFakeModule(modT);
1006    setCurrModule(m);
1007    
1008    n = newName(conT,NIL);
1009    name(n).arity  = 1;
1010    name(n).number = cfunNo(0);
1011    name(n).type   = NIL;
1012    name(n).primop = (void*)rep;
1013
1014    t = newTycon(typeT);
1015    tycon(t).what = DATATYPE;
1016    tycon(t).kind = kind;
1017    return n;
1018 }
1019
1020
1021 Tycon addTupleTycon ( Int n )
1022 {
1023    Int    i;
1024    Kind   k;
1025    Tycon  t;
1026    Module m;
1027    Name   nm;
1028
1029    for (i = TYCON_BASE_ADDR; 
1030         i < TYCON_BASE_ADDR+tabTyconSz; i++)
1031       if (tabTycon[i-TYCON_BASE_ADDR].inUse)
1032          if (tycon(i).tuple == n) return i;
1033
1034    if (combined)
1035       m = findFakeModule(findText(n==0 ? "PrelBase" : "PrelTup")); else
1036       m = findModule(findText("Prelude"));
1037
1038    setCurrModule(m);
1039    k = STAR;
1040    for (i = 0; i < n; i++) k = ap(STAR,k);
1041    t = newTycon(ghcTupleText_n(n));
1042    tycon(t).kind  = k;
1043    tycon(t).tuple = n;
1044    tycon(t).what  = DATATYPE;
1045
1046    if (n == 0) {
1047       /* maybe we want to do this for all n ? */
1048       nm = newName(ghcTupleText_n(n), t);
1049       name(nm).type = t;   /* ummm ... for n > 0 */
1050    }
1051
1052    return t;
1053 }
1054
1055
1056 Tycon addWiredInEnumTycon ( String modNm, String typeNm, 
1057                             List /*of Text*/ constrs )
1058 {
1059    Int    i;
1060    Tycon  t;
1061    Text   modT  = findText(modNm);
1062    Text   typeT = findText(typeNm);
1063    Module m     = findFakeModule(modT);
1064    setCurrModule(m);
1065
1066    t             = newTycon(typeT);
1067    tycon(t).kind = STAR;
1068    tycon(t).what = DATATYPE;
1069    
1070    constrs = reverse(constrs);
1071    i       = length(constrs);
1072    for (; nonNull(constrs); constrs=tl(constrs),i--) {
1073       Text conT        = hd(constrs);
1074       Name con         = newName(conT,t);
1075       name(con).number = cfunNo(i);
1076       name(con).type   = t;
1077       name(con).parent = t;
1078       tycon(t).defn    = cons(con, tycon(t).defn);      
1079    }
1080    return t;
1081 }
1082
1083
1084 Name addPrimCfunREP(t,arity,no,rep)     /* add primitive constructor func  */
1085 Text t;                                 /* sets rep, not type              */
1086 Int  arity;
1087 Int  no;
1088 Int  rep; { /* Really AsmRep */
1089     Name n          = newName(t,NIL);
1090     name(n).arity   = arity;
1091     name(n).number  = cfunNo(no);
1092     name(n).type    = NIL;
1093     name(n).primop  = (void*)rep;
1094     return n;
1095 }
1096
1097
1098 Name addPrimCfun(t,arity,no,type)       /* add primitive constructor func  */
1099 Text t;
1100 Int  arity;
1101 Int  no;
1102 Cell type; {
1103     Name n         = newName(t,NIL);
1104     name(n).arity  = arity;
1105     name(n).number = cfunNo(no);
1106     name(n).type   = type;
1107     return n;
1108 }
1109
1110
1111 Int sfunPos(s,c)                        /* Find position of field with     */
1112 Name s;                                 /* selector s in constructor c.    */
1113 Name c; {
1114     List cns;
1115     cns = name(s).defn;
1116     for (; nonNull(cns); cns=tl(cns))
1117         if (fst(hd(cns))==c)
1118             return intOf(snd(hd(cns)));
1119     internal("sfunPos");
1120     return 0;/* NOTREACHED */
1121 }
1122
1123 static List local insertName(nm,ns)     /* insert name nm into sorted list */
1124 Name nm;                                /* ns                              */
1125 List ns; {
1126     Cell   prev = NIL;
1127     Cell   curr = ns;
1128     String s    = textToStr(name(nm).text);
1129
1130     while (nonNull(curr) && strCompare(s,textToStr(name(hd(curr)).text))>=0) {
1131         if (hd(curr)==nm)               /* just in case we get duplicates! */
1132             return ns;
1133         prev = curr;
1134         curr = tl(curr);
1135     }
1136     if (nonNull(prev)) {
1137         tl(prev) = cons(nm,curr);
1138         return ns;
1139     }
1140     else
1141         return cons(nm,curr);
1142 }
1143
1144 List addNamesMatching(pat,ns)           /* Add names matching pattern pat  */
1145 String pat;                             /* to list of names ns             */
1146 List   ns; {                            /* Null pattern matches every name */
1147     Name nm;                            /* (Names with NIL type, or hidden */
1148                                         /* or invented names are excluded) */
1149 #if 1
1150     for (nm = NAME_BASE_ADDR;
1151          nm < NAME_BASE_ADDR+tabNameSz; ++nm)
1152        if (tabName[nm-NAME_BASE_ADDR].inUse) {
1153           if (!inventedText(name(nm).text) && nonNull(name(nm).type)) {
1154              String str = textToStr(name(nm).text);
1155              if (str[0]!='_' && (!pat || stringMatch(pat,str)))
1156                  ns = insertName(nm,ns);
1157           }
1158        }
1159     return ns;
1160 #else
1161     List mns = module(currentModule).names;
1162     for(; nonNull(mns); mns=tl(mns)) {
1163         Name nm = hd(mns);
1164         if (!inventedText(name(nm).text)) {
1165             String str = textToStr(name(nm).text);
1166             if (str[0]!='_' && (!pat || stringMatch(pat,str)))
1167                 ns = insertName(nm,ns);
1168         }
1169     }
1170     return ns;
1171 #endif
1172 }
1173
1174 /* --------------------------------------------------------------------------
1175  * A simple string matching routine
1176  *     `*'    matches any sequence of zero or more characters
1177  *     `?'    matches any single character exactly 
1178  *     `@str' matches the string str exactly (ignoring any special chars)
1179  *     `\c'   matches the character c only (ignoring special chars)
1180  *     c      matches the character c only
1181  * ------------------------------------------------------------------------*/
1182
1183 static Void local patternError(s)       /* report error in pattern         */
1184 String s; {
1185     ERRMSG(0) "%s in pattern", s
1186     EEND;
1187 }
1188
1189 static Bool local stringMatch(pat,str)  /* match string against pattern    */
1190 String pat;
1191 String str; {
1192
1193     for (;;)
1194         switch (*pat) {
1195             case '\0' : return (*str=='\0');
1196
1197             case '*'  : do {
1198                             if (stringMatch(pat+1,str))
1199                                 return TRUE;
1200                         } while (*str++);
1201                         return FALSE;
1202
1203             case '?'  : if (*str++=='\0')
1204                             return FALSE;
1205                         pat++;
1206                         break;
1207
1208             case '['  : {   Bool found = FALSE;
1209                             while (*++pat!='\0' && *pat!=']')
1210                                 if (!found && ( pat[0] == *str  ||
1211                                                (pat[1] == '-'   &&
1212                                                 pat[2] != ']'   &&
1213                                                 pat[2] != '\0'  &&
1214                                                 pat[0] <= *str  &&
1215                                                 pat[2] >= *str)))
1216
1217                                     found = TRUE;
1218                             if (*pat != ']')
1219                                 patternError("missing `]'");
1220                             if (!found)
1221                                 return FALSE;
1222                             pat++;
1223                             str++;
1224                         }
1225                         break;
1226
1227             case '\\' : if (*++pat == '\0')
1228                             patternError("extra trailing `\\'");
1229                         /*fallthru!*/
1230             default   : if (*pat++ != *str++)
1231                             return FALSE;
1232                         break;
1233         }
1234 }
1235
1236 /* --------------------------------------------------------------------------
1237  * Storage of type classes, instances etc...:
1238  * ------------------------------------------------------------------------*/
1239
1240 static List  classes;                  /* list of classes in current scope */
1241
1242 Class newClass ( Text t )              /* add new class to class table     */
1243 {
1244     Class cl                     = allocNewClass();
1245     tabClass
1246       [cl-CCLASS_BASE_ADDR].mod  = currentModule;
1247     cclass(cl).text              = t;
1248     cclass(cl).arity             = 0;
1249     cclass(cl).kinds             = NIL;
1250     cclass(cl).head              = NIL;
1251     cclass(cl).fds               = NIL;
1252     cclass(cl).xfds              = NIL;
1253     cclass(cl).dcon              = NIL;
1254     cclass(cl).supers            = NIL;
1255     cclass(cl).dsels             = NIL;
1256     cclass(cl).members           = NIL;
1257     cclass(cl).defaults          = NIL;
1258     cclass(cl).instances         = NIL;
1259     classes                      = cons(cl,classes);
1260     module(currentModule).classes
1261        = cons(cl,module(currentModule).classes);
1262     return cl;
1263 }
1264
1265 Class findClass(t)                     /* look for named class in table    */
1266 Text t; {
1267     Class cl;
1268     List cs;
1269     for (cs=classes; nonNull(cs); cs=tl(cs)) {
1270         cl=hd(cs);
1271         if (cclass(cl).text==t)
1272             return cl;
1273     }
1274     return NIL;
1275 }
1276
1277 Class addClass(c)                       /* Insert Class in class list      */
1278 Class c; {                              /*  - if no clash caused           */
1279     Class oldc; 
1280     assert(whatIs(c)==CLASS);
1281     oldc = findClass(cclass(c).text);
1282     if (isNull(oldc)) {
1283         classes=cons(c,classes);
1284         module(currentModule).classes=cons(c,module(currentModule).classes);
1285         return c;
1286     }
1287     else
1288         return oldc;
1289 }
1290
1291 Class findQualClass(c)                  /* Look for (possibly qualified)   */
1292 Cell c; {                               /* class in class list             */
1293     if (!isQualIdent(c)) {
1294         return findClass(textOf(c));
1295     } else {
1296         Text   t  = qtextOf(c);
1297         Module m  = findQualifier(qmodOf(c));
1298         List   es = NIL;
1299         if (isNull(m))
1300             return NIL;
1301         for (es=module(m).exports; nonNull(es); es=tl(es)) {
1302             Cell e = hd(es);
1303             if (isPair(e) && isClass(fst(e)) && cclass(fst(e)).text==t) 
1304                 return fst(e);
1305         }
1306     }
1307     return NIL;
1308 }
1309
1310 Inst newInst() {                       /* Add new instance to table        */
1311     Inst in                    = allocNewInst();
1312     tabInst
1313        [in-INST_BASE_ADDR].mod = currentModule;
1314     inst(in).kinds             = NIL;
1315     inst(in).head              = NIL;
1316     inst(in).specifics         = NIL;
1317     inst(in).implements        = NIL;
1318     inst(in).builder           = NIL;
1319     return in;
1320 }
1321
1322 #ifdef DEBUG_DICTS
1323 extern Void printInst ( Inst));
1324
1325 Void printInst(in)
1326 Inst in; {
1327     Class cl = inst(in).c;
1328     Printf("%s-", textToStr(cclass(cl).text));
1329     printType(stdout,inst(in).t);
1330 }
1331 #endif /* DEBUG_DICTS */
1332
1333 Inst findFirstInst(tc)                  /* look for 1st instance involving */
1334 Tycon tc; {                             /* the type constructor tc         */
1335     return findNextInst(tc,INST_BASE_ADDR-1);
1336 }
1337
1338 Inst findNextInst(tc,in)                /* look for next instance involving*/
1339 Tycon tc;                               /* the type constructor tc         */
1340 Inst  in; {                             /* starting after instance in      */
1341     Cell pi;
1342     while (++in < INST_BASE_ADDR+tabInstSz) {
1343         if (!tabInst[in-INST_BASE_ADDR].inUse) continue;
1344         assert(isModule(inst(in).mod));
1345         pi = inst(in).head;
1346         for (; isAp(pi); pi=fun(pi))
1347             if (typeInvolves(arg(pi),tc))
1348                 return in;
1349     }
1350     return NIL;
1351 }
1352
1353 static Bool local typeInvolves(ty,tc)   /* Test to see if type ty involves */
1354 Type ty;                                /* type constructor/tuple tc.      */
1355 Type tc; {
1356     return (ty==tc)
1357         || (isAp(ty) && (typeInvolves(fun(ty),tc)
1358                          || typeInvolves(arg(ty),tc)));
1359 }
1360
1361
1362 /* Needed by finishGHCInstance to find classes, before the
1363    export list has been built -- so we can't use 
1364    findQualClass.
1365 */
1366 Class findQualClassWithoutConsultingExportList ( QualId q )
1367 {
1368    Class cl;
1369    Text t_mod;
1370    Text t_class;
1371
1372    assert(isQCon(q));
1373
1374    if (isCon(q)) {
1375       t_mod   = NIL;
1376       t_class = textOf(q);
1377    } else {
1378       t_mod   = qmodOf(q);
1379       t_class = qtextOf(q);
1380    }
1381
1382    for (cl = CCLASS_BASE_ADDR; 
1383         cl < CCLASS_BASE_ADDR+tabClassSz; cl++) {
1384       if (tabClass[cl-CCLASS_BASE_ADDR].inUse)
1385          if (cclass(cl).text == t_class) {
1386             /* Class name is ok, but is this the right module? */
1387             if (isNull(t_mod)   /* no module name specified */
1388                 || (nonNull(t_mod) 
1389                     && t_mod == module(cclass(cl).mod).text)
1390                )
1391                return cl;
1392          }
1393    }
1394    return NIL;
1395 }
1396
1397 /* Same deal, except for Tycons. */
1398 Tycon findQualTyconWithoutConsultingExportList ( QualId q )
1399 {
1400    Tycon tc;
1401    Text t_mod;
1402    Text t_tycon;
1403
1404    assert(isQCon(q));
1405
1406    if (isCon(q)) {
1407       t_mod   = NIL;
1408       t_tycon = textOf(q);
1409    } else {
1410       t_mod   = qmodOf(q);
1411       t_tycon = qtextOf(q);
1412    }
1413
1414    for (tc = TYCON_BASE_ADDR; 
1415         tc < TYCON_BASE_ADDR+tabTyconSz; tc++) {
1416       if (tabTycon[tc-TYCON_BASE_ADDR].inUse)
1417          if (tycon(tc).text == t_tycon) {
1418             /* Tycon name is ok, but is this the right module? */
1419             if (isNull(t_mod)   /* no module name specified */
1420                 || (nonNull(t_mod) 
1421                     && t_mod == module(tycon(tc).mod).text)
1422                )
1423                return tc;
1424          }
1425    }
1426    return NIL;
1427 }
1428
1429 /* Same deal, except for Names. */
1430 Name findQualNameWithoutConsultingExportList ( QualId q )
1431 {
1432    Name nm;
1433    Text t_mod;
1434    Text t_name;
1435
1436    assert(isQVar(q) || isQCon(q));
1437
1438    if (isCon(q) || isVar(q)) {
1439       t_mod  = NIL;
1440       t_name = textOf(q);
1441    } else {
1442       t_mod  = qmodOf(q);
1443       t_name = qtextOf(q);
1444    }
1445
1446    for (nm = NAME_BASE_ADDR; 
1447         nm < NAME_BASE_ADDR+tabNameSz; nm++) {
1448       if (tabName[nm-NAME_BASE_ADDR].inUse)
1449          if (name(nm).text == t_name) {
1450             /* Name is ok, but is this the right module? */
1451             if (isNull(t_mod)   /* no module name specified */
1452                 || (nonNull(t_mod) 
1453                     && t_mod == module(name(nm).mod).text)
1454                )
1455                return nm;
1456          }
1457    }
1458    return NIL;
1459 }
1460
1461
1462 Tycon findTyconInAnyModule ( Text t )
1463 {
1464    Tycon tc;
1465    for (tc = TYCON_BASE_ADDR; 
1466         tc < TYCON_BASE_ADDR+tabTyconSz; tc++)
1467       if (tabTycon[tc-TYCON_BASE_ADDR].inUse)
1468          if (tycon(tc).text == t) return tc;
1469    return NIL;
1470 }
1471
1472 Class findClassInAnyModule ( Text t )
1473 {
1474    Class cc;
1475    for (cc = CCLASS_BASE_ADDR; 
1476         cc < CCLASS_BASE_ADDR+tabClassSz; cc++)
1477       if (tabClass[cc-CCLASS_BASE_ADDR].inUse)
1478          if (cclass(cc).text == t) return cc;
1479    return NIL;
1480 }
1481
1482 Name findNameInAnyModule ( Text t )
1483 {
1484    Name nm;
1485    for (nm = NAME_BASE_ADDR; 
1486         nm < NAME_BASE_ADDR+tabNameSz; nm++)
1487       if (tabName[nm-NAME_BASE_ADDR].inUse)
1488          if (name(nm).text == t) return nm;
1489    return NIL;
1490 }
1491
1492
1493 /* returns List of QualId */
1494 List getAllKnownTyconsAndClasses ( void )
1495 {
1496    Tycon tc;
1497    Class nw;
1498    List  xs = NIL;
1499    for (tc = TYCON_BASE_ADDR; 
1500         tc < TYCON_BASE_ADDR+tabTyconSz; tc++) {
1501       if (tabTycon[tc-TYCON_BASE_ADDR].inUse) {
1502          /* almost certainly undue paranoia about duplicate avoidance */
1503          QualId q = mkQCon( module(tycon(tc).mod).text, tycon(tc).text );
1504          if (!qualidIsMember(q,xs))
1505             xs = cons ( q, xs );
1506       }
1507    }
1508    for (nw = CCLASS_BASE_ADDR; 
1509         nw < CCLASS_BASE_ADDR+tabClassSz; nw++) {
1510       if (tabClass[nw-CCLASS_BASE_ADDR].inUse) {
1511          QualId q = mkQCon( module(cclass(nw).mod).text, cclass(nw).text );
1512          if (!qualidIsMember(q,xs))
1513             xs = cons ( q, xs );
1514       }
1515    }
1516    return xs;
1517 }
1518
1519 /* Purely for debugging. */
1520 void locateSymbolByName ( Text t )
1521 {
1522    Int i;
1523    for (i = NAME_BASE_ADDR; 
1524         i < NAME_BASE_ADDR+tabNameSz; i++)
1525       if (tabName[i-NAME_BASE_ADDR].inUse && name(i).text == t)
1526          fprintf ( stderr, "name(%d)\n", i-NAME_BASE_ADDR);
1527    for (i = TYCON_BASE_ADDR; 
1528         i < TYCON_BASE_ADDR+tabTyconSz; i++)
1529       if (tabTycon[i-TYCON_BASE_ADDR].inUse && tycon(i).text == t)
1530          fprintf ( stderr, "tycon(%d)\n", i-TYCON_BASE_ADDR);
1531    for (i = CCLASS_BASE_ADDR; 
1532         i < CCLASS_BASE_ADDR+tabClassSz; i++)
1533       if (tabClass[i-CCLASS_BASE_ADDR].inUse && cclass(i).text == t)
1534          fprintf ( stderr, "class(%d)\n", i-CCLASS_BASE_ADDR);
1535 }
1536
1537 /* --------------------------------------------------------------------------
1538  * Control stack:
1539  *
1540  * Various parts of the system use a stack of cells.  Most of the stack
1541  * operations are defined as macros, expanded inline.
1542  * ------------------------------------------------------------------------*/
1543
1544 Cell cellStack[NUM_STACK];          /* Storage for cells on stack          */
1545 StackPtr sp;                        /* stack pointer                       */
1546
1547 Void hugsStackOverflow() {          /* Report stack overflow               */
1548     ERRMSG(0) "Control stack overflow"
1549     EEND;
1550 }
1551
1552
1553 /* --------------------------------------------------------------------------
1554  * Module storage:
1555  *
1556  * A Module represents a user defined module.  
1557  *
1558  * Note: there are now two lookup mechanisms in the system:
1559  *
1560  * 1) The exports from a module are stored in a big list.
1561  *    We resolve qualified names, and import lists by linearly scanning
1562  *    through this list.
1563  *
1564  * 2) Unqualified imports and local definitions for the current module
1565  *    are stored in hash tables (tyconHash and nameHash) or linear lists
1566  *    (classes).
1567  *
1568  * ------------------------------------------------------------------------*/
1569
1570 Module  currentModule;                  /* Module currently being processed*/
1571
1572 Bool isValidModule(m)                   /* is m a legitimate module id?    */
1573 Module m; {
1574     return isModule(m);
1575 }
1576
1577 Module newModule ( Text t )             /* add new module to module table  */
1578 {
1579     Module mod                   = allocNewModule();
1580     module(mod).text             = t;      /* clear new module record      */
1581
1582     module(mod).tycons           = NIL;
1583     module(mod).names            = NIL;
1584     module(mod).classes          = NIL;
1585     module(mod).exports          = NIL;
1586     module(mod).qualImports      = NIL;
1587     module(mod).fake             = FALSE;
1588
1589     module(mod).tree             = NIL;
1590     module(mod).completed        = FALSE;
1591     module(mod).lastStamp        = 0; /* ???? */
1592
1593     module(mod).fromSrc          = TRUE;
1594     module(mod).srcExt           = findText("");
1595     module(mod).uses             = NIL;
1596
1597     module(mod).objName          = findText("");
1598     module(mod).objSize          = 0;
1599
1600     module(mod).object           = NULL;
1601     module(mod).objectExtras     = NULL;
1602     module(mod).objectExtraNames = NIL;
1603     return mod;
1604 }
1605
1606 void nukeModule ( Module m )
1607 {
1608    ObjectCode* oc;
1609    ObjectCode* oc2;
1610    Int         i;
1611 assert(isModule(m));
1612 fprintf(stderr, "NUKEMODULE `%s'\n", textToStr(module(m).text));
1613    oc = module(m).object;
1614    while (oc) {
1615       oc2 = oc->next;
1616       ocFree(oc);
1617       oc = oc2;
1618    }
1619    oc = module(m).objectExtras;
1620    while (oc) {
1621       oc2 = oc->next;
1622       ocFree(oc);
1623       oc = oc2;
1624    }
1625
1626    for (i = NAME_BASE_ADDR; i < NAME_BASE_ADDR+tabNameSz; i++)
1627       if (tabName[i-NAME_BASE_ADDR].inUse && name(i).mod == m) {
1628          if (name(i).itbl) free(name(i).itbl);
1629          name(i).itbl = NULL;
1630          freeName(i);
1631       }
1632
1633    for (i = TYCON_BASE_ADDR; i < TYCON_BASE_ADDR+tabTyconSz; i++)
1634       if (tabTycon[i-TYCON_BASE_ADDR].inUse && tycon(i).mod == m) {
1635          if (tycon(i).itbl) free(tycon(i).itbl);
1636          tycon(i).itbl = NULL;
1637          freeTycon(i);
1638       }
1639
1640    for (i = CCLASS_BASE_ADDR; i < CCLASS_BASE_ADDR+tabClassSz; i++)
1641       if (tabClass[i-CCLASS_BASE_ADDR].inUse) {
1642          if (cclass(i).mod == m) {
1643             freeClass(i);
1644          } else {
1645             List /* Inst */ ins;
1646             List /* Inst */ ins2 = NIL;
1647             for (ins = cclass(i).instances; nonNull(ins); ins=tl(ins))
1648                if (inst(hd(ins)).mod != m) 
1649                   ins2 = cons(hd(ins),ins2);
1650             cclass(i).instances = ins2;
1651          }
1652       }
1653
1654
1655    for (i = INST_BASE_ADDR; i < INST_BASE_ADDR+tabInstSz; i++)
1656       if (tabInst[i-INST_BASE_ADDR].inUse && inst(i).mod == m)
1657          freeInst(i);
1658
1659    freeModule(m);
1660    //for (i = 0; i < TYCONHSZ; i++) tyconHash[i] = 0;
1661    //for (i = 0; i < NAMEHSZ; i++)  nameHash[i] = 0;
1662    //classes = NIL;
1663    //hashSanity();
1664 }
1665
1666 void ppModules ( void )
1667 {
1668    Int i;
1669    fflush(stderr); fflush(stdout);
1670    printf ( "begin MODULES\n" );
1671    for (i  = MODULE_BASE_ADDR+tabModuleSz-1;
1672         i >= MODULE_BASE_ADDR; i--)
1673       if (tabModule[i-MODULE_BASE_ADDR].inUse)
1674          printf ( " %2d: %16s\n",
1675                   i-MODULE_BASE_ADDR, textToStr(module(i).text)
1676                 );
1677    printf ( "end   MODULES\n" );
1678    fflush(stderr); fflush(stdout);
1679 }
1680
1681
1682 Module findModule(t)                    /* locate Module in module table  */
1683 Text t; {
1684     Module m;
1685     for(m = MODULE_BASE_ADDR; 
1686         m < MODULE_BASE_ADDR+tabModuleSz; ++m) {
1687         if (tabModule[m-MODULE_BASE_ADDR].inUse)
1688             if (module(m).text==t)
1689                 return m;
1690     }
1691     return NIL;
1692 }
1693
1694 Module findModid(c)                    /* Find module by name or filename  */
1695 Cell c; {
1696     switch (whatIs(c)) {
1697         case STRCELL   : internal("findModid-STRCELL unimp");
1698         case CONIDCELL : return findModule(textOf(c));
1699         default        : internal("findModid");
1700     }
1701     return NIL;/*NOTUSED*/
1702 }
1703
1704 static local Module findQualifier(t)    /* locate Module in import list   */
1705 Text t; {
1706     Module ms;
1707     for (ms=module(currentModule).qualImports; nonNull(ms); ms=tl(ms)) {
1708         if (textOf(fst(hd(ms)))==t)
1709             return snd(hd(ms));
1710     }
1711     if (module(currentModule).text==t)
1712         return currentModule;
1713     return NIL;
1714 }
1715
1716 Void setCurrModule(m)              /* set lookup tables for current module */
1717 Module m; {
1718     Int i;
1719     assert(isModule(m));
1720     /* fprintf(stderr, "SET CURR MODULE %s\n", textToStr(module(m).text));*/
1721     {List t;
1722      for (t = module(m).names; nonNull(t); t=tl(t))
1723         assert(isName(hd(t)));
1724      for (t = module(m).tycons; nonNull(t); t=tl(t))
1725         assert(isTycon(hd(t)) || isTuple(hd(t)));
1726      for (t = module(m).classes; nonNull(t); t=tl(t))
1727         assert(isClass(hd(t)));
1728     }
1729
1730     currentModule = m; /* This is the only assignment to currentModule */
1731     for (i=0; i<TYCONHSZ; ++i)
1732        tyconHash[RC_T(i)] = NIL;
1733     mapProc(hashTycon,module(m).tycons);
1734     for (i=0; i<NAMEHSZ; ++i)
1735        nameHash[RC_N(i)] = NIL;
1736     mapProc(hashName,module(m).names);
1737     classes = module(m).classes;
1738     hashSanity();
1739 }
1740
1741 Name jrsFindQualName ( Text mn, Text sn )
1742 {
1743    Module m;
1744    List   ns;
1745
1746    for (m = MODULE_BASE_ADDR; 
1747         m < MODULE_BASE_ADDR+tabModuleSz; m++)
1748       if (tabModule[m-MODULE_BASE_ADDR].inUse 
1749           && module(m).text == mn) break;
1750
1751    if (m == MODULE_BASE_ADDR+tabModuleSz) return NIL;
1752    
1753    for (ns = module(m).names; nonNull(ns); ns=tl(ns)) 
1754       if (name(hd(ns)).text == sn) return hd(ns);
1755
1756    return NIL;
1757 }
1758
1759
1760 char* nameFromOPtr ( void* p )
1761 {
1762    int i;
1763    Module m;
1764    for (m = MODULE_BASE_ADDR; 
1765         m < MODULE_BASE_ADDR+tabModuleSz; m++) {
1766       if (tabModule[m-MODULE_BASE_ADDR].inUse && module(m).object) {
1767          char* nm = ocLookupAddr ( module(m).object, p );
1768          if (nm) return nm;
1769       }
1770    }
1771 #  if 0
1772    /* A kludge to assist Win32 debugging; not actually necessary. */
1773    { char* nm = nameFromStaticOPtr(p);
1774      if (nm) return nm;
1775    }
1776 #  endif
1777    return NULL;
1778 }
1779
1780
1781 void* lookupOTabName ( Module m, char* sym )
1782 {
1783    assert(isModule(m));
1784    if (module(m).object)
1785       return ocLookupSym ( module(m).object, sym );
1786    return NULL;
1787 }
1788
1789
1790 void* lookupOExtraTabName ( char* sym )
1791 {
1792    ObjectCode* oc;
1793    Module      m;
1794    for (m = MODULE_BASE_ADDR; 
1795         m < MODULE_BASE_ADDR+tabModuleSz; m++) {
1796       if (tabModule[m-MODULE_BASE_ADDR].inUse)
1797          for (oc = module(m).objectExtras; oc; oc=oc->next) {
1798             void* ad = ocLookupSym ( oc, sym );
1799             if (ad) return ad;
1800          }
1801    }
1802    return NULL;
1803 }
1804
1805
1806 OSectionKind lookupSection ( void* ad )
1807 {
1808    int          i;
1809    Module       m;
1810    ObjectCode*  oc;
1811    OSectionKind sect;
1812
1813    for (m = MODULE_BASE_ADDR; 
1814         m < MODULE_BASE_ADDR+tabModuleSz; m++) {
1815       if (tabModule[m-MODULE_BASE_ADDR].inUse) {
1816          if (module(m).object) {
1817             sect = ocLookupSection ( module(m).object, ad );
1818             if (sect != HUGS_SECTIONKIND_NOINFOAVAIL)
1819                return sect;
1820          }
1821          for (oc = module(m).objectExtras; oc; oc=oc->next) {
1822             sect = ocLookupSection ( oc, ad );
1823             if (sect != HUGS_SECTIONKIND_NOINFOAVAIL)
1824                return sect;
1825          }
1826       }
1827    }
1828    return HUGS_SECTIONKIND_OTHER;
1829 }
1830
1831
1832 /* --------------------------------------------------------------------------
1833  * Heap storage:
1834  *
1835  * Provides a garbage collectable heap for storage of expressions etc.
1836  *
1837  * Now incorporates a flat resource:  A two-space collected extension of
1838  * the heap that provides storage for contiguous arrays of Cell storage,
1839  * cooperating with the garbage collection mechanisms for the main heap.
1840  * ------------------------------------------------------------------------*/
1841
1842 Int     heapSize = DEFAULTHEAP;         /* number of cells in heap         */
1843 Heap    heapFst;                        /* array of fst component of pairs */
1844 Heap    heapSnd;                        /* array of snd component of pairs */
1845 #ifndef GLOBALfst
1846 Heap    heapTopFst;
1847 #endif
1848 #ifndef GLOBALsnd
1849 Heap    heapTopSnd;
1850 #endif
1851 Bool    consGC = TRUE;                  /* Set to FALSE to turn off gc from*/
1852                                         /* C stack; use with extreme care! */
1853 Long    numCells;
1854 Int     numGcs;                         /* number of garbage collections   */
1855 Int     cellsRecovered;                 /* number of cells recovered       */
1856
1857 static  Cell freeList;                  /* free list of unused cells       */
1858 static  Cell lsave, rsave;              /* save components of pair         */
1859
1860 #if GC_STATISTICS
1861
1862 static Int markCount, stackRoots;
1863
1864 #define initStackRoots() stackRoots = 0
1865 #define recordStackRoot() stackRoots++
1866
1867 #define startGC()       \
1868     if (gcMessages) {   \
1869         Printf("\n");   \
1870         fflush(stdout); \
1871     }
1872 #define endGC()         \
1873     if (gcMessages) {   \
1874         Printf("\n");   \
1875         fflush(stdout); \
1876     }
1877
1878 #define start()      markCount = 0
1879 #define end(thing,rs) \
1880     if (gcMessages) { \
1881         Printf("GC: %-18s: %4d cells, %4d roots.\n", thing, markCount, rs); \
1882         fflush(stdout); \
1883     }
1884 #define recordMark() markCount++
1885
1886 #else /* !GC_STATISTICS */
1887
1888 #define startGC()
1889 #define endGC()
1890
1891 #define initStackRoots()
1892 #define recordStackRoot()
1893
1894 #define start()   
1895 #define end(thing,root) 
1896 #define recordMark() 
1897
1898 #endif /* !GC_STATISTICS */
1899
1900 Cell pair(l,r)                          /* Allocate pair (l, r) from       */
1901 Cell l, r; {                            /* heap, garbage collecting first  */
1902     Cell c = freeList;                  /* if necessary ...                */
1903
1904     if (isNull(c)) {
1905         lsave = l;
1906         rsave = r;
1907         garbageCollect();
1908         l     = lsave;
1909         lsave = NIL;
1910         r     = rsave;
1911         rsave = NIL;
1912         c     = freeList;
1913     }
1914     freeList = snd(freeList);
1915     fst(c)   = l;
1916     snd(c)   = r;
1917     numCells++;
1918     return c;
1919 }
1920
1921 static Int *marks;
1922 static Int marksSize;
1923
1924 Cell markExpr(c)                        /* External interface to markCell  */
1925 Cell c; {
1926     return isGenPair(c) ? markCell(c) : c;
1927 }
1928
1929 static Cell local markCell(c)           /* Traverse part of graph marking  */
1930 Cell c; {                               /* cells reachable from given root */
1931                                         /* markCell(c) is only called if c */
1932                                         /* is a pair                       */
1933     {   register int place = placeInSet(c);
1934         register int mask  = maskInSet(c);
1935         if (marks[place]&mask)
1936             return c;
1937         else {
1938             marks[place] |= mask;
1939             recordMark();
1940         }
1941     }
1942
1943     /* STACK_CHECK: Avoid stack overflows during recursive marking. */
1944     if (isGenPair(fst(c))) {
1945         STACK_CHECK
1946         fst(c) = markCell(fst(c));
1947         markSnd(c);
1948     }
1949     else if (isNull(fst(c)) || isTagPtr(fst(c))) {
1950         STACK_CHECK
1951         markSnd(c);
1952     }
1953
1954     return c;
1955 }
1956
1957 static Void local markSnd(c)            /* Variant of markCell used to     */
1958 Cell c; {                               /* update snd component of cell    */
1959     Cell t;                             /* using tail recursion            */
1960
1961 ma: t = c;                              /* Keep pointer to original pair   */
1962     c = snd(c);
1963     if (!isPair(c))
1964         return;
1965
1966     {   register int place = placeInSet(c);
1967         register int mask  = maskInSet(c);
1968         if (marks[place]&mask)
1969             return;
1970         else {
1971             marks[place] |= mask;
1972             recordMark();
1973         }
1974     }
1975
1976     if (isGenPair(fst(c))) {
1977         fst(c) = markCell(fst(c));
1978         goto ma;
1979     }
1980     else if (isNull(fst(c)) || isTagPtr(fst(c)))
1981         goto ma;
1982     return;
1983 }
1984
1985 Void markWithoutMove(n)                 /* Garbage collect cell at n, as if*/
1986 Cell n; {                               /* it was a cell ref, but don't    */
1987                                         /* move cell so we don't have      */
1988                                         /* to modify the stored value of n */
1989     if (isGenPair(n)) {
1990         recordStackRoot();
1991         markCell(n); 
1992     }
1993 }
1994
1995 Void garbageCollect()     {             /* Run garbage collector ...       */
1996                                         /* disable break checking          */
1997     Int i,j;
1998     register Int mask;
1999     register Int place;
2000     Int      recovered;
2001     jmp_buf  regs;                      /* save registers on stack         */
2002     HugsBreakAction oldBrk
2003        = setBreakAction ( HugsIgnoreBreak );
2004 fprintf ( stderr, "wa-hey!  garbage collection!  too difficult!  bye!\n" );
2005 exit(0);
2006     setjmp(regs);
2007
2008     gcStarted();
2009     for (i=0; i<marksSize; ++i)         /* initialise mark set to empty    */
2010         marks[i] = 0;
2011
2012     everybody(MARK);                    /* Mark all components of system   */
2013
2014     gcScanning();                       /* scan mark set                   */
2015     mask      = 1;
2016     place     = 0;
2017     recovered = 0;
2018     j         = 0;
2019
2020     freeList = NIL;
2021     for (i=1; i<=heapSize; i++) {
2022         if ((marks[place] & mask) == 0) {
2023             snd(-i)  = freeList;
2024             fst(-i)  = FREECELL;
2025             freeList = -i;
2026             recovered++;
2027         }
2028         mask <<= 1;
2029         if (++j == bitsPerWord) {
2030             place++;
2031             mask = 1;
2032             j    = 0;
2033         }
2034     }
2035
2036     gcRecovered(recovered);
2037     setBreakAction ( oldBrk );
2038
2039     everybody(GCDONE);
2040
2041     /* can only return if freeList is nonempty on return. */
2042     if (recovered<minRecovery || isNull(freeList)) {
2043         ERRMSG(0) "Garbage collection fails to reclaim sufficient space"
2044         EEND;
2045     }
2046     cellsRecovered = recovered;
2047 }
2048
2049 /* --------------------------------------------------------------------------
2050  * Code for saving last expression entered:
2051  *
2052  * This is a little tricky because some text values (e.g. strings or variable
2053  * names) may not be defined or have the same value when the expression is
2054  * recalled.  These text values are therefore saved in the top portion of
2055  * the text table.
2056  * ------------------------------------------------------------------------*/
2057
2058 static Cell lastExprSaved;              /* last expression to be saved     */
2059
2060 Void setLastExpr(e)                     /* save expression for later recall*/
2061 Cell e; {
2062     lastExprSaved = NIL;                /* in case attempt to save fails   */
2063     savedText     = TEXT_SIZE;
2064     lastExprSaved = lowLevelLastIn(e);
2065 }
2066
2067 static Cell local lowLevelLastIn(c)     /* Duplicate expression tree (i.e. */
2068 Cell c; {                               /* acyclic graph) for later recall */
2069     if (isPair(c)) {                    /* Duplicating any text strings    */
2070         if (isTagNonPtr(fst(c)))        /* in case these are lost at some  */
2071             switch (fst(c)) {           /* point before the expr is reused */
2072                 case VARIDCELL :
2073                 case VAROPCELL :
2074                 case DICTVAR   :
2075                 case CONIDCELL :
2076                 case CONOPCELL :
2077                 case STRCELL   : return pair(fst(c),saveText(textOf(c)));
2078                 default        : return pair(fst(c),snd(c));
2079             }
2080         else
2081             return pair(lowLevelLastIn(fst(c)),lowLevelLastIn(snd(c)));
2082     }
2083 #if TREX
2084     else if (isExt(c))
2085         return pair(EXTCOPY,saveText(extText(c)));
2086 #endif
2087     else
2088         return c;
2089 }
2090
2091 Cell getLastExpr() {                    /* recover previously saved expr   */
2092     return lowLevelLastOut(lastExprSaved);
2093 }
2094
2095 static Cell local lowLevelLastOut(c)    /* As with lowLevelLastIn() above  */
2096 Cell c; {                               /* except that Cells refering to   */
2097     if (isPair(c)) {                    /* Text values are restored to     */
2098         if (isTagNonPtr(fst(c)))        /* appropriate values              */
2099             switch (fst(c)) {
2100                 case VARIDCELL :
2101                 case VAROPCELL :
2102                 case DICTVAR   :
2103                 case CONIDCELL :
2104                 case CONOPCELL :
2105                 case STRCELL   : return pair(fst(c),
2106                                              findText(text+intValOf(c)));
2107 #if TREX
2108                 case EXTCOPY   : return mkExt(findText(text+intValOf(c)));
2109 #endif
2110                 default        : return pair(fst(c),snd(c));
2111             }
2112         else
2113             return pair(lowLevelLastOut(fst(c)),lowLevelLastOut(snd(c)));
2114     }
2115     else
2116         return c;
2117 }
2118
2119 /* --------------------------------------------------------------------------
2120  * Miscellaneous operations on heap cells:
2121  * ------------------------------------------------------------------------*/
2122
2123 Cell whatIs ( register Cell c )
2124 {
2125     if (isPair(c)) {
2126         register Cell fstc = fst(c);
2127         return isTag(fstc) ? fstc : AP;
2128     }
2129     if (isOffset(c))           return OFFSET;
2130     if (isChar(c))             return CHARCELL;
2131     if (isInt(c))              return INTCELL;
2132     if (isName(c))             return NAME;
2133     if (isTycon(c))            return TYCON;
2134     if (isTuple(c))            return TUPLE;
2135     if (isClass(c))            return CLASS;
2136     if (isInst(c))             return INSTANCE;
2137     if (isModule(c))           return MODULE;
2138     if (isText(c))             return TEXTCELL;
2139     if (isInventedVar(c))      return INVAR;
2140     if (isInventedDictVar(c))  return INDVAR;
2141     if (isSpec(c))             return c;
2142     if (isNull(c))             return c;
2143     fprintf ( stderr, "whatIs: unknown %d\n", c );
2144     internal("whatIs");
2145 }
2146
2147
2148 #if 0
2149 Cell whatIs(c)                         /* identify type of cell            */
2150 register Cell c; {
2151     if (isPair(c)) {
2152         register Cell fstc = fst(c);
2153         return isTag(fstc) ? fstc : AP;
2154     }
2155     if (c<OFFMIN)    return c;
2156 #if TREX
2157     if (isExt(c))    return EXT;
2158 #endif
2159     if (c>=INTMIN)   return INTCELL;
2160
2161     if (c>=NAMEMIN){if (c>=CLASSMIN)   {if (c>=CHARMIN) return CHARCELL;
2162                                         else            return CLASS;}
2163                     else                if (c>=INSTMIN) return INSTANCE;
2164                                         else            return NAME;}
2165     else            if (c>=MODMIN)     {if (c>=TYCMIN)  return isTuple(c) ? TUPLE : TYCON;
2166                                         else            return MODULE;}
2167                     else                if (c>=OFFMIN)  return OFFSET;
2168 #if TREX
2169                                         else            return (c>=EXTMIN) ?
2170                                                                 EXT : TUPLE;
2171 #else
2172                                         else            return TUPLE;
2173 #endif
2174
2175
2176 /*  if (isPair(c)) {
2177         register Cell fstc = fst(c);
2178         return isTag(fstc) ? fstc : AP;
2179     }
2180     if (c>=INTMIN)   return INTCELL;
2181     if (c>=CHARMIN)  return CHARCELL;
2182     if (c>=CLASSMIN) return CLASS;
2183     if (c>=INSTMIN)  return INSTANCE;
2184     if (c>=NAMEMIN)  return NAME;
2185     if (c>=TYCMIN)   return TYCON;
2186     if (c>=MODMIN)   return MODULE;
2187     if (c>=OFFMIN)   return OFFSET;
2188 #if TREX
2189     if (c>=EXTMIN)   return EXT;
2190 #endif
2191     if (c>=TUPMIN)   return TUPLE;
2192     return c;*/
2193 }
2194 #endif
2195
2196
2197 /* A very, very simple printer.
2198  * Output is uglier than from printExp - but the printer is more
2199  * robust and can be used on any data structure irrespective of
2200  * its type.
2201  */
2202 Void print ( Cell c, Int depth )
2203 {
2204     if (0 == depth) {
2205         Printf("...");
2206     }
2207     else if (isNull(c)) {
2208        Printf("NIL");
2209     }
2210     else if (isTagPtr(c)) {
2211         Printf("TagP(%d)", c);
2212     }
2213     else if (isTagNonPtr(c)) {
2214         Printf("TagNP(%d)", c);
2215     }
2216     else if (isSpec(c)) {
2217         Printf("TagS(%d)", c);
2218     }
2219     else if (isText(c)) {
2220         Printf("text(%d)=\"%s\"",c-TEXT_BASE_ADDR,textToStr(c));
2221     }
2222     else if (isInventedVar(c)) {
2223         Printf("invented(%d)", c-INVAR_BASE_ADDR);
2224     }
2225     else if (isInventedDictVar(c)) {
2226         Printf("inventedDict(%d)",c-INDVAR_BASE_ADDR);
2227     }
2228     else {
2229         Int tag = whatIs(c);
2230         switch (tag) {
2231         case AP: 
2232                 Putchar('(');
2233                 print(fst(c), depth-1);
2234                 Putchar(',');
2235                 print(snd(c), depth-1);
2236                 Putchar(')');
2237                 break;
2238         case FREECELL:
2239                 Printf("free(%d)", c);
2240                 break;
2241         case INTCELL:
2242                 Printf("int(%d)", intOf(c));
2243                 break;
2244         case BIGCELL:
2245                 Printf("bignum(%s)", bignumToString(c));
2246                 break;
2247         case CHARCELL:
2248                 Printf("char('%c')", charOf(c));
2249                 break;
2250         case PTRCELL: 
2251                 Printf("ptr(%p)",ptrOf(c));
2252                 break;
2253         case CLASS:
2254                 Printf("class(%d)", c-CCLASS_BASE_ADDR);
2255                 Printf("=\"%s\"", textToStr(cclass(c).text));
2256                 break;
2257         case INSTANCE:
2258                 Printf("instance(%d)", c - INST_BASE_ADDR);
2259                 break;
2260         case NAME:
2261                 Printf("name(%d)", c-NAME_BASE_ADDR);
2262                 Printf("=\"%s\"", textToStr(name(c).text));
2263                 break;
2264         case TYCON:
2265                 Printf("tycon(%d)", c-TYCON_BASE_ADDR);
2266                 Printf("=\"%s\"", textToStr(tycon(c).text));
2267                 break;
2268         case MODULE:
2269                 Printf("module(%d)", c - MODULE_BASE_ADDR);
2270                 Printf("=\"%s\"", textToStr(module(c).text));
2271                 break;
2272         case OFFSET:
2273                 Printf("Offset %d", offsetOf(c));
2274                 break;
2275         case TUPLE:
2276                 Printf("%s", textToStr(ghcTupleText(c)));
2277                 break;
2278         case POLYTYPE:
2279                 Printf("Polytype");
2280                 print(snd(c),depth-1);
2281                 break;
2282         case QUAL:
2283                 Printf("Qualtype");
2284                 print(snd(c),depth-1);
2285                 break;
2286         case RANK2:
2287                 Printf("Rank2(");
2288                 if (isPair(snd(c)) && isInt(fst(snd(c)))) {
2289                     Printf("%d ", intOf(fst(snd(c))));
2290                     print(snd(snd(c)),depth-1);
2291                 } else {
2292                     print(snd(c),depth-1);
2293                 }
2294                 Printf(")");
2295                 break;
2296         case WILDCARD:
2297                 Printf("_");
2298                 break;
2299         case STAR:
2300                 Printf("STAR");
2301                 break;
2302         case DOTDOT:
2303                 Printf("DOTDOT");
2304                 break;
2305         case DICTVAR:
2306                 Printf("{dict %d}",textOf(c));
2307                 break;
2308         case VARIDCELL:
2309         case VAROPCELL:
2310         case CONIDCELL:
2311         case CONOPCELL:
2312                 Printf("{id %s}",textToStr(textOf(c)));
2313                 break;
2314 #if IPARAM
2315           case IPCELL :
2316               Printf("{ip %s}",textToStr(textOf(c)));
2317               break;
2318           case IPVAR :
2319               Printf("?%s",textToStr(textOf(c)));
2320               break;
2321 #endif
2322         case QUALIDENT:
2323                 Printf("{qid %s.%s}",textToStr(qmodOf(c)),textToStr(qtextOf(c)));
2324                 break;
2325         case LETREC:
2326                 Printf("LetRec(");
2327                 print(fst(snd(c)),depth-1);
2328                 Putchar(',');
2329                 print(snd(snd(c)),depth-1);
2330                 Putchar(')');
2331                 break;
2332         case LAMBDA:
2333                 Printf("Lambda(");
2334                 print(snd(c),depth-1);
2335                 Putchar(')');
2336                 break;
2337         case FINLIST:
2338                 Printf("FinList(");
2339                 print(snd(c),depth-1);
2340                 Putchar(')');
2341                 break;
2342         case COMP:
2343                 Printf("Comp(");
2344                 print(fst(snd(c)),depth-1);
2345                 Putchar(',');
2346                 print(snd(snd(c)),depth-1);
2347                 Putchar(')');
2348                 break;
2349         case ASPAT:
2350                 Printf("AsPat(");
2351                 print(fst(snd(c)),depth-1);
2352                 Putchar(',');
2353                 print(snd(snd(c)),depth-1);
2354                 Putchar(')');
2355                 break;
2356         case FROMQUAL:
2357                 Printf("FromQual(");
2358                 print(fst(snd(c)),depth-1);
2359                 Putchar(',');
2360                 print(snd(snd(c)),depth-1);
2361                 Putchar(')');
2362                 break;
2363         case STGVAR:
2364                 Printf("StgVar%d=",-c);
2365                 print(snd(c), depth-1);
2366                 break;
2367         case STGAPP:
2368                 Printf("StgApp(");
2369                 print(fst(snd(c)),depth-1);
2370                 Putchar(',');
2371                 print(snd(snd(c)),depth-1);
2372                 Putchar(')');
2373                 break;
2374         case STGPRIM:
2375                 Printf("StgPrim(");
2376                 print(fst(snd(c)),depth-1);
2377                 Putchar(',');
2378                 print(snd(snd(c)),depth-1);
2379                 Putchar(')');
2380                 break;
2381         case STGCON:
2382                 Printf("StgCon(");
2383                 print(fst(snd(c)),depth-1);
2384                 Putchar(',');
2385                 print(snd(snd(c)),depth-1);
2386                 Putchar(')');
2387                 break;
2388         case PRIMCASE:
2389                 Printf("PrimCase(");
2390                 print(fst(snd(c)),depth-1);
2391                 Putchar(',');
2392                 print(snd(snd(c)),depth-1);
2393                 Putchar(')');
2394                 break;
2395         case DICTAP:
2396                 Printf("(DICTAP,");
2397                 print(snd(c),depth-1);
2398                 Putchar(')');
2399                 break;
2400         case UNBOXEDTUP:
2401                 Printf("(UNBOXEDTUP,");
2402                 print(snd(c),depth-1);
2403                 Putchar(')');
2404                 break;
2405         case ZTUP2:
2406                 Printf("<ZPair ");
2407                 print(zfst(c),depth-1);
2408                 Putchar(' ');
2409                 print(zsnd(c),depth-1);
2410                 Putchar('>');
2411                 break;
2412         case ZTUP3:
2413                 Printf("<ZTriple ");
2414                 print(zfst3(c),depth-1);
2415                 Putchar(' ');
2416                 print(zsnd3(c),depth-1);
2417                 Putchar(' ');
2418                 print(zthd3(c),depth-1);
2419                 Putchar('>');
2420                 break;
2421         case BANG:
2422                 Printf("(BANG,");
2423                 print(snd(c),depth-1);
2424                 Putchar(')');
2425                 break;
2426         default:
2427                 if (isTagNonPtr(tag)) {
2428                     Printf("(TagNP=%d,%d)", c, tag);
2429                 } else if (isTagPtr(tag)) {
2430                     Printf("(TagP=%d,",tag);
2431                     print(snd(c), depth-1);
2432                     Putchar(')');
2433                     break;
2434                 } else if (c == tag) {
2435                     Printf("Tag(%d)", c);
2436                 } else {
2437                     Printf("Tag(%d)=%d", c, tag);
2438                 }
2439                 break;
2440         }
2441     }
2442     FlushStdout();
2443 }
2444
2445
2446 Bool isVar(c)                           /* is cell a VARIDCELL/VAROPCELL ? */
2447 Cell c; {                               /* also recognises DICTVAR cells   */
2448     return isPair(c) &&
2449                (fst(c)==VARIDCELL || fst(c)==VAROPCELL || fst(c)==DICTVAR);
2450 }
2451
2452 Bool isCon(c)                          /* is cell a CONIDCELL/CONOPCELL ?  */
2453 Cell c; {
2454     return isPair(c) && (fst(c)==CONIDCELL || fst(c)==CONOPCELL);
2455 }
2456
2457 Bool isQVar(c)                        /* is cell a [un]qualified varop/id? */
2458 Cell c; {
2459     if (!isPair(c)) return FALSE;
2460     switch (fst(c)) {
2461         case VARIDCELL  :
2462         case VAROPCELL  : return TRUE;
2463
2464         case QUALIDENT  : return isVar(snd(snd(c)));
2465
2466         default         : return FALSE;
2467     }
2468 }
2469
2470 Bool isQCon(c)                         /*is cell a [un]qualified conop/id? */
2471 Cell c; {
2472     if (!isPair(c)) return FALSE;
2473     switch (fst(c)) {
2474         case CONIDCELL  :
2475         case CONOPCELL  : return TRUE;
2476
2477         case QUALIDENT  : return isCon(snd(snd(c)));
2478
2479         default         : return FALSE;
2480     }
2481 }
2482
2483 Bool isQualIdent(c)                    /* is cell a qualified identifier?  */
2484 Cell c; {
2485     return isPair(c) && (fst(c)==QUALIDENT);
2486 }
2487
2488 Bool eqQualIdent ( QualId c1, QualId c2 )
2489 {
2490    assert(isQualIdent(c1));
2491    if (!isQualIdent(c2)) {
2492    assert(isQualIdent(c2));
2493    }
2494    return qmodOf(c1)==qmodOf(c2) &&
2495           qtextOf(c1)==qtextOf(c2);
2496 }
2497
2498 Bool isIdent(c)                        /* is cell an identifier?           */
2499 Cell c; {
2500     if (!isPair(c)) return FALSE;
2501     switch (fst(c)) {
2502         case VARIDCELL  :
2503         case VAROPCELL  :
2504         case CONIDCELL  :
2505         case CONOPCELL  : return TRUE;
2506
2507         case QUALIDENT  : return TRUE;
2508
2509         default         : return FALSE;
2510     }
2511 }
2512
2513 Bool isInt(c)                          /* cell holds integer value?        */
2514 Cell c; {
2515     return isSmall(c) || (isPair(c) && fst(c)==INTCELL);
2516 }
2517
2518 Int intOf(c)                           /* find integer value of cell?      */
2519 Cell c; {
2520     assert(isInt(c));
2521     return isPair(c) ? (Int)(snd(c)) : (Int)(c-SMALL_INT_ZERO);
2522 }
2523
2524 Cell mkInt(n)                          /* make cell representing integer   */
2525 Int n; {
2526     return (SMALL_INT_MIN    <= SMALL_INT_ZERO+n &&
2527             SMALL_INT_ZERO+n <= SMALL_INT_MAX)
2528            ? SMALL_INT_ZERO+n
2529            : pair(INTCELL,n);
2530 }
2531
2532 #if SIZEOF_VOID_P == SIZEOF_INT
2533
2534 typedef union {Int i; Ptr p;} IntOrPtr;
2535
2536 Cell mkPtr(p)
2537 Ptr p;
2538 {
2539     IntOrPtr x;
2540     x.p = p;
2541     return pair(PTRCELL,x.i);
2542 }
2543
2544 Ptr ptrOf(c)
2545 Cell c;
2546 {
2547     IntOrPtr x;
2548     assert(fst(c) == PTRCELL);
2549     x.i = snd(c);
2550     return x.p;
2551 }
2552
2553 Cell mkCPtr(p)
2554 Ptr p;
2555 {
2556     IntOrPtr x;
2557     x.p = p;
2558     return pair(CPTRCELL,x.i);
2559 }
2560
2561 Ptr cptrOf(c)
2562 Cell c;
2563 {
2564     IntOrPtr x;
2565     assert(fst(c) == CPTRCELL);
2566     x.i = snd(c);
2567     return x.p;
2568 }
2569
2570 #elif SIZEOF_VOID_P == 2*SIZEOF_INT
2571
2572 typedef union {struct {Int i1; Int i2;} i; Ptr p;} IntOrPtr;
2573
2574 Cell mkPtr(p)
2575 Ptr p;
2576 {
2577     IntOrPtr x;
2578     x.p = p;
2579     return pair(PTRCELL,pair(mkInt(x.i.i1),mkInt(x.i.i2)));
2580 }
2581
2582 Ptr ptrOf(c)
2583 Cell c;
2584 {
2585     IntOrPtr x;
2586     assert(fst(c) == PTRCELL);
2587     x.i.i1 = intOf(fst(snd(c)));
2588     x.i.i2 = intOf(snd(snd(c)));
2589     return x.p;
2590 }
2591
2592 Cell mkCPtr(p)
2593 Ptr p;
2594 {
2595     IntOrPtr x;
2596     x.p = p;
2597     return pair(CPTRCELL,pair(mkInt(x.i.i1),mkInt(x.i.i2)));
2598 }
2599
2600 Ptr cptrOf(c)
2601 Cell c;
2602 {
2603     IntOrPtr x;
2604     assert(fst(c) == CPTRCELL);
2605     x.i.i1 = intOf(fst(snd(c)));
2606     x.i.i2 = intOf(snd(snd(c)));
2607     return x.p;
2608 }
2609
2610 #else
2611
2612 #error "Can't implement mkPtr/ptrOf on this architecture."
2613
2614 #endif
2615
2616
2617 String stringNegate( s )
2618 String s;
2619 {
2620     if (s[0] == '-') {
2621         return &s[1];
2622     } else {
2623         static char t[100];
2624         t[0] = '-';
2625         strcpy(&t[1],s);  /* ToDo: use strncpy instead */
2626         return t;
2627     }
2628 }
2629
2630 /* --------------------------------------------------------------------------
2631  * List operations:
2632  * ------------------------------------------------------------------------*/
2633
2634 Int length(xs)                         /* calculate length of list xs      */
2635 List xs; {
2636     Int n = 0;
2637     for (; nonNull(xs); ++n)
2638         xs = tl(xs);
2639     return n;
2640 }
2641
2642 List appendOnto(xs,ys)                 /* Destructively prepend xs onto    */
2643 List xs, ys; {                         /* ys by modifying xs ...           */
2644     if (isNull(xs))
2645         return ys;
2646     else {
2647         List zs = xs;
2648         while (nonNull(tl(zs)))
2649             zs = tl(zs);
2650         tl(zs) = ys;
2651         return xs;
2652     }
2653 }
2654
2655 List dupOnto(xs,ys)      /* non-destructively prepend xs backwards onto ys */
2656 List xs; 
2657 List ys; {
2658     for (; nonNull(xs); xs=tl(xs))
2659         ys = cons(hd(xs),ys);
2660     return ys;
2661 }
2662
2663 List dupListOnto(xs,ys)              /* Duplicate spine of list xs onto ys */
2664 List xs;
2665 List ys; {
2666     return revOnto(dupOnto(xs,NIL),ys);
2667 }
2668
2669 List dupList(xs)                       /* Duplicate spine of list xs       */
2670 List xs; {
2671     List ys = NIL;
2672     for (; nonNull(xs); xs=tl(xs))
2673         ys = cons(hd(xs),ys);
2674     return rev(ys);
2675 }
2676
2677 List revOnto(xs,ys)                    /* Destructively reverse elements of*/
2678 List xs, ys; {                         /* list xs onto list ys...          */
2679     Cell zs;
2680
2681     while (nonNull(xs)) {
2682         zs     = tl(xs);
2683         tl(xs) = ys;
2684         ys     = xs;
2685         xs     = zs;
2686     }
2687     return ys;
2688 }
2689
2690 QualId qualidIsMember ( QualId q, List xs )
2691 {
2692    for (; nonNull(xs); xs=tl(xs)) {
2693       if (eqQualIdent(q, hd(xs)))
2694          return hd(xs);
2695    }
2696    return NIL;
2697 }  
2698
2699 Cell varIsMember(t,xs)                 /* Test if variable is a member of  */
2700 Text t;                                /* given list of variables          */
2701 List xs; {
2702     for (; nonNull(xs); xs=tl(xs))
2703         if (t==textOf(hd(xs)))
2704             return hd(xs);
2705     return NIL;
2706 }
2707
2708 Name nameIsMember(t,ns)                 /* Test if name with text t is a   */
2709 Text t;                                 /* member of list of names xs      */
2710 List ns; {
2711     for (; nonNull(ns); ns=tl(ns))
2712         if (t==name(hd(ns)).text)
2713             return hd(ns);
2714     return NIL;
2715 }
2716
2717 Cell intIsMember(n,xs)                 /* Test if integer n is member of   */
2718 Int  n;                                /* given list of integers           */
2719 List xs; {
2720     for (; nonNull(xs); xs=tl(xs))
2721         if (n==intOf(hd(xs)))
2722             return hd(xs);
2723     return NIL;
2724 }
2725
2726 Cell cellIsMember(x,xs)                /* Test for membership of specific  */
2727 Cell x;                                /* cell x in list xs                */
2728 List xs; {
2729     for (; nonNull(xs); xs=tl(xs))
2730         if (x==hd(xs))
2731             return hd(xs);
2732     return NIL;
2733 }
2734
2735 Cell cellAssoc(c,xs)                   /* Lookup cell in association list  */
2736 Cell c;         
2737 List xs; {
2738     for (; nonNull(xs); xs=tl(xs))
2739         if (c==fst(hd(xs)))
2740             return hd(xs);
2741     return NIL;
2742 }
2743
2744 Cell cellRevAssoc(c,xs)                /* Lookup cell in range of          */
2745 Cell c;                                /* association lists                */
2746 List xs; {
2747     for (; nonNull(xs); xs=tl(xs))
2748         if (c==snd(hd(xs)))
2749             return hd(xs);
2750     return NIL;
2751 }
2752
2753 List replicate(n,x)                     /* create list of n copies of x    */
2754 Int n;
2755 Cell x; {
2756     List xs=NIL;
2757     while (0<n--)
2758         xs = cons(x,xs);
2759     return xs;
2760 }
2761
2762 List diffList(from,take)               /* list difference: from\take       */
2763 List from, take; {                     /* result contains all elements of  */
2764     List result = NIL;                 /* `from' not appearing in `take'   */
2765
2766     while (nonNull(from)) {
2767         List next = tl(from);
2768         if (!cellIsMember(hd(from),take)) {
2769             tl(from) = result;
2770             result   = from;
2771         }
2772         from = next;
2773     }
2774     return rev(result);
2775 }
2776
2777 List deleteCell(xs, y)                  /* copy xs deleting pointers to y  */
2778 List xs;
2779 Cell y; {
2780     List result = NIL; 
2781     for(;nonNull(xs);xs=tl(xs)) {
2782         Cell x = hd(xs);
2783         if (x != y) {
2784             result=cons(x,result);
2785         }
2786     }
2787     return rev(result);
2788 }
2789
2790 List take(n,xs)                         /* destructively truncate list to  */
2791 Int  n;                                 /* specified length                */
2792 List xs; {
2793     List ys = xs;
2794
2795     if (n==0)
2796         return NIL;
2797     while (1<n-- && nonNull(xs))
2798         xs = tl(xs);
2799     if (nonNull(xs))
2800         tl(xs) = NIL;
2801     return ys;
2802 }
2803
2804 List splitAt(n,xs)                      /* drop n things from front of list*/
2805 Int  n;       
2806 List xs; {
2807     for(; n>0; --n) {
2808         xs = tl(xs);
2809     }
2810     return xs;
2811 }
2812
2813 Cell nth(n,xs)                          /* extract n'th element of list    */
2814 Int  n;
2815 List xs; {
2816     for(; n>0 && nonNull(xs); --n, xs=tl(xs)) {
2817     }
2818     if (isNull(xs))
2819         internal("nth");
2820     return hd(xs);
2821 }
2822
2823 List removeCell(x,xs)                   /* destructively remove cell from  */
2824 Cell x;                                 /* list                            */
2825 List xs; {
2826     if (nonNull(xs)) {
2827         if (hd(xs)==x)
2828             return tl(xs);              /* element at front of list        */
2829         else {
2830             List prev = xs;
2831             List curr = tl(xs);
2832             for (; nonNull(curr); prev=curr, curr=tl(prev))
2833                 if (hd(curr)==x) {
2834                     tl(prev) = tl(curr);
2835                     return xs;          /* element in middle of list       */
2836                 }
2837         }
2838     }
2839     return xs;                          /* here if element not found       */
2840 }
2841
2842 List nubList(xs)                        /* nuke dups in list               */
2843 List xs; {                              /* non destructive                 */
2844    List outs = NIL;
2845    for (; nonNull(xs); xs=tl(xs))
2846       if (isNull(cellIsMember(hd(xs),outs)))
2847          outs = cons(hd(xs),outs);
2848    outs = rev(outs);
2849    return outs;
2850 }
2851
2852
2853 /* --------------------------------------------------------------------------
2854  * Tagged tuples (experimental)
2855  * ------------------------------------------------------------------------*/
2856
2857 static void z_tag_check ( Cell x, int tag, char* caller )
2858 {
2859    char buf[100];
2860    if (isNull(x)) {
2861       sprintf(buf,"z_tag_check(%s): null\n", caller);
2862       internal(buf);
2863    }
2864    if (whatIs(x) != tag) {
2865       sprintf(buf, 
2866           "z_tag_check(%s): tag was %d, expected %d\n",
2867           caller, whatIs(x), tag );
2868       internal(buf);
2869    }  
2870 }
2871
2872 Cell zpair ( Cell x1, Cell x2 )
2873 { return ap(ZTUP2,ap(x1,x2)); }
2874 Cell zfst ( Cell zpair )
2875 { z_tag_check(zpair,ZTUP2,"zfst"); return fst( snd(zpair) ); }
2876 Cell zsnd ( Cell zpair )
2877 { z_tag_check(zpair,ZTUP2,"zsnd"); return snd( snd(zpair) ); }
2878
2879 Cell ztriple ( Cell x1, Cell x2, Cell x3 )
2880 { return ap(ZTUP3,ap(x1,ap(x2,x3))); }
2881 Cell zfst3 ( Cell zpair )
2882 { z_tag_check(zpair,ZTUP3,"zfst3"); return fst( snd(zpair) ); }
2883 Cell zsnd3 ( Cell zpair )
2884 { z_tag_check(zpair,ZTUP3,"zsnd3"); return fst(snd( snd(zpair) )); }
2885 Cell zthd3 ( Cell zpair )
2886 { z_tag_check(zpair,ZTUP3,"zthd3"); return snd(snd( snd(zpair) )); }
2887
2888 Cell z4ble ( Cell x1, Cell x2, Cell x3, Cell x4 )
2889 { return ap(ZTUP4,ap(x1,ap(x2,ap(x3,x4)))); }
2890 Cell zsel14 ( Cell zpair )
2891 { z_tag_check(zpair,ZTUP4,"zsel14"); return fst( snd(zpair) ); }
2892 Cell zsel24 ( Cell zpair )
2893 { z_tag_check(zpair,ZTUP4,"zsel24"); return fst(snd( snd(zpair) )); }
2894 Cell zsel34 ( Cell zpair )
2895 { z_tag_check(zpair,ZTUP4,"zsel34"); return fst(snd(snd( snd(zpair) ))); }
2896 Cell zsel44 ( Cell zpair )
2897 { z_tag_check(zpair,ZTUP4,"zsel44"); return snd(snd(snd( snd(zpair) ))); }
2898
2899 Cell z5ble ( Cell x1, Cell x2, Cell x3, Cell x4, Cell x5 )
2900 { return ap(ZTUP5,ap(x1,ap(x2,ap(x3,ap(x4,x5))))); }
2901 Cell zsel15 ( Cell zpair )
2902 { z_tag_check(zpair,ZTUP5,"zsel15"); return fst( snd(zpair) ); }
2903 Cell zsel25 ( Cell zpair )
2904 { z_tag_check(zpair,ZTUP5,"zsel25"); return fst(snd( snd(zpair) )); }
2905 Cell zsel35 ( Cell zpair )
2906 { z_tag_check(zpair,ZTUP5,"zsel35"); return fst(snd(snd( snd(zpair) ))); }
2907 Cell zsel45 ( Cell zpair )
2908 { z_tag_check(zpair,ZTUP5,"zsel45"); return fst(snd(snd(snd( snd(zpair) )))); }
2909 Cell zsel55 ( Cell zpair )
2910 { z_tag_check(zpair,ZTUP5,"zsel55"); return snd(snd(snd(snd( snd(zpair) )))); }
2911
2912
2913 Cell unap ( int tag, Cell c )
2914 {
2915    char buf[100];
2916    if (whatIs(c) != tag) {
2917       sprintf(buf, "unap: specified %d, actual %d\n",
2918                    tag, whatIs(c) );
2919       internal(buf);
2920    }
2921    return snd(c);
2922 }
2923
2924 /* --------------------------------------------------------------------------
2925  * Operations on applications:
2926  * ------------------------------------------------------------------------*/
2927
2928 Int argCount;                          /* number of args in application    */
2929
2930 Cell getHead(e)                        /* get head cell of application     */
2931 Cell e; {                              /* set number of args in argCount   */
2932     for (argCount=0; isAp(e); e=fun(e))
2933         argCount++;
2934     return e;
2935 }
2936
2937 List getArgs(e)                        /* get list of arguments in function*/
2938 Cell e; {                              /* application:                     */
2939     List as;                           /* getArgs(f e1 .. en) = [e1,..,en] */
2940
2941     for (as=NIL; isAp(e); e=fun(e))
2942         as = cons(arg(e),as);
2943     return as;
2944 }
2945
2946 Cell nthArg(n,e)                       /* return nth arg in application    */
2947 Int  n;                                /* of function to m args (m>=n)     */
2948 Cell e; {                              /* nthArg n (f x0 x1 ... xm) = xn   */
2949     for (n=numArgs(e)-n-1; n>0; n--)
2950         e = fun(e);
2951     return arg(e);
2952 }
2953
2954 Int numArgs(e)                         /* find number of arguments to expr */
2955 Cell e; {
2956     Int n;
2957     for (n=0; isAp(e); e=fun(e))
2958         n++;
2959     return n;
2960 }
2961
2962 Cell applyToArgs(f,args)               /* destructively apply list of args */
2963 Cell f;                                /* to function f                    */
2964 List args; {
2965     while (nonNull(args)) {
2966         Cell temp = tl(args);
2967         tl(args)  = hd(args);
2968         hd(args)  = f;
2969         f         = args;
2970         args      = temp;
2971     }
2972     return f;
2973 }
2974
2975 /* --------------------------------------------------------------------------
2976  * debugging support
2977  * ------------------------------------------------------------------------*/
2978
2979 static String maybeModuleStr ( Module m )
2980 {
2981    if (isModule(m)) return textToStr(module(m).text); else return "??";
2982 }
2983
2984 static String maybeNameStr ( Name n )
2985 {
2986    if (isName(n)) return textToStr(name(n).text); else return "??";
2987 }
2988
2989 static String maybeTyconStr ( Tycon t )
2990 {
2991    if (isTycon(t)) return textToStr(tycon(t).text); else return "??";
2992 }
2993
2994 static String maybeClassStr ( Class c )
2995 {
2996    if (isClass(c)) return textToStr(cclass(c).text); else return "??";
2997 }
2998
2999 static String maybeText ( Text t )
3000 {
3001    if (isNull(t)) return "(nil)";
3002    return textToStr(t);
3003 }
3004
3005 static void print100 ( Int x )
3006 {
3007    print ( x, 100); printf("\n");
3008 }
3009
3010 void dumpTycon ( Int t )
3011 {
3012    if (isTycon(TYCON_BASE_ADDR+t) && !isTycon(t)) t += TYCON_BASE_ADDR;
3013    if (!isTycon(t)) {
3014       printf ( "dumpTycon %d: not a tycon\n", t);
3015       return;
3016    }
3017    printf ( "{\n" );
3018    printf ( "    text: %s\n",     textToStr(tycon(t).text) );
3019    printf ( "    line: %d\n",     tycon(t).line );
3020    printf ( "     mod: %s\n",     maybeModuleStr(tycon(t).mod));
3021    printf ( "   tuple: %d\n",     tycon(t).tuple);
3022    printf ( "   arity: %d\n",     tycon(t).arity);
3023    printf ( "    kind: ");        print100(tycon(t).kind);
3024    printf ( "    what: %d\n",     tycon(t).what);
3025    printf ( "    defn: ");        print100(tycon(t).defn);
3026    printf ( "    cToT: %d %s\n",  tycon(t).conToTag, 
3027                                   maybeNameStr(tycon(t).conToTag));
3028    printf ( "    tToC: %d %s\n",  tycon(t).tagToCon, 
3029                                   maybeNameStr(tycon(t).tagToCon));
3030    printf ( "    itbl: %p\n",     tycon(t).itbl);
3031    printf ( "  nextTH: %d %s\n",  tycon(t).nextTyconHash,
3032                                   maybeTyconStr(tycon(t).nextTyconHash));
3033    printf ( "}\n" );
3034 }
3035
3036 void dumpName ( Int n )
3037 {
3038    if (isName(NAME_BASE_ADDR+n) && !isName(n)) n += NAME_BASE_ADDR;
3039    if (!isName(n)) {
3040       printf ( "dumpName %d: not a name\n", n);
3041       return;
3042    }
3043    printf ( "{\n" );
3044    printf ( "    text: %s\n",     textToStr(name(n).text) );
3045    printf ( "    line: %d\n",     name(n).line );
3046    printf ( "     mod: %s\n",     maybeModuleStr(name(n).mod));
3047    printf ( "  syntax: %d\n",     name(n).syntax );
3048    printf ( "  parent: %d\n",     name(n).parent );
3049    printf ( "   arity: %d\n",     name(n).arity );
3050    printf ( "  number: %d\n",     name(n).number );
3051    printf ( "    type: ");        print100(name(n).type);
3052    printf ( "    defn: %d\n",     name(n).defn );
3053    printf ( "  stgVar: ");        print100(name(n).stgVar);
3054    printf ( "   cconv: %d\n",     name(n).callconv );
3055    printf ( "  primop: %p\n",     name(n).primop );
3056    printf ( "    itbl: %p\n",     name(n).itbl );
3057    printf ( "  nextNH: %d\n",     name(n).nextNameHash );
3058    printf ( "}\n" );
3059 }
3060
3061
3062 void dumpClass ( Int c )
3063 {
3064    if (isClass(CCLASS_BASE_ADDR+c) && !isClass(c)) c += CCLASS_BASE_ADDR;
3065    if (!isClass(c)) {
3066       printf ( "dumpClass %d: not a class\n", c);
3067       return;
3068    }
3069    printf ( "{\n" );
3070    printf ( "    text: %s\n",     textToStr(cclass(c).text) );
3071    printf ( "    line: %d\n",     cclass(c).line );
3072    printf ( "     mod: %s\n",     maybeModuleStr(cclass(c).mod));
3073    printf ( "   arity: %d\n",     cclass(c).arity );
3074    printf ( "   level: %d\n",     cclass(c).level );
3075    printf ( "   kinds: ");        print100( cclass(c).kinds );
3076    printf ( "     fds: %d\n",     cclass(c).fds );
3077    printf ( "    xfds: %d\n",     cclass(c).xfds );
3078    printf ( "    head: ");        print100( cclass(c).head );
3079    printf ( "    dcon: ");        print100( cclass(c).dcon );
3080    printf ( "  supers: ");        print100( cclass(c).supers );
3081    printf ( " #supers: %d\n",     cclass(c).numSupers );
3082    printf ( "   dsels: ");        print100( cclass(c).dsels );
3083    printf ( " members: ");        print100( cclass(c).members );
3084    printf ( "#members: %d\n",     cclass(c).numMembers );
3085    printf ( "defaults: ");        print100( cclass(c).defaults );
3086    printf ( "   insts: ");        print100( cclass(c).instances );
3087    printf ( "}\n" );
3088 }
3089
3090
3091 void dumpInst ( Int i )
3092 {
3093    if (isInst(INST_BASE_ADDR+i) && !isInst(i)) i += INST_BASE_ADDR;
3094    if (!isInst(i)) {
3095       printf ( "dumpInst %d: not an instance\n", i);
3096       return;
3097    }
3098    printf ( "{\n" );
3099    printf ( "   class: %s\n",     maybeClassStr(inst(i).c) );
3100    printf ( "    line: %d\n",     inst(i).line );
3101    printf ( "     mod: %s\n",     maybeModuleStr(inst(i).mod));
3102    printf ( "   kinds: ");        print100( inst(i).kinds );
3103    printf ( "    head: ");        print100( inst(i).head );
3104    printf ( "   specs: ");        print100( inst(i).specifics );
3105    printf ( "  #specs: %d\n",     inst(i).numSpecifics );
3106    printf ( "   impls: ");        print100( inst(i).implements );
3107    printf ( " builder: %s\n",     maybeNameStr( inst(i).builder ) );
3108    printf ( "}\n" );
3109 }
3110
3111
3112 /* --------------------------------------------------------------------------
3113  * storage control:
3114  * ------------------------------------------------------------------------*/
3115
3116 Void storage(what)
3117 Int what; {
3118     Int i;
3119
3120     switch (what) {
3121         case POSTPREL: break;
3122
3123         case RESET   : clearStack();
3124
3125                        /* the next 2 statements are particularly important
3126                         * if you are using GLOBALfst or GLOBALsnd since the
3127                         * corresponding registers may be reset to their
3128                         * uninitialised initial values by a longjump.
3129                         */
3130                        heapTopFst = heapFst + heapSize;
3131                        heapTopSnd = heapSnd + heapSize;
3132                        consGC = TRUE;
3133                        lsave  = NIL;
3134                        rsave  = NIL;
3135                        if (isNull(lastExprSaved))
3136                            savedText = TEXT_SIZE;
3137                        break;
3138
3139         case MARK    : 
3140                        start();
3141                        for (i = NAME_BASE_ADDR; 
3142                             i < NAME_BASE_ADDR+tabNameSz; ++i) {
3143                           if (tabName[i-NAME_BASE_ADDR].inUse) {
3144                              mark(name(i).parent);
3145                              mark(name(i).defn);
3146                              mark(name(i).stgVar);
3147                              mark(name(i).type);
3148                           }
3149                        }
3150                        end("Names", nameHw-NAMEMIN);
3151
3152                        start();
3153                        for (i = MODULE_BASE_ADDR; 
3154                             i < MODULE_BASE_ADDR+tabModuleSz; ++i) {
3155                           if (tabModule[i-MODULE_BASE_ADDR].inUse) {
3156                              mark(module(i).tycons);
3157                              mark(module(i).names);
3158                              mark(module(i).classes);
3159                              mark(module(i).exports);
3160                              mark(module(i).qualImports);
3161                              mark(module(i).objectExtraNames);
3162                           }
3163                        }
3164                        mark(moduleGraph);
3165                        mark(prelModules);
3166                        mark(targetModules);
3167                        end("Modules", moduleHw-MODMIN);
3168
3169                        start();
3170                        for (i = TYCON_BASE_ADDR; 
3171                             i < TYCON_BASE_ADDR+tabTyconSz; ++i) {
3172                           if (tabTycon[i-TYCON_BASE_ADDR].inUse) {
3173                              mark(tycon(i).defn);
3174                              mark(tycon(i).kind);
3175                              mark(tycon(i).what);
3176                           }
3177                        }
3178                        end("Type constructors", tyconHw-TYCMIN);
3179
3180                        start();
3181                        for (i = CCLASS_BASE_ADDR; 
3182                             i < CCLASS_BASE_ADDR+tabClassSz; ++i) {
3183                           if (tabModule[i-MODULE_BASE_ADDR].inUse) {
3184                              mark(cclass(i).head);
3185                              mark(cclass(i).kinds);
3186                              mark(cclass(i).fds);
3187                              mark(cclass(i).xfds);
3188                              mark(cclass(i).dsels);
3189                              mark(cclass(i).supers);
3190                              mark(cclass(i).members);
3191                              mark(cclass(i).defaults);
3192                              mark(cclass(i).instances);
3193                           }
3194                        }
3195                        mark(classes);
3196                        end("Classes", classHw-CLASSMIN);
3197
3198                        start();
3199                        for (i = INST_BASE_ADDR; 
3200                             i < INST_BASE_ADDR+tabInstSz; ++i) {
3201                           if (tabInst[i-INST_BASE_ADDR].inUse) {
3202                              mark(inst(i).head);
3203                              mark(inst(i).kinds);
3204                              mark(inst(i).specifics);
3205                              mark(inst(i).implements);
3206                           }
3207                        }
3208                        end("Instances", instHw-INSTMIN);
3209
3210                        start();
3211                        for (i=0; i<=sp; ++i)
3212                            mark(stack(i));
3213                        end("Stack", sp+1);
3214
3215                        start();
3216                        mark(lastExprSaved);
3217                        mark(lsave);
3218                        mark(rsave);
3219                        end("Last expression", 3);
3220
3221                        if (consGC) {
3222                            start();
3223                            gcCStack();
3224                            end("C stack", stackRoots);
3225                        }
3226
3227                        break;
3228
3229         case PREPREL : heapFst = heapAlloc(heapSize);
3230                        heapSnd = heapAlloc(heapSize);
3231
3232                        if (heapFst==(Heap)0 || heapSnd==(Heap)0) {
3233                            ERRMSG(0) "Cannot allocate heap storage (%d cells)",
3234                                      heapSize
3235                            EEND;
3236                        }
3237
3238                        heapTopFst = heapFst + heapSize;
3239                        heapTopSnd = heapSnd + heapSize;
3240                        for (i=1; i<heapSize; ++i) {
3241                            fst(-i) = FREECELL;
3242                            snd(-i) = -(i+1);
3243                        }
3244                        snd(-heapSize) = NIL;
3245                        freeList  = -1;
3246                        numGcs    = 0;
3247                        consGC    = TRUE;
3248                        lsave     = NIL;
3249                        rsave     = NIL;
3250
3251                        marksSize  = bitArraySize(heapSize);
3252                        if ((marks=(Int *)calloc(marksSize, sizeof(Int)))==0) {
3253                            ERRMSG(0) "Unable to allocate gc markspace"
3254                            EEND;
3255                        }
3256
3257                        clearStack();
3258
3259                        textHw        = 0;
3260                        nextNewText   = INVAR_BASE_ADDR;
3261                        nextNewDText  = INDVAR_BASE_ADDR;
3262                        lastExprSaved = NIL;
3263                        savedText     = TEXT_SIZE;
3264
3265                        for (i=0; i<TEXTHSZ;  ++i) textHash[i][0] = NOTEXT;
3266                        for (i=0; i<TYCONHSZ; ++i) tyconHash[RC_T(i)] = NIL;
3267                        for (i=0; i<NAMEHSZ;  ++i) nameHash[RC_N(i)] = NIL;
3268
3269                        break;
3270     }
3271 }
3272
3273 /*-------------------------------------------------------------------------*/