[project @ 1999-10-15 21:40:49 by andy]
[ghc-hetmet.git] / ghc / interpreter / compiler.c
1
2 /* --------------------------------------------------------------------------
3  * This is the Hugs compiler, handling translation of typechecked code to
4  * `kernel' language, elimination of pattern matching and translation to
5  * super combinators (lambda lifting).
6  *
7  * The Hugs 98 system is Copyright (c) Mark P Jones, Alastair Reid, the
8  * Yale Haskell Group, and the Oregon Graduate Institute of Science and
9  * Technology, 1994-1999, All rights reserved.  It is distributed as
10  * free software under the license in the file "License", which is
11  * included in the distribution.
12  *
13  * $RCSfile: compiler.c,v $
14  * $Revision: 1.9 $
15  * $Date: 1999/10/15 21:41:03 $
16  * ------------------------------------------------------------------------*/
17
18 #include "prelude.h"
19 #include "storage.h"
20 #include "backend.h"
21 #include "connect.h"
22 #include "errors.h"
23 #include "Rts.h"                       /* for rts_eval and related stuff   */
24 #include "RtsAPI.h"                    /* for rts_eval and related stuff   */
25 #include "Schedule.h"
26 #include "link.h"
27
28 Addr inputCode;                        /* Addr of compiled code for expr   */
29 static Name currentName;               /* Top level name being processed   */
30 #if DEBUG_CODE
31 Bool   debugCode     = FALSE;          /* TRUE => print G-code to screen   */
32 #endif
33
34
35
36 /* --------------------------------------------------------------------------
37  * Local function prototypes:
38  * ------------------------------------------------------------------------*/
39
40 static Cell local translate             Args((Cell));
41 static Void local transPair             Args((Pair));
42 static Void local transTriple           Args((Triple));
43 static Void local transAlt              Args((Cell));
44 static Void local transCase             Args((Cell));
45 static List local transBinds            Args((List));
46 static Cell local transRhs              Args((Cell));
47 static Cell local mkConsList            Args((List));
48 static Cell local expandLetrec          Args((Cell));
49 static Cell local transComp             Args((Cell,List,Cell));
50 static Cell local transDo               Args((Cell,Cell,List));
51 static Cell local transConFlds          Args((Cell,List));
52 static Cell local transUpdFlds          Args((Cell,List,List));
53
54 static Cell local refutePat             Args((Cell));
55 static Cell local refutePatAp           Args((Cell));
56 static Cell local matchPat              Args((Cell));
57 static List local remPat                Args((Cell,Cell,List));
58 static List local remPat1               Args((Cell,Cell,List));
59
60 static Cell local pmcTerm               Args((Int,List,Cell));
61 static Cell local pmcPair               Args((Int,List,Pair));
62 static Cell local pmcTriple             Args((Int,List,Triple));
63 static Cell local pmcVar                Args((List,Text));
64 static Void local pmcLetrec             Args((Int,List,Pair));
65 static Cell local pmcVarDef             Args((Int,List,List));
66 static Void local pmcFunDef             Args((Int,List,Triple));
67 static List local altsMatch             Args((Int,Int,List,List));
68 static Cell local match                 Args((Int,List));
69 static Cell local joinMas               Args((Int,List));
70 static Bool local canFail               Args((Cell));
71 static List local addConTable           Args((Cell,Cell,List));
72 static Void local advance               Args((Int,Int,Cell));
73 static Bool local emptyMatch            Args((Cell));
74 static Cell local maDiscr               Args((Cell));
75 static Bool local isNumDiscr            Args((Cell));
76 static Bool local eqNumDiscr            Args((Cell,Cell));
77 #if TREX
78 static Bool local isExtDiscr            Args((Cell));
79 static Bool local eqExtDiscr            Args((Cell,Cell));
80 #endif
81
82 static Void local compileGlobalFunction Args((Pair));
83 static Void local compileGenFunction    Args((Name));
84 static Name local compileSelFunction    Args((Pair));
85 static List local addStgVar             Args((List,Pair));
86
87
88 /* --------------------------------------------------------------------------
89  * Translation:    Convert input expressions into a less complex language
90  *                 of terms using only LETREC, AP, constants and vars.
91  *                 Also remove pattern definitions on lhs of eqns.
92  * ------------------------------------------------------------------------*/
93
94 static Cell local translate(e)         /* Translate expression:            */
95 Cell e; {
96     switch (whatIs(e)) {
97         case LETREC     : snd(snd(e)) = translate(snd(snd(e)));
98                           return expandLetrec(e);
99
100         case COND       : transTriple(snd(e));
101                           return e;
102
103         case AP         : fst(e) = translate(fst(e));
104
105                           if (fst(e)==nameId || fst(e)==nameInd)
106                               return translate(snd(e));
107                           if (isName(fst(e)) &&
108                               isMfun(fst(e)) &&
109                               mfunOf(fst(e))==0)
110                               return translate(snd(e));
111
112                           snd(e) = translate(snd(e));
113                           return e;
114
115         case NAME       : if (e==nameOtherwise)
116                               return nameTrue;
117                           if (isCfun(e)) {
118                               if (isName(name(e).defn))
119                                   return name(e).defn;
120                               if (isPair(name(e).defn))
121                                   return snd(name(e).defn);
122                           }
123                           return e;
124
125 #if TREX
126         case RECSEL     : return nameRecSel;
127
128         case EXT        :
129 #endif
130         case TUPLE      :
131         case VAROPCELL  :
132         case VARIDCELL  :
133         case DICTVAR    :
134         case INTCELL    :
135         case FLOATCELL  :
136         case STRCELL    :
137         case BIGCELL    :
138         case CHARCELL   : return e;
139
140         case FINLIST    : mapOver(translate,snd(e));
141                           return mkConsList(snd(e));
142
143         case DOCOMP     : {   Cell m = translate(fst(snd(e)));
144                               Cell r = translate(fst(snd(snd(e))));
145                               return transDo(m,r,snd(snd(snd(e))));
146                           }
147
148         case MONADCOMP  : {   Cell m  = translate(fst(snd(e)));
149                               Cell r  = translate(fst(snd(snd(e))));
150                               Cell qs = snd(snd(snd(e)));
151                               if (m == nameListMonad)
152                                   return transComp(r,qs,nameNil);
153                               else {
154 #if MONAD_COMPS
155                                   r = ap(ap(nameReturn,m),r);
156                                   return transDo(m,r,qs);
157 #else
158                                   internal("translate: monad comps");
159 #endif
160                               }
161                           }
162
163         case CONFLDS    : return transConFlds(fst(snd(e)),snd(snd(e)));
164
165         case UPDFLDS    : return transUpdFlds(fst3(snd(e)),
166                                               snd3(snd(e)),
167                                               thd3(snd(e)));
168
169         case CASE       : {   Cell nv = inventVar();
170                               mapProc(transCase,snd(snd(e)));
171                               return ap(LETREC,
172                                         pair(singleton(pair(nv,snd(snd(e)))),
173                                              ap(nv,translate(fst(snd(e))))));
174                           }
175
176         case LAMBDA     : {   Cell nv = inventVar();
177                               transAlt(snd(e));
178                               return ap(LETREC,
179                                         pair(singleton(pair(
180                                                         nv,
181                                                         singleton(snd(e)))),
182                                              nv));
183                           }
184
185         default         : fprintf(stderr, "stuff=%d\n",whatIs(e));internal("translate");
186     }
187     return e;
188 }
189
190 static Void local transPair(pr)        /* Translate each component in a    */
191 Pair pr; {                             /* pair of expressions.             */
192     fst(pr) = translate(fst(pr));
193     snd(pr) = translate(snd(pr));
194 }
195
196 static Void local transTriple(tr)      /* Translate each component in a    */
197 Triple tr; {                           /* triple of expressions.           */
198     fst3(tr) = translate(fst3(tr));
199     snd3(tr) = translate(snd3(tr));
200     thd3(tr) = translate(thd3(tr));
201 }
202
203 static Void local transAlt(e)          /* Translate alt:                   */
204 Cell e; {                              /* ([Pat], Rhs) ==> ([Pat], Rhs')   */
205     snd(e) = transRhs(snd(e));
206 }
207
208 static Void local transCase(c)         /* Translate case:                  */
209 Cell c; {                              /* (Pat, Rhs) ==> ([Pat], Rhs')     */
210     fst(c) = singleton(fst(c));
211     snd(c) = transRhs(snd(c));
212 }
213
214 static List local transBinds(bs)        /* Translate list of bindings:     */
215 List bs; {                              /* eliminating pattern matching on */
216     List newBinds = NIL;                /* lhs of bindings.                */
217     for (; nonNull(bs); bs=tl(bs)) {
218         if (isVar(fst(hd(bs)))) {
219             mapProc(transAlt,snd(hd(bs)));
220             newBinds = cons(hd(bs),newBinds);
221         }
222         else
223             newBinds = remPat(fst(snd(hd(bs))),
224                               snd(snd(hd(bs)))=transRhs(snd(snd(hd(bs)))),
225                               newBinds);
226     }
227     return newBinds;
228 }
229
230 static Cell local transRhs(rhs)        /* Translate rhs: removing line nos */
231 Cell rhs; {
232     switch (whatIs(rhs)) {
233         case LETREC  : snd(snd(rhs)) = transRhs(snd(snd(rhs)));
234                        return expandLetrec(rhs);
235
236         case GUARDED : mapOver(snd,snd(rhs));       /* discard line number */
237                        mapProc(transPair,snd(rhs));
238                        return rhs;
239
240         default      : return translate(snd(rhs));  /* discard line number */
241     }
242 }
243
244 static Cell local mkConsList(es)       /* Construct expression for list es */
245 List es; {                             /* using nameNil and nameCons       */
246     if (isNull(es))
247         return nameNil;
248     else
249         return ap(ap(nameCons,hd(es)),mkConsList(tl(es)));
250 }
251
252 static Cell local expandLetrec(root)   /* translate LETREC with list of    */
253 Cell root; {                           /* groups of bindings (from depend. */
254     Cell e   = snd(snd(root));         /* analysis) to use nested LETRECs  */
255     List bss = fst(snd(root));
256     Cell temp;
257
258     if (isNull(bss))                   /* should never happen, but just in */
259         return e;                      /* case:  LETREC [] IN e  ==>  e    */
260
261     mapOver(transBinds,bss);           /* translate each group of bindings */
262
263     for (temp=root; nonNull(tl(bss)); bss=tl(bss)) {
264         fst(snd(temp)) = hd(bss);
265         snd(snd(temp)) = ap(LETREC,pair(NIL,e));
266         temp           = snd(snd(temp));
267     }
268     fst(snd(temp)) = hd(bss);
269
270     return root;
271 }
272
273 /* --------------------------------------------------------------------------
274  * Translation of list comprehensions is based on the description in
275  * `The Implementation of Functional Programming Languages':
276  *
277  * [ e | qs ] ++ l            => transComp e qs l
278  * transComp e []           l => e : l
279  * transComp e ((p<-xs):qs) l => LETREC _h []      = l
280  *                                      _h (p:_xs) = transComp e qs (_h _xs)
281  *                                      _h (_:_xs) = _h _xs --if p !failFree
282  *                               IN _h xs
283  * transComp e (b:qs)       l => if b then transComp e qs l else l
284  * transComp e (decls:qs)   l => LETREC decls IN transComp e qs l
285  * ------------------------------------------------------------------------*/
286
287 static Cell local transComp(e,qs,l)    /* Translate [e | qs] ++ l          */
288 Cell e;
289 List qs;
290 Cell l; {
291     if (nonNull(qs)) {
292         Cell q   = hd(qs);
293         Cell qs1 = tl(qs);
294
295         switch (fst(q)) {
296             case FROMQUAL : {   Cell ld    = NIL;
297                                 Cell hVar  = inventVar();
298                                 Cell xsVar = inventVar();
299
300                                 if (!failFree(fst(snd(q))))
301                                     ld = cons(pair(singleton(
302                                                     ap(ap(nameCons,
303                                                           WILDCARD),
304                                                           xsVar)),
305                                                    ap(hVar,xsVar)),
306                                               ld);
307
308                                 ld = cons(pair(singleton(
309                                                 ap(ap(nameCons,
310                                                       fst(snd(q))),
311                                                       xsVar)),
312                                                transComp(e,
313                                                          qs1,
314                                                          ap(hVar,xsVar))),
315                                           ld);
316                                 ld = cons(pair(singleton(nameNil),
317                                                l),
318                                           ld);
319
320                                 return ap(LETREC,
321                                           pair(singleton(pair(hVar,
322                                                               ld)),
323                                                ap(hVar,
324                                                   translate(snd(snd(q))))));
325                             }
326
327             case QWHERE   : return
328                                 expandLetrec(ap(LETREC,
329                                                 pair(snd(q),
330                                                      transComp(e,qs1,l))));
331
332             case BOOLQUAL : return ap(COND,
333                                       triple(translate(snd(q)),
334                                              transComp(e,qs1,l),
335                                              l));
336         }
337     }
338
339     return ap(ap(nameCons,e),l);
340 }
341
342 /* --------------------------------------------------------------------------
343  * Translation of monad comprehensions written using do-notation:
344  *
345  * do { e }               =>  e
346  * do { p <- exp; qs }    =>  LETREC _h p = do { qs }
347  *                                   _h _ = fail m "match fails"
348  *                            IN bind m exp _h
349  * do { LET decls; qs }   =>  LETREC decls IN do { qs }
350  * do { IF guard; qs }    =>  if guard then do { qs } else fail m  "guard fails"
351  * do { e; qs }           =>  LETREC _h _ = [ e | qs ] in bind m exp _h
352  *
353  * where m :: Monad f
354  * ------------------------------------------------------------------------*/
355
356 static Cell local transDo(m,e,qs)       /* Translate do { qs ; e }         */
357 Cell m;
358 Cell e;
359 List qs; {
360     if (nonNull(qs)) {
361         Cell q   = hd(qs);
362         Cell qs1 = tl(qs);
363
364         switch (fst(q)) {
365             case FROMQUAL : {   Cell ld   = NIL;
366                                 Cell hVar = inventVar();
367
368                                 if (!failFree(fst(snd(q)))) {
369                                     Cell str = mkStr(findText("match fails"));
370                                     ld = cons(pair(singleton(WILDCARD),
371                                                    ap2(nameMFail,m,str)),
372                                               ld);
373                                 }
374
375                                 ld = cons(pair(singleton(fst(snd(q))),
376                                                transDo(m,e,qs1)),
377                                           ld);
378
379                                 return ap(LETREC,
380                                           pair(singleton(pair(hVar,ld)),
381                                                ap(ap(ap(nameBind,
382                                                         m),
383                                                      translate(snd(snd(q)))),
384                                                   hVar)));
385                             }
386
387             case DOQUAL :   {   Cell hVar = inventVar();
388                                 Cell ld   = cons(pair(singleton(WILDCARD),
389                                                       transDo(m,e,qs1)),
390                                                  NIL);
391                                 return ap(LETREC,
392                                           pair(singleton(pair(hVar,ld)),
393                                                ap(ap(ap(nameBind,
394                                                         m),
395                                                      translate(snd(q))),
396                                                   hVar)));
397                             }
398
399             case QWHERE   : return
400                                 expandLetrec(ap(LETREC,
401                                                 pair(snd(q),
402                                                      transDo(m,e,qs1))));
403
404             case BOOLQUAL : return
405                                 ap(COND,
406                                    triple(translate(snd(q)),
407                                           transDo(m,e,qs1),
408                                           ap2(nameMFail,m,
409                                             mkStr(findText("guard fails")))));
410         }
411     }
412     return e;
413 }
414
415 /* --------------------------------------------------------------------------
416  * Translation of named field construction and update:
417  *
418  * Construction is implemented using the following transformation:
419  *
420  *   C{x1=e1, ..., xn=en} =  C v1 ... vm
421  * where:
422  *   vi = e1,        if the ith component of C is labelled with x1
423  *       ...
424  *      = en,        if the ith component of C is labelled with xn
425  *      = undefined, otherwise
426  *
427  * Update is implemented using the following transformation:
428  *
429  *   e{x1=e1, ..., xn=en}
430  *      =  let nv (C a1 ... am) v1 ... vn = C a1' .. am'
431  *             nv (D b1 ... bk) v1 ... vn = D b1' .. bk
432  *             ...
433  *             nv _             v1 ... vn = error "failed update"
434  *         in nv e e1 ... en
435  * where:
436  *   nv, v1, ..., vn, a1, ..., am, b1, ..., bk, ... are new variables,
437  *   C,D,... = { K | K is a constr fun s.t. {x1,...,xn} subset of sels(K)}
438  * and:
439  *   ai' = v1,   if the ith component of C is labelled with x1
440  *       ...
441  *       = vn,   if the ith component of C is labelled with xn
442  *       = ai,   otherwise
443  *  etc...
444  *
445  * The error case may be omitted if C,D,... is an enumeration of all of the
446  * constructors for the datatype concerned.  Strictly speaking, error case
447  * isn't needed at all -- the only benefit of including it is that the user
448  * will get a "failed update" message rather than a cryptic {v354 ...}.
449  * So, for now, we'll go with the second option!
450  *
451  * For the time being, code for each update operation is generated
452  * independently of any other updates.  However, if updates are used
453  * frequently, then we might want to consider changing the implementation
454  * at a later stage to cache definitions of functions like nv above.  This
455  * would create a shared library of update functions, indexed by a set of
456  * constructors {C,D,...}.
457  * ------------------------------------------------------------------------*/
458
459 static Cell local transConFlds(c,flds)  /* Translate C{flds}               */
460 Name c;
461 List flds; {
462     Cell e = c;
463     Int  m = name(c).arity;
464     Int  i;
465     for (i=m; i>0; i--)
466         e = ap(e,nameUndefined);
467     for (; nonNull(flds); flds=tl(flds)) {
468         Cell a = e;
469         for (i=m-sfunPos(fst(hd(flds)),c); i>0; i--)
470             a = fun(a);
471         arg(a) = translate(snd(hd(flds)));
472     }
473     return e;
474 }
475
476 static Cell local transUpdFlds(e,cs,flds)/* Translate e{flds}              */
477 Cell e;                                 /* (cs is corresp list of constrs) */
478 List cs;
479 List flds; {
480     Cell nv   = inventVar();
481     Cell body = ap(nv,translate(e));
482     List fs   = flds;
483     List args = NIL;
484     List alts = NIL;
485
486     for (; nonNull(fs); fs=tl(fs)) {    /* body = nv e1 ... en             */
487         Cell b = hd(fs);                /* args = [v1, ..., vn]            */
488         body   = ap(body,translate(snd(b)));
489         args   = cons(inventVar(),args);
490     }
491
492     for (; nonNull(cs); cs=tl(cs)) {    /* Loop through constructors to    */
493         Cell c   = hd(cs);              /* build up list of alts.          */
494         Cell pat = c;
495         Cell rhs = c;
496         List as  = args;
497         Int  m   = name(c).arity;
498         Int  i;
499
500         for (i=m; i>0; i--) {           /* pat  = C a1 ... am              */
501             Cell a = inventVar();       /* rhs  = C a1 ... am              */
502             pat    = ap(pat,a);
503             rhs    = ap(rhs,a);
504         }
505
506         for (fs=flds; nonNull(fs); fs=tl(fs), as=tl(as)) {
507             Name s = fst(hd(fs));       /* Replace approp ai in rhs with   */
508             Cell r = rhs;               /* vars from [v1,...,vn]           */
509             for (i=m-sfunPos(s,c); i>0; i--)
510                 r = fun(r);
511             arg(r) = hd(as);
512         }
513
514         alts     = cons(pair(cons(pat,args),rhs),alts);
515     }
516     return ap(LETREC,pair(singleton(pair(nv,alts)),body));
517 }
518
519 /* --------------------------------------------------------------------------
520  * Elimination of pattern bindings:
521  *
522  * The following code adopts the definition of failure free patterns as given
523  * in the Haskell 1.3 report; the term "irrefutable" is also used there for
524  * a subset of the failure free patterns described here, but has no useful
525  * role in this implementation.  Basically speaking, the failure free patterns
526  * are:         variable, wildcard, ~apat
527  *              var@apat,               if apat is failure free
528  *              C apat1 ... apatn       if C is a product constructor
529  *                                      (i.e. an only constructor) and
530  *                                      apat1,...,apatn are failure free
531  * Note that the last case automatically covers the case where C comes from
532  * a newtype construction.
533  * ------------------------------------------------------------------------*/
534
535 Bool failFree(pat)                /* is pattern failure free? (do we need  */
536 Cell pat; {                       /* a conformality check?)                */
537     Cell c = getHead(pat);
538
539     switch (whatIs(c)) {
540         case ASPAT     : return failFree(snd(snd(pat)));
541
542         case NAME      : if (!isCfun(c) || cfunOf(c)!=0)
543                              return FALSE;
544                          /*intentional fall-thru*/
545         case TUPLE     : for (; isAp(pat); pat=fun(pat))
546                              if (!failFree(arg(pat)))
547                                 return FALSE;
548                          /*intentional fall-thru*/
549         case LAZYPAT   :
550         case VAROPCELL :
551         case VARIDCELL :
552         case DICTVAR   :
553         case WILDCARD  : return TRUE;
554
555 #if TREX
556         case EXT       : return failFree(extField(pat)) &&
557                                 failFree(extRow(pat));
558 #endif
559
560         case CONFLDS   : if (cfunOf(fst(snd(c)))==0) {
561                              List fs = snd(snd(c));
562                              for (; nonNull(fs); fs=tl(fs))
563                                  if (!failFree(snd(hd(fs))))
564                                      return FALSE;
565                              return TRUE;
566                          }
567                          /*intentional fall-thru*/
568         default        : return FALSE;
569     }
570 }
571
572 static Cell local refutePat(pat)  /* find pattern to refute in conformality*/
573 Cell pat; {                       /* test with pat.                        */
574                                   /* e.g. refPat  (x:y) == (_:_)           */
575                                   /*      refPat ~(x:y) == _      etc..    */
576
577     switch (whatIs(pat)) {
578         case ASPAT     : return refutePat(snd(snd(pat)));
579
580         case FINLIST   : {   Cell ys = snd(pat);
581                              Cell xs = NIL;
582                              for (; nonNull(ys); ys=tl(ys))
583                                  xs = ap(ap(nameCons,refutePat(hd(ys))),xs);
584                              return revOnto(xs,nameNil);
585                          }
586
587         case CONFLDS   : {   Cell ps = NIL;
588                              Cell fs = snd(snd(pat));
589                              for (; nonNull(fs); fs=tl(fs)) {
590                                  Cell p = refutePat(snd(hd(fs)));
591                                  ps     = cons(pair(fst(hd(fs)),p),ps);
592                              }
593                              return pair(CONFLDS,pair(fst(snd(pat)),rev(ps)));
594                          }
595
596         case VAROPCELL :
597         case VARIDCELL :
598         case DICTVAR   :
599         case WILDCARD  :
600         case LAZYPAT   : return WILDCARD;
601
602         case STRCELL   :
603         case CHARCELL  :
604 #if NPLUSK
605         case ADDPAT    :
606 #endif
607         case TUPLE     :
608         case NAME      : return pat;
609
610         case AP        : return refutePatAp(pat);
611
612         default        : internal("refutePat");
613                          return NIL; /*NOTREACHED*/
614     }
615 }
616
617 static Cell local refutePatAp(p)  /* find pattern to refute in conformality*/
618 Cell p; {
619     Cell h = getHead(p);
620     if (h==nameFromInt || h==nameFromInteger || h==nameFromDouble)
621         return p;
622 #if NPLUSK
623     else if (whatIs(h)==ADDPAT)
624         return ap(fun(p),refutePat(arg(p)));
625 #endif
626 #if TREX
627     else if (isExt(h)) {
628         Cell pf = refutePat(extField(p));
629         Cell pr = refutePat(extRow(p));
630         return ap(ap(fun(fun(p)),pf),pr);
631     }
632 #endif
633     else {
634         List as = getArgs(p);
635         mapOver(refutePat,as);
636         return applyToArgs(h,as);
637     }
638 }
639
640 static Cell local matchPat(pat) /* find pattern to match against           */
641 Cell pat; {                     /* replaces parts of pattern that do not   */
642                                 /* include variables with wildcards        */
643     switch (whatIs(pat)) {
644         case ASPAT     : {   Cell p = matchPat(snd(snd(pat)));
645                              return (p==WILDCARD) ? fst(snd(pat))
646                                                   : ap(ASPAT,
647                                                        pair(fst(snd(pat)),p));
648                          }
649
650         case FINLIST   : {   Cell ys = snd(pat);
651                              Cell xs = NIL;
652                              for (; nonNull(ys); ys=tl(ys))
653                                  xs = cons(matchPat(hd(ys)),xs);
654                              while (nonNull(xs) && hd(xs)==WILDCARD)
655                                  xs = tl(xs);
656                              for (ys=nameNil; nonNull(xs); xs=tl(xs))
657                                  ys = ap(ap(nameCons,hd(xs)),ys);
658                              return ys;
659                          }
660
661         case CONFLDS   : {   Cell ps   = NIL;
662                              Name c    = fst(snd(pat));
663                              Cell fs   = snd(snd(pat));
664                              Bool avar = FALSE;
665                              for (; nonNull(fs); fs=tl(fs)) {
666                                  Cell p = matchPat(snd(hd(fs)));
667                                  ps     = cons(pair(fst(hd(fs)),p),ps);
668                                  if (p!=WILDCARD)
669                                      avar = TRUE;
670                              }
671                              return avar ? pair(CONFLDS,pair(c,rev(ps)))
672                                          : WILDCARD;
673                          }
674
675         case VAROPCELL :
676         case VARIDCELL :
677         case DICTVAR   : return pat;
678
679         case LAZYPAT   : {   Cell p = matchPat(snd(pat));
680                              return (p==WILDCARD) ? WILDCARD : ap(LAZYPAT,p);
681                          }
682
683         case WILDCARD  :
684         case STRCELL   :
685         case CHARCELL  : return WILDCARD;
686
687         case TUPLE     :
688         case NAME      :
689         case AP        : {   Cell h = getHead(pat);
690                              if (h==nameFromInt     ||
691                                  h==nameFromInteger || h==nameFromDouble)
692                                  return WILDCARD;
693 #if NPLUSK
694                              else if (whatIs(h)==ADDPAT)
695                                  return pat;
696 #endif
697 #if TREX
698                              else if (isExt(h)) {
699                                  Cell pf = matchPat(extField(pat));
700                                  Cell pr = matchPat(extRow(pat));
701                                  return (pf==WILDCARD && pr==WILDCARD)
702                                           ? WILDCARD
703                                           : ap(ap(fun(fun(pat)),pf),pr);
704                              }
705 #endif
706                              else {
707                                  List args = NIL;
708                                  Bool avar = FALSE;
709                                  for (; isAp(pat); pat=fun(pat)) {
710                                      Cell p = matchPat(arg(pat));
711                                      if (p!=WILDCARD)
712                                          avar = TRUE;
713                                      args = cons(p,args);
714                                  }
715                                  return avar ? applyToArgs(pat,args)
716                                              : WILDCARD;
717                              }
718                          }
719
720         default        : internal("matchPat");
721                          return NIL; /*NOTREACHED*/
722     }
723 }
724
725 #define addEqn(v,val,lds)  cons(pair(v,singleton(pair(NIL,val))),lds)
726
727 static List local remPat(pat,expr,lds)
728 Cell pat;                         /* Produce list of definitions for eqn   */
729 Cell expr;                        /* pat = expr, including a conformality  */
730 List lds; {                       /* check if required.                    */
731
732     /* Conformality test (if required):
733      *   pat = expr  ==>    nv = LETREC confCheck nv@pat = nv
734      *                           IN confCheck expr
735      *                      remPat1(pat,nv,.....);
736      */
737
738     if (!failFree(pat)) {
739         Cell confVar = inventVar();
740         Cell nv      = inventVar();
741         Cell locfun  = pair(confVar,         /* confVar [([nv@refPat],nv)] */
742                             singleton(pair(singleton(ap(ASPAT,
743                                                         pair(nv,
744                                                              refutePat(pat)))),
745                                            nv)));
746
747         if (whatIs(expr)==GUARDED) {         /* A spanner ... special case */
748             lds  = addEqn(nv,expr,lds);      /* for guarded pattern binding*/
749             expr = nv;
750             nv   = inventVar();
751         }
752
753         if (whatIs(pat)==ASPAT) {            /* avoid using new variable if*/
754             nv   = fst(snd(pat));            /* a variable is already given*/
755             pat  = snd(snd(pat));            /* by an as-pattern           */
756         }
757
758         lds = addEqn(nv,                                /* nv =            */
759                      ap(LETREC,pair(singleton(locfun),  /* LETREC [locfun] */
760                                     ap(confVar,expr))), /* IN confVar expr */
761                      lds);
762
763         return remPat1(matchPat(pat),nv,lds);
764     }
765
766     return remPat1(matchPat(pat),expr,lds);
767 }
768
769 static List local remPat1(pat,expr,lds)
770 Cell pat;                         /* Add definitions for: pat = expr to    */
771 Cell expr;                        /* list of local definitions in lds.     */
772 List lds; {
773     Cell c = getHead(pat);
774
775     switch (whatIs(c)) {
776         case WILDCARD  :
777         case STRCELL   :
778         case CHARCELL  : break;
779
780         case ASPAT     : return remPat1(snd(snd(pat)),     /* v@pat = expr */
781                                         fst(snd(pat)),
782                                         addEqn(fst(snd(pat)),expr,lds));
783
784         case LAZYPAT   : {   Cell nv;
785
786                              if (isVar(expr) || isName(expr))
787                                  nv  = expr;
788                              else {
789                                  nv  = inventVar();
790                                  lds = addEqn(nv,expr,lds);
791                              }
792
793                              return remPat(snd(pat),nv,lds);
794                          }
795
796 #if NPLUSK
797         case ADDPAT    : return remPat1(arg(pat),       /* n + k = expr */
798                                         ap(ap(ap(namePmSub,
799                                                  arg(fun(pat))),
800                                                  mkInt(snd(fun(fun(pat))))),
801                                                  expr),
802                                         lds);
803 #endif
804
805         case FINLIST   : return remPat1(mkConsList(snd(pat)),expr,lds);
806
807         case CONFLDS   : {   Name h  = fst(snd(pat));
808                              Int  m  = name(h).arity;
809                              Cell p  = h;
810                              List fs = snd(snd(pat));
811                              Int  i  = m;
812                              while (0<i--)
813                                  p = ap(p,WILDCARD);
814                              for (; nonNull(fs); fs=tl(fs)) {
815                                  Cell r = p;
816                                  for (i=m-sfunPos(fst(hd(fs)),h); i>0; i--)
817                                      r = fun(r);
818                                  arg(r) = snd(hd(fs));
819                              }
820                              return remPat1(p,expr,lds);
821                          }
822
823         case DICTVAR   : /* shouldn't really occur */
824                          assert(0); /* so let's test for it then! ADR */
825         case VARIDCELL :
826         case VAROPCELL : return addEqn(pat,expr,lds);
827
828         case NAME      : if (c==nameFromInt || c==nameFromInteger
829                                             || c==nameFromDouble) {
830                              if (argCount==2)
831                                  arg(fun(pat)) = translate(arg(fun(pat)));
832                              break;
833                          }
834
835                          if (argCount==1 && isCfun(c)       /* for newtype */
836                              && cfunOf(c)==0 && name(c).defn==nameId)
837                              return remPat1(arg(pat),expr,lds);
838
839                          /* intentional fall-thru */
840         case TUPLE     : {   List ps = getArgs(pat);
841
842                              if (nonNull(ps)) {
843                                  Cell nv, sel;
844                                  Int  i;
845
846                                  if (isVar(expr) || isName(expr))
847                                      nv  = expr;
848                                  else {
849                                      nv  = inventVar();
850                                      lds = addEqn(nv,expr,lds);
851                                  }
852
853                                  sel = ap(ap(nameSel,c),nv);
854                                  for (i=1; nonNull(ps); ++i, ps=tl(ps))
855                                       lds = remPat1(hd(ps),
856                                                     ap(sel,mkInt(i)),
857                                                     lds);
858                              }
859                          }
860                          break;
861
862 #if TREX
863         case EXT       : {   Cell nv = inventVar();
864                              arg(fun(fun(pat)))
865                                  = translate(arg(fun(fun(pat))));
866                              lds = addEqn(nv,
867                                           ap(ap(nameRecBrk,
868                                                 arg(fun(fun(pat)))),
869                                              expr),
870                                           lds);
871                              lds = remPat1(extField(pat),ap(nameFst,nv),lds);
872                              lds = remPat1(extRow(pat),ap(nameSnd,nv),lds);
873                          }
874                          break;
875 #endif
876
877         default        : internal("remPat1");
878                          break;
879     }
880     return lds;
881 }
882
883 /* --------------------------------------------------------------------------
884  * Eliminate pattern matching in function definitions -- pattern matching
885  * compiler:
886  *
887  * The original Gofer/Hugs pattern matching compiler was based on Wadler's
888  * algorithms described in `Implementation of functional programming
889  * languages'.  That should still provide a good starting point for anyone
890  * wanting to understand this part of the system.  However, the original
891  * algorithm has been generalized and restructured in order to implement
892  * new features added in Haskell 1.3.
893  *
894  * During the translation, in preparation for later stages of compilation,
895  * all local and bound variables are replaced by suitable offsets, and
896  * locally defined function symbols are given new names (which will
897  * eventually be their names when lifted to make top level definitions).
898  * ------------------------------------------------------------------------*/
899
900 static Offset freeBegin; /* only variables with offset <= freeBegin are of */
901 static List   freeVars;  /* interest as `free' variables                   */
902 static List   freeFuns;  /* List of `free' local functions                 */
903
904 static Cell local pmcTerm(co,sc,e)     /* apply pattern matching compiler  */
905 Int  co;                               /* co = current offset              */
906 List sc;                               /* sc = scope                       */
907 Cell e;  {                             /* e  = expr to transform           */
908     switch (whatIs(e)) {
909         case GUARDED  : map2Over(pmcPair,co,sc,snd(e));
910                         break;
911
912         case LETREC   : pmcLetrec(co,sc,snd(e));
913                         break;
914
915         case VARIDCELL:
916         case VAROPCELL:
917         case DICTVAR  : return pmcVar(sc,textOf(e));
918
919         case COND     : return ap(COND,pmcTriple(co,sc,snd(e)));
920
921         case AP       : return pmcPair(co,sc,e);
922
923 #if NPLUSK
924         case ADDPAT   :
925 #endif
926 #if TREX
927         case EXT      :
928 #endif
929         case TUPLE    :
930         case NAME     :
931         case CHARCELL :
932         case INTCELL  :
933         case BIGCELL  :
934         case FLOATCELL:
935         case STRCELL  : break;
936
937         default       : internal("pmcTerm");
938                         break;
939     }
940     return e;
941 }
942
943 static Cell local pmcPair(co,sc,pr)    /* apply pattern matching compiler  */
944 Int  co;                               /* to a pair of exprs               */
945 List sc;
946 Pair pr; {
947     return pair(pmcTerm(co,sc,fst(pr)),
948                 pmcTerm(co,sc,snd(pr)));
949 }
950
951 static Cell local pmcTriple(co,sc,tr)  /* apply pattern matching compiler  */
952 Int    co;                             /* to a triple of exprs             */
953 List   sc;
954 Triple tr; {
955     return triple(pmcTerm(co,sc,fst3(tr)),
956                   pmcTerm(co,sc,snd3(tr)),
957                   pmcTerm(co,sc,thd3(tr)));
958 }
959
960 static Cell local pmcVar(sc,t)         /* find translation of variable     */
961 List sc;                               /* in current scope                 */
962 Text t; {
963     List xs;
964     Name n;
965
966     for (xs=sc; nonNull(xs); xs=tl(xs)) {
967         Cell x = hd(xs);
968         if (t==textOf(fst(x))) {
969             if (isOffset(snd(x))) {                  /* local variable ... */
970                 if (snd(x)<=freeBegin && !cellIsMember(snd(x),freeVars))
971                     freeVars = cons(snd(x),freeVars);
972                 return snd(x);
973             }
974             else {                                   /* local function ... */
975                 if (!cellIsMember(snd(x),freeFuns))
976                     freeFuns = cons(snd(x),freeFuns);
977                 return fst3(snd(x));
978             }
979         }
980     }
981
982     if (isNull(n=findName(t)))         /* Lookup global name - the only way*/
983         n = newName(t,currentName);    /* this (should be able to happen)  */
984                                        /* is with new global var introduced*/
985                                        /* after type check; e.g. remPat1   */
986     return n;
987 }
988
989 static Void local pmcLetrec(co,sc,e)   /* apply pattern matching compiler  */
990 Int  co;                               /* to LETREC, splitting decls into  */
991 List sc;                               /* two sections                     */
992 Pair e; {
993     List fs = NIL;                     /* local function definitions       */
994     List vs = NIL;                     /* local variable definitions       */
995     List ds;
996
997     for (ds=fst(e); nonNull(ds); ds=tl(ds)) {      /* Split decls into two */
998         Cell v     = fst(hd(ds));
999         Int  arity = length(fst(hd(snd(hd(ds)))));
1000
1001         if (arity==0) {                            /* Variable declaration */
1002             vs = cons(snd(hd(ds)),vs);
1003             sc = cons(pair(v,mkOffset(++co)),sc);
1004         }
1005         else {                                     /* Function declaration */
1006             fs = cons(triple(inventVar(),mkInt(arity),snd(hd(ds))),fs);
1007             sc = cons(pair(v,hd(fs)),sc);
1008         }
1009     }
1010     vs       = rev(vs);                /* Put declaration lists back in    */
1011     fs       = rev(fs);                /* original order                   */
1012     fst(e)   = pair(vs,fs);            /* Store declaration lists          */
1013     map2Over(pmcVarDef,co,sc,vs);      /* Translate variable definitions   */
1014     map2Proc(pmcFunDef,co,sc,fs);      /* Translate function definitions   */
1015     snd(e)   = pmcTerm(co,sc,snd(e));  /* Translate LETREC body            */
1016     freeFuns = diffList(freeFuns,fs);  /* Delete any `freeFuns' bound in fs*/
1017 }
1018
1019 static Cell local pmcVarDef(co,sc,vd)  /* apply pattern matching compiler  */
1020 Int  co;                               /* to variable definition           */
1021 List sc;
1022 List vd; {                             /* vd :: [ ([], rhs) ]              */
1023     Cell d = snd(hd(vd));
1024     if (nonNull(tl(vd)) && canFail(d))
1025         return ap(FATBAR,pair(pmcTerm(co,sc,d),
1026                               pmcVarDef(co,sc,tl(vd))));
1027     return pmcTerm(co,sc,d);
1028 }
1029
1030 static Void local pmcFunDef(co,sc,fd)  /* apply pattern matching compiler  */
1031 Int    co;                             /* to function definition           */
1032 List   sc;
1033 Triple fd; {                           /* fd :: (Var, Arity, [Alt])        */
1034     Offset saveFreeBegin = freeBegin;
1035     List   saveFreeVars  = freeVars;
1036     List   saveFreeFuns  = freeFuns;
1037     Int    arity         = intOf(snd3(fd));
1038     Cell   temp          = altsMatch(co+1,arity,sc,thd3(fd));
1039     Cell   xs;
1040
1041     freeBegin = mkOffset(co);
1042     freeVars  = NIL;
1043     freeFuns  = NIL;
1044     temp      = match(co+arity,temp);
1045     thd3(fd)  = triple(freeVars,freeFuns,temp);
1046
1047     for (xs=freeVars; nonNull(xs); xs=tl(xs))
1048         if (hd(xs)<=saveFreeBegin && !cellIsMember(hd(xs),saveFreeVars))
1049             saveFreeVars = cons(hd(xs),saveFreeVars);
1050
1051     for (xs=freeFuns; nonNull(xs); xs=tl(xs))
1052         if (!cellIsMember(hd(xs),saveFreeFuns))
1053             saveFreeFuns = cons(hd(xs),saveFreeFuns);
1054
1055     freeBegin = saveFreeBegin;
1056     freeVars  = saveFreeVars;
1057     freeFuns  = saveFreeFuns;
1058 }
1059
1060 /* ---------------------------------------------------------------------------
1061  * Main part of pattern matching compiler: convert [Alt] to case constructs
1062  *
1063  * This section of Hugs has been almost completely rewritten to be more
1064  * general, in particular, to allow pattern matching in orders other than the
1065  * strictly left-to-right approach of the previous version.  This is needed
1066  * for the implementation of the so-called Haskell 1.3 `record' syntax.
1067  *
1068  * At each stage, the different branches for the cases to be considered
1069  * are represented by a list of values of type:
1070  *   Match ::= { maPats :: [Pat],       patterns to match
1071  *               maOffs :: [Offs],      offsets of corresponding values
1072  *               maSc   :: Scope,       mapping from vars to offsets
1073  *               maRhs  :: Rhs }        right hand side
1074  * [Implementation uses nested pairs, ((pats,offs),(sc,rhs)).]
1075  *
1076  * The Scope component has type:
1077  *   Scope  ::= [(Var,Expr)]
1078  * and provides a mapping from variable names to offsets used in the matching
1079  * process.
1080  *
1081  * Matches can be normalized by reducing them to a form in which the list
1082  * of patterns is empty (in which case the match itself is described as an
1083  * empty match), or in which the list is non-empty and the first pattern is
1084  * one that requires either a CASE or NUMCASE (or EXTCASE) to decompose.
1085  * ------------------------------------------------------------------------*/
1086
1087 #define mkMatch(ps,os,sc,r)     pair(pair(ps,os),pair(sc,r))
1088 #define maPats(ma)              fst(fst(ma))
1089 #define maOffs(ma)              snd(fst(ma))
1090 #define maSc(ma)                fst(snd(ma))
1091 #define maRhs(ma)               snd(snd(ma))
1092 #define extSc(v,o,ma)           maSc(ma) = cons(pair(v,o),maSc(ma))
1093
1094 static List local altsMatch(co,n,sc,as) /* Make a list of matches from list*/
1095 Int  co;                                /* of Alts, with initial offsets   */
1096 Int  n;                                 /* reverse (take n [co..])         */
1097 List sc;
1098 List as; {
1099     List mas = NIL;
1100     List us  = NIL;
1101     for (; n>0; n--)
1102         us = cons(mkOffset(co++),us);
1103     for (; nonNull(as); as=tl(as))      /* Each Alt is ([Pat], Rhs)        */
1104         mas = cons(mkMatch(fst(hd(as)),us,sc,snd(hd(as))),mas);
1105     return rev(mas);
1106 }
1107
1108 static Cell local match(co,mas) /* Generate case statement for Matches mas */
1109 Int  co;                        /* at current offset co                    */
1110 List mas; {                     /* N.B. Assumes nonNull(mas).              */
1111     Cell srhs = NIL;            /* Rhs for selected matches                */
1112     List smas = mas;            /* List of selected matches                */
1113     mas       = tl(mas);
1114     tl(smas)  = NIL;
1115
1116     if (emptyMatch(hd(smas))) {         /* The case for empty matches:     */
1117         while (nonNull(mas) && emptyMatch(hd(mas))) {
1118             List temp = tl(mas);
1119             tl(mas)   = smas;
1120             smas      = mas;
1121             mas       = temp;
1122         }
1123         srhs = joinMas(co,rev(smas));
1124     }
1125     else {                              /* Non-empty match                 */
1126         Int  o = offsetOf(hd(maOffs(hd(smas))));
1127         Cell d = maDiscr(hd(smas));
1128         if (isNumDiscr(d)) {            /* Numeric match                   */
1129             Int  da = discrArity(d);
1130             Cell d1 = pmcTerm(co,maSc(hd(smas)),d);
1131             while (nonNull(mas) && !emptyMatch(hd(mas))
1132                                 && o==offsetOf(hd(maOffs(hd(mas))))
1133                                 && isNumDiscr(d=maDiscr(hd(mas)))
1134                                 && eqNumDiscr(d,d1)) {
1135                 List temp = tl(mas);
1136                 tl(mas)   = smas;
1137                 smas      = mas;
1138                 mas       = temp;
1139             }
1140             smas = rev(smas);
1141             map2Proc(advance,co,da,smas);
1142             srhs = ap(NUMCASE,triple(mkOffset(o),d1,match(co+da,smas)));
1143         }
1144 #if TREX
1145         else if (isExtDiscr(d)) {       /* Record match                    */
1146             Int  da = discrArity(d);
1147             Cell d1 = pmcTerm(co,maSc(hd(smas)),d);
1148             while (nonNull(mas) && !emptyMatch(hd(mas))
1149                                 && o==offsetOf(hd(maOffs(hd(mas))))
1150                                 && isExtDiscr(d=maDiscr(hd(mas)))
1151                                 && eqExtDiscr(d,d1)) {
1152                 List temp = tl(mas);
1153                 tl(mas)   = smas;
1154                 smas      = mas;
1155                 mas       = temp;
1156             }
1157             smas = rev(smas);
1158             map2Proc(advance,co,da,smas);
1159             srhs = ap(EXTCASE,triple(mkOffset(o),d1,match(co+da,smas)));
1160         }
1161 #endif
1162         else {                          /* Constructor match               */
1163             List tab = addConTable(d,hd(smas),NIL);
1164             Int  da;
1165             while (nonNull(mas) && !emptyMatch(hd(mas))
1166                                 && o==offsetOf(hd(maOffs(hd(mas))))
1167                                 && !isNumDiscr(d=maDiscr(hd(mas)))) {
1168                 tab = addConTable(d,hd(mas),tab);
1169                 mas = tl(mas);
1170             }
1171             for (tab=rev(tab); nonNull(tab); tab=tl(tab)) {
1172                 d    = fst(hd(tab));
1173                 smas = snd(hd(tab));
1174                 da   = discrArity(d);
1175                 map2Proc(advance,co,da,smas);
1176                 srhs = cons(pair(d,match(co+da,smas)),srhs);
1177             }
1178             srhs = ap(CASE,pair(mkOffset(o),srhs));
1179         }
1180     }
1181     return nonNull(mas) ? ap(FATBAR,pair(srhs,match(co,mas))) : srhs;
1182 }
1183
1184 static Cell local joinMas(co,mas)       /* Combine list of matches into rhs*/
1185 Int  co;                                /* using FATBARs as necessary      */
1186 List mas; {                             /* Non-empty list of empty matches */
1187     Cell ma  = hd(mas);
1188     Cell rhs = pmcTerm(co,maSc(ma),maRhs(ma));
1189     if (nonNull(tl(mas)) && canFail(rhs))
1190         return ap(FATBAR,pair(rhs,joinMas(co,tl(mas))));
1191     else
1192         return rhs;
1193 }
1194
1195 static Bool local canFail(rhs)         /* Determine if expression (as rhs) */
1196 Cell rhs; {                            /* might ever be able to fail       */
1197     switch (whatIs(rhs)) {
1198         case LETREC  : return canFail(snd(snd(rhs)));
1199         case GUARDED : return TRUE;    /* could get more sophisticated ..? */
1200         default      : return FALSE;
1201     }
1202 }
1203
1204 /* type Table a b = [(a, [b])]
1205  *
1206  * addTable                 :: a -> b -> Table a b -> Table a b
1207  * addTable x y []           = [(x,[y])]
1208  * addTable x y (z@(n,sws):zs)
1209  *              | n == x     = (n,sws++[y]):zs
1210  *              | otherwise  = (n,sws):addTable x y zs
1211  */
1212
1213 static List local addConTable(x,y,tab) /* add element (x,y) to table       */
1214 Cell x, y;
1215 List tab; {
1216     if (isNull(tab))
1217         return singleton(pair(x,singleton(y)));
1218     else if (fst(hd(tab))==x)
1219         snd(hd(tab)) = appendOnto(snd(hd(tab)),singleton(y));
1220     else
1221         tl(tab) = addConTable(x,y,tl(tab));
1222
1223     return tab;
1224 }
1225
1226 static Void local advance(co,a,ma)      /* Advance non-empty match by      */
1227 Int  co;                                /* processing head pattern         */
1228 Int  a;                                 /* discriminator arity             */
1229 Cell ma; {
1230     Cell p  = hd(maPats(ma));
1231     List ps = tl(maPats(ma));
1232     List us = tl(maOffs(ma));
1233     if (whatIs(p)==CONFLDS) {           /* Special case for record syntax  */
1234         Name c  = fst(snd(p));
1235         List fs = snd(snd(p));
1236         List qs = NIL;
1237         List vs = NIL;
1238         for (; nonNull(fs); fs=tl(fs)) {
1239             vs = cons(mkOffset(co+a+1-sfunPos(fst(hd(fs)),c)),vs);
1240             qs = cons(snd(hd(fs)),qs);
1241         }
1242         ps = revOnto(qs,ps);
1243         us = revOnto(vs,us);
1244     }
1245     else                                /* Normally just spool off patterns*/
1246         for (; a>0; --a) {              /* and corresponding offsets ...   */
1247             us = cons(mkOffset(++co),us);
1248             ps = cons(arg(p),ps);
1249             p  = fun(p);
1250         }
1251
1252     maPats(ma) = ps;
1253     maOffs(ma) = us;
1254 }
1255
1256 /* --------------------------------------------------------------------------
1257  * Normalize and test for empty match:
1258  * ------------------------------------------------------------------------*/
1259
1260 static Bool local emptyMatch(ma)/* Normalize and test to see if a given    */
1261 Cell ma; {                      /* match, ma, is empty.                    */
1262
1263     while (nonNull(maPats(ma))) {
1264         Cell p;
1265 tidyHd: switch (whatIs(p=hd(maPats(ma)))) {
1266             case LAZYPAT   : {   Cell nv   = inventVar();
1267                                  maRhs(ma) = ap(LETREC,
1268                                                 pair(remPat(snd(p),nv,NIL),
1269                                                      maRhs(ma)));
1270                                  p         = nv;
1271                              }
1272                              /* intentional fall-thru */
1273             case VARIDCELL :
1274             case VAROPCELL :
1275             case DICTVAR   : extSc(p,hd(maOffs(ma)),ma);
1276             case WILDCARD  : maPats(ma) = tl(maPats(ma));
1277                              maOffs(ma) = tl(maOffs(ma));
1278                              continue;
1279
1280             /* So-called "as-patterns"are really just pattern intersections:
1281              *    (p1@p2:ps, o:os, sc, e) ==> (p1:p2:ps, o:o:os, sc, e)
1282              * (But the input grammar probably doesn't let us take
1283              * advantage of this, so we stick with the special case
1284              * when p1 is a variable.)
1285              */
1286             case ASPAT     : extSc(fst(snd(p)),hd(maOffs(ma)),ma);
1287                              hd(maPats(ma)) = snd(snd(p));
1288                              goto tidyHd;
1289
1290             case FINLIST   : hd(maPats(ma)) = mkConsList(snd(p));
1291                              return FALSE;
1292
1293             case STRCELL   : {   String s = textToStr(textOf(p));
1294                                  for (p=NIL; *s!='\0'; ++s) {
1295                                      if (*s!='\\' || *++s=='\\')
1296                                          p = ap(consChar(*s),p);
1297                                      else
1298                                          p = ap(consChar('\0'),p);
1299                                  }
1300                                  hd(maPats(ma)) = revOnto(p,nameNil);
1301                              }
1302                              return FALSE;
1303
1304             case AP        : if (isName(fun(p)) && isCfun(fun(p))
1305                                  && cfunOf(fun(p))==0
1306                                  && name(fun(p)).defn==nameId) {
1307                                   hd(maPats(ma)) = arg(p);
1308                                   goto tidyHd;
1309                              }
1310                              /* intentional fall-thru */
1311             case CHARCELL  :
1312             case NAME      :
1313             case CONFLDS   :
1314                              return FALSE;
1315
1316             default        : internal("emptyMatch");
1317         }
1318     }
1319     return TRUE;
1320 }
1321
1322 /* --------------------------------------------------------------------------
1323  * Discriminators:
1324  * ------------------------------------------------------------------------*/
1325
1326 static Cell local maDiscr(ma)   /* Get the discriminator for a non-empty   */
1327 Cell ma; {                      /* match, ma.                              */
1328     Cell p = hd(maPats(ma));
1329     Cell h = getHead(p);
1330     switch (whatIs(h)) {
1331         case CONFLDS : return fst(snd(p));
1332 #if NPLUSK
1333         case ADDPAT  : arg(fun(p)) = translate(arg(fun(p)));
1334                        return fun(p);
1335 #endif
1336 #if TREX
1337         case EXT     : h      = fun(fun(p));
1338                        arg(h) = translate(arg(h));
1339                        return h;
1340 #endif
1341         case NAME    : if (h==nameFromInt || h==nameFromInteger
1342                                           || h==nameFromDouble) {
1343                            if (argCount==2)
1344                                arg(fun(p)) = translate(arg(fun(p)));
1345                            return p;
1346                        }
1347     }
1348     return h;
1349 }
1350
1351 static Bool local isNumDiscr(d) /* TRUE => numeric discriminator           */
1352 Cell d; {
1353     switch (whatIs(d)) {
1354         case NAME      :
1355         case TUPLE     :
1356         case CHARCELL  : return FALSE;
1357
1358 #if TREX
1359         case AP        : return !isExt(fun(d));
1360 #else
1361         case AP        : return TRUE;   /* must be a literal or (n+k)      */
1362 #endif
1363     }
1364     internal("isNumDiscr");
1365     return 0;/*NOTREACHED*/
1366 }
1367
1368 Int discrArity(d)                      /* Find arity of discriminator      */
1369 Cell d; {
1370     switch (whatIs(d)) {
1371         case NAME      : return name(d).arity;
1372         case TUPLE     : return tupleOf(d);
1373         case CHARCELL  : return 0;
1374 #if TREX
1375         case AP        : switch (whatIs(fun(d))) {
1376 #if NPLUSK
1377                              case ADDPAT : return 1;
1378 #endif
1379                              case EXT    : return 2;
1380                              default     : return 0;
1381                          }
1382 #else
1383 #if NPLUSK
1384         case AP        : return (whatIs(fun(d))==ADDPAT) ? 1 : 0;
1385 #else
1386         case AP        : return 0;      /* must be an Int or Float lit     */
1387 #endif
1388 #endif
1389     }
1390     internal("discrArity");
1391     return 0;/*NOTREACHED*/
1392 }
1393
1394 static Bool local eqNumDiscr(d1,d2)     /* Determine whether two numeric   */
1395 Cell d1, d2; {                          /* descriptors have same value     */
1396 #if NPLUSK
1397     if (whatIs(fun(d1))==ADDPAT)
1398         return whatIs(fun(d2))==ADDPAT && snd(fun(d1))==snd(fun(d2));
1399 #endif
1400     if (isInt(arg(d1)))
1401         return isInt(arg(d2)) && intOf(arg(d1))==intOf(arg(d2));
1402     if (isFloat(arg(d1)))
1403         return isFloat(arg(d2)) && floatOf(arg(d1))==floatOf(arg(d2));
1404     internal("eqNumDiscr");
1405     return FALSE;/*NOTREACHED*/
1406 }
1407
1408 #if TREX
1409 static Bool local isExtDiscr(d)         /* Test of extension discriminator */
1410 Cell d; {
1411     return isAp(d) && isExt(fun(d));
1412 }
1413
1414 static Bool local eqExtDiscr(d1,d2)     /* Determine whether two extension */
1415 Cell d1, d2; {                          /* discriminators have same label  */
1416     return fun(d1)==fun(d2);
1417 }
1418 #endif
1419
1420 /*-------------------------------------------------------------------------*/
1421
1422
1423
1424 /* --------------------------------------------------------------------------
1425  * STG stuff
1426  * ------------------------------------------------------------------------*/
1427
1428 static Void local stgCGBinds( List );
1429
1430 static Void local stgCGBinds(binds)
1431 List binds; {
1432     cgBinds(binds);
1433 }
1434
1435 /* --------------------------------------------------------------------------
1436  * Main entry points to compiler:
1437  * ------------------------------------------------------------------------*/
1438
1439 static List addGlobals( List binds )
1440 {
1441     /* stgGlobals = list of top-level STG binds */
1442     for(;nonNull(stgGlobals);stgGlobals=tl(stgGlobals)) {
1443         StgVar bind = snd(hd(stgGlobals));
1444         if (nonNull(stgVarBody(bind))) {
1445             binds = cons(bind,binds);
1446         }
1447     }
1448     return binds;
1449 }
1450
1451 typedef void (*sighandler_t)(int);
1452 void eval_ctrlbrk ( int dunnowhat )
1453 {
1454    interruptStgRts();
1455    /* reinstall the signal handler so that further interrupts which
1456       happen before the thread can return to the scheduler, lead back
1457       here rather than invoking the previous break handler. */
1458    signal(SIGINT, eval_ctrlbrk);
1459 }
1460
1461 Void evalExp() {                    /* compile and run input expression    */
1462     /* ToDo: this name (and other names generated during pattern match?)
1463      * get inserted in the symbol table but never get removed.
1464      */
1465     Name n = newName(inventText(),NIL);
1466     Cell e;
1467     StgVar v = mkStgVar(NIL,NIL);
1468     name(n).stgVar = v;
1469     compiler(RESET);
1470     e = pmcTerm(0,NIL,translate(inputExpr));
1471     stgDefn(n,0,e);
1472     inputExpr = NIL;
1473     stgCGBinds(addGlobals(singleton(v)));
1474     
1475     /* Run thread (and any other runnable threads) */
1476
1477     /* Re-initialise the scheduler - ToDo: do I need this? */
1478     initScheduler();
1479 #ifdef CRUDE_PROFILING
1480     cp_init();
1481 #endif
1482
1483     /* ToDo: don't really initScheduler every time.  fix */
1484     {
1485         HaskellObj      result; /* ignored */
1486         sighandler_t    old_ctrlbrk;
1487         SchedulerStatus status;
1488         old_ctrlbrk    = signal(SIGINT, eval_ctrlbrk);
1489         assert(old_ctrlbrk != SIG_ERR);
1490         status         = rts_eval_(closureOfVar(v),10000,&result);
1491         signal(SIGINT,old_ctrlbrk);
1492         switch (status) {
1493         case Deadlock:
1494         case AllBlocked: /* I don't understand the distinction - ADR */
1495                 printf("{Deadlock}");
1496                 RevertCAFs();
1497                 break;
1498         case Interrupted:
1499                 printf("{Interrupted}");
1500                 RevertCAFs();
1501                 break;
1502         case Killed:
1503                 printf("{Killed}");
1504                 RevertCAFs();
1505                 break;
1506         case Success:
1507           //fflush(stderr);fflush(stdout);
1508           //fprintf(stderr, "\n\nFinal top-of-stack is\n" );
1509           //printObj ( *(MainRegTable.rSp) );
1510                 RevertCAFs();
1511                 break;
1512         default:
1513                 internal("evalExp: Unrecognised SchedulerStatus");
1514         }
1515         fflush(stdout);
1516         fflush(stderr);
1517     }
1518 #ifdef CRUDE_PROFILING
1519     cp_show();
1520 #endif
1521
1522 }
1523
1524
1525 static List local addStgVar( List binds, Pair bind )
1526 {
1527     StgVar nv = mkStgVar(NIL,NIL);
1528     Text   t  = textOf(fst(bind));
1529     Name   n  = findName(t);
1530
1531     if (isNull(n)) {                   /* Lookup global name - the only way*/
1532         n = newName(t,NIL);            /* this (should be able to happen)  */
1533     }                                  /* is with new global var introduced*/
1534                                        /* after type check; e.g. remPat1   */
1535     name(n).stgVar = nv;
1536     return cons(nv,binds);
1537 }
1538
1539
1540 Void compileDefns() {                  /* compile script definitions       */
1541     Target t = length(valDefns) + length(genDefns) + length(selDefns);
1542     Target i = 0;
1543     List binds = NIL;
1544
1545     /* a nasty hack.  But I don't know an easier way to make */
1546     /* these things appear.                                  */
1547     if (lastModule() == modulePrelude) {
1548        implementCfun ( nameCons, NIL );
1549        implementCfun ( nameNil, NIL );
1550        implementCfun ( nameUnit, NIL );
1551     }
1552
1553     {
1554         List vss;
1555         List vs;
1556         for(vs=genDefns; nonNull(vs); vs=tl(vs)) {
1557             Name   n  = hd(vs);
1558             StgVar nv = mkStgVar(NIL,NIL);
1559             assert(isName(n));
1560             name(n).stgVar = nv;
1561             binds = cons(nv,binds);
1562         }
1563         for(vss=selDefns; nonNull(vss); vss=tl(vss)) {
1564             for(vs=hd(vss); nonNull(vs); vs=tl(vs)) {
1565                 Pair p = hd(vs);
1566                 Name n = fst(p);
1567                 StgVar nv = mkStgVar(NIL,NIL);
1568                 assert(isName(n));
1569                 name(n).stgVar = nv;
1570                 binds = cons(nv,binds);
1571             }
1572         }
1573     }
1574
1575     setGoal("Translating",t);
1576     /* do valDefns before everything else so that all stgVar's get added. */
1577     for (; nonNull(valDefns); valDefns=tl(valDefns)) {
1578         hd(valDefns) = transBinds(hd(valDefns));
1579         mapAccum(addStgVar,binds,hd(valDefns));
1580         mapProc(compileGlobalFunction,hd(valDefns));
1581         soFar(i++);
1582     }
1583     for (; nonNull(genDefns); genDefns=tl(genDefns)) {
1584         compileGenFunction(hd(genDefns));
1585         soFar(i++);
1586     }
1587     for (; nonNull(selDefns); selDefns=tl(selDefns)) {
1588         mapOver(compileSelFunction,hd(selDefns));
1589         soFar(i++);
1590     }
1591
1592     binds = addGlobals(binds);
1593     done();
1594 #if USE_HUGS_OPTIMIZER
1595     if (optimise) {
1596        t = length(binds);
1597        setGoal("Simplifying",t);
1598        optimiseTopBinds(binds);
1599        done();
1600     }
1601 #endif
1602     setGoal("Generating code",t);
1603     stgCGBinds(binds);
1604
1605     done();
1606 }
1607
1608 static Void local compileGlobalFunction(bind)
1609 Pair bind; {
1610     Name n     = findName(textOf(fst(bind)));
1611     List defs  = snd(bind);
1612     Int  arity = length(fst(hd(defs)));
1613     assert(isName(n));
1614     compiler(RESET);
1615     stgDefn(n,arity,match(arity,altsMatch(1,arity,NIL,defs)));
1616 }
1617
1618 static Void local compileGenFunction(n) /* Produce code for internally     */
1619 Name n; {                               /* generated function              */
1620     List defs  = name(n).defn;
1621     Int  arity = length(fst(hd(defs)));
1622     compiler(RESET);
1623     currentName = n;
1624     mapProc(transAlt,defs);
1625     stgDefn(n,arity,match(arity,altsMatch(1,arity,NIL,defs)));
1626     name(n).defn = NIL;
1627 }
1628
1629 static Name local compileSelFunction(p) /* Produce code for selector func  */
1630 Pair p; {                               /* Should be merged with genDefns, */
1631     Name s     = fst(p);                /* but the name(_).defn field is   */
1632     List defs  = snd(p);                /* already used for other purposes */
1633     Int  arity = length(fst(hd(defs))); /* in selector functions.          */
1634
1635     compiler(RESET);
1636     mapProc(transAlt,defs);
1637     stgDefn(s,arity,match(arity,altsMatch(1,arity,NIL,defs)));
1638     return s;
1639 }
1640
1641
1642 /* --------------------------------------------------------------------------
1643  * Compiler control:
1644  * ------------------------------------------------------------------------*/
1645
1646 Void compiler(what)
1647 Int what; {
1648     switch (what) {
1649         case INSTALL :
1650         case RESET   : freeVars      = NIL;
1651                        freeFuns      = NIL;
1652                        freeBegin     = mkOffset(0);
1653                        //extraVars     = NIL;
1654                        //numExtraVars  = 0;
1655                        //localOffset   = 0;
1656                        //localArity    = 0;
1657                        break;
1658
1659         case MARK    : mark(freeVars);
1660                        mark(freeFuns);
1661                        //mark(extraVars);
1662                        break;
1663     }
1664 }
1665
1666 /*-------------------------------------------------------------------------*/