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