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