[project @ 1999-07-14 10:01:43 by simonmar]
[ghc-hetmet.git] / ghc / interpreter / derive.c
1
2 /* --------------------------------------------------------------------------
3  * Deriving
4  *
5  * Copyright (c) The University of Nottingham and Yale University, 1994-1997.
6  * All rights reserved. See NOTICE for details and conditions of use etc...
7  * Hugs version 1.4, December 1997
8  *
9  * $RCSfile: derive.c,v $
10  * $Revision: 1.6 $
11  * $Date: 1999/04/27 10:06:50 $
12  * ------------------------------------------------------------------------*/
13
14 #include "prelude.h"
15 #include "storage.h"
16 #include "backend.h"
17 #include "connect.h"
18 #include "errors.h"
19 #include "Assembler.h"
20 #include "link.h"
21
22 List cfunSfuns;                        /* List of (Cfun,[SelectorVar])    */
23
24 /* --------------------------------------------------------------------------
25  * local function prototypes:
26  * ------------------------------------------------------------------------*/
27
28 static List  local getDiVars            Args((Int));
29 static Cell  local mkBind               Args((String,List));
30 static Cell  local mkVarAlts            Args((Int,Cell));
31 static List  local makeDPats2           Args((Cell,Int));
32 static Bool  local isEnumType           Args((Tycon));
33 static Pair   local mkAltEq             Args((Int,List));
34 static Pair   local mkAltOrd            Args((Int,List));
35 static Cell   local prodRange           Args((Int,List,Cell,Cell,Cell));
36 static Cell   local prodIndex           Args((Int,List,Cell,Cell,Cell));
37 static Cell   local prodInRange         Args((Int,List,Cell,Cell,Cell));
38 static List   local mkIxBinds           Args((Int,Cell,Int));
39 static Cell   local mkAltShow           Args((Int,Cell,Int));
40 static Cell   local showsPrecRhs        Args((Cell,Cell,Int));
41 static Cell   local mkReadCon           Args((Name,Cell,Cell));
42 static Cell   local mkReadPrefix        Args((Cell));
43 static Cell   local mkReadInfix         Args((Cell));
44 static Cell   local mkReadTuple         Args((Cell));
45 static Cell   local mkReadRecord        Args((Cell,List));
46 static List   local mkBndBinds          Args((Int,Cell,Int));
47
48
49 /* --------------------------------------------------------------------------
50  * Deriving Utilities
51  * ------------------------------------------------------------------------*/
52
53 List diVars = NIL;                      /* Acts as a cache of invented vars*/
54 Int  diNum  = 0;
55
56 static List local getDiVars(n)          /* get list of at least n vars for */
57 Int n; {                                /* derived instance generation     */
58     for (; diNum<n; diNum++) {
59         diVars = cons(inventVar(),diVars);
60     }
61     return diVars;
62 }
63
64 static Cell local mkBind(s,alts)        /* make a binding for a variable   */
65 String s;
66 List   alts; {
67     return pair(mkVar(findText(s)),pair(NIL,alts));
68 }
69
70 static Cell local mkVarAlts(line,r)     /* make alts for binding a var to  */
71 Int  line;                              /* a simple expression             */
72 Cell r; {
73     return singleton(pair(NIL,pair(mkInt(line),r)));
74 }
75
76 static List local makeDPats2(h,n)       /* generate pattern list           */
77 Cell h;                                 /* by putting two new patterns with*/
78 Int  n; {                               /* head h and new var components   */
79     List us = getDiVars(2*n);
80     List vs = NIL;
81     Cell p;
82     Int  i;
83
84     for (i=0, p=h; i<n; ++i) {          /* make first version of pattern   */
85         p  = ap(p,hd(us));
86         us = tl(us);
87     }
88     vs = cons(p,vs);
89
90     for (i=0, p=h; i<n; ++i) {          /* make second version of pattern  */
91         p  = ap(p,hd(us));
92         us = tl(us);
93     }
94     return cons(p,vs);
95 }
96
97 static Bool local isEnumType(t) /* Determine whether t is an enumeration   */
98 Tycon t; {                      /* type (i.e. all constructors arity == 0) */
99     if (isTycon(t) && (tycon(t).what==DATATYPE || tycon(t).what==NEWTYPE)) {
100         List cs = tycon(t).defn;
101         for (; hasCfun(cs); cs=tl(cs)) {
102             if (name(hd(cs)).arity!=0) {
103                 return FALSE;
104             }
105         }
106         /* ToDo: correct?  addCfunTable(t); */
107         return TRUE;
108     }
109     return FALSE;
110 }
111
112
113 /* --------------------------------------------------------------------------
114  * Given a datatype:   data T a b = A a b | B Int | C  deriving (Eq, Ord)
115  * The derived definitions of equality and ordering are given by:
116  *
117  *   A a b == A x y  =  a==x && b==y
118  *   B a   == B x    =  a==x
119  *   C     == C      =  True
120  *   _     == _      =  False
121  *
122  *   compare (A a b) (A x y) =  primCompAux a x (compare b y)
123  *   compare (B a)   (B x)   =  compare a x
124  *   compare C       C       =  EQ
125  *   compare a       x       =  cmpConstr a x
126  *
127  * In each case, the last line is only needed if there are multiple
128  * constructors in the datatype definition.
129  * ------------------------------------------------------------------------*/
130
131 static Pair  local mkAltEq              Args((Int,List));
132
133 List deriveEq(t)                        /* generate binding for derived == */
134 Type t; {                               /* for some TUPLE or DATATYPE t    */
135     List alts = NIL;
136     if (isTycon(t)) {                   /* deal with type constrs          */
137         List cs = tycon(t).defn;
138         for (; hasCfun(cs); cs=tl(cs)) {
139             alts = cons(mkAltEq(tycon(t).line,
140                                 makeDPats2(hd(cs),userArity(hd(cs)))),
141                         alts);
142         }
143         if (cfunOf(hd(tycon(t).defn))!=0) {
144             alts = cons(pair(cons(WILDCARD,cons(WILDCARD,NIL)),
145                              pair(mkInt(tycon(t).line),nameFalse)),alts);
146         }
147         alts = rev(alts);
148     } else {                            /* special case for tuples         */
149         alts = singleton(mkAltEq(0,makeDPats2(t,tupleOf(t))));
150     }
151     return singleton(mkBind("==",alts));
152 }
153
154 static Pair local mkAltEq(line,pats)    /* make alt for an equation for == */
155 Int  line;                              /* using patterns in pats for lhs  */
156 List pats; {                            /* arguments                       */
157     Cell p = hd(pats);
158     Cell q = hd(tl(pats));
159     Cell e = nameTrue;
160
161     if (isAp(p)) {
162         e = ap2(nameEq,arg(p),arg(q));
163         for (p=fun(p), q=fun(q); isAp(p); p=fun(p), q=fun(q)) {
164             e = ap2(nameAnd,ap2(nameEq,arg(p),arg(q)),e);
165         }
166     }
167     return pair(pats,pair(mkInt(line),e));
168 }
169
170
171 static Pair  local mkAltOrd             Args((Int,List));
172
173 List deriveOrd(t)                       /* make binding for derived compare*/
174 Type t; {                               /* for some TUPLE or DATATYPE t    */
175     List alts = NIL;
176     if (isEnumType(t)) {                /* special case for enumerations   */
177         Cell u = inventVar();
178         Cell w = inventVar();
179         Cell rhs = NIL;
180         if (cfunOf(hd(tycon(t).defn))!=0) {
181             implementConToTag(t);
182             rhs = ap2(nameCompare,
183                       ap(tycon(t).conToTag,u),
184                       ap(tycon(t).conToTag,w));
185         } else {
186             rhs = nameEQ;
187         }
188         alts = singleton(pair(doubleton(u,w),pair(mkInt(tycon(t).line),rhs)));
189     } else if (isTycon(t)) {            /* deal with type constrs          */
190         List cs = tycon(t).defn;
191         for (; hasCfun(cs); cs=tl(cs)) {
192             alts = cons(mkAltOrd(tycon(t).line,
193                                  makeDPats2(hd(cs),userArity(hd(cs)))),
194                         alts);
195         }
196         if (cfunOf(hd(tycon(t).defn))!=0) {
197             Cell u = inventVar();
198             Cell w = inventVar();
199             implementConToTag(t);
200             alts   = cons(pair(doubleton(u,w),
201                                pair(mkInt(tycon(t).line),
202                                     ap2(nameCompare,
203                                         ap(tycon(t).conToTag,u),
204                                         ap(tycon(t).conToTag,w)))),
205                           alts);
206         }
207         alts = rev(alts);
208     } else {                            /* special case for tuples         */
209         alts = singleton(mkAltOrd(0,makeDPats2(t,tupleOf(t))));
210     }
211     return singleton(mkBind("compare",alts));
212 }
213
214 static Pair local mkAltOrd(line,pats)   /* make alt for eqn for compare    */
215 Int  line;                              /* using patterns in pats for lhs  */
216 List pats; {                            /* arguments                       */
217     Cell p = hd(pats);
218     Cell q = hd(tl(pats));
219     Cell e = nameEQ;
220
221     if (isAp(p)) {
222         e = ap2(nameCompare,arg(p),arg(q));
223         for (p=fun(p), q=fun(q); isAp(p); p=fun(p), q=fun(q)) {
224             e = ap3(nameCompAux,arg(p),arg(q),e);
225         }
226     }
227
228     return pair(pats,pair(mkInt(line),e));
229 }
230
231
232 /* --------------------------------------------------------------------------
233  * Deriving Ix and Enum:
234  * ------------------------------------------------------------------------*/
235
236 List deriveEnum(t)              /* Construct definition of enumeration     */
237 Tycon t; {
238     Int  l     = tycon(t).line;
239     Cell x     = inventVar();
240     Cell y     = inventVar();
241     Cell first = hd(tycon(t).defn);
242     Cell last  = tycon(t).defn;
243
244     if (!isEnumType(t)) {
245         ERRMSG(l) "Can only derive instances of Enum for enumeration types"
246         EEND;
247     }
248     while (hasCfun(tl(last))) {
249         last = tl(last);
250     }
251     last = hd(last);
252     implementConToTag(t);
253     implementTagToCon(t);
254     return cons(mkBind("toEnum",      mkVarAlts(l,tycon(t).tagToCon)),
255            cons(mkBind("fromEnum",    mkVarAlts(l,tycon(t).conToTag)),
256            cons(mkBind("enumFrom",    singleton(pair(singleton(x),  
257                                         pair(mkInt(l),
258                                         ap2(nameFromTo,x,last))))),
259            /* default instance of enumFromTo is good */
260            cons(mkBind("enumFromThen",singleton(pair(doubleton(x,y),
261                                         pair(mkInt(l),
262                                         ap3(nameFromThenTo,x,y,
263                                         ap(COND,triple(ap2(nameLe,x,y),
264                                         last,first))))))),
265            /* default instance of enumFromThenTo is good */
266            NIL))));
267 }
268
269
270 static List  local mkIxBindsEnum        Args((Tycon));
271 static List  local mkIxBinds            Args((Int,Cell,Int));
272 static Cell  local prodRange            Args((Int,List,Cell,Cell,Cell));
273 static Cell  local prodIndex            Args((Int,List,Cell,Cell,Cell));
274 static Cell  local prodInRange          Args((Int,List,Cell,Cell,Cell));
275
276 List deriveIx(t)                /* Construct definition of indexing        */
277 Tycon t; {
278     if (isEnumType(t)) {        /* Definitions for enumerations            */
279         implementConToTag(t);
280         implementTagToCon(t);
281         return mkIxBindsEnum(t);
282     } else if (isTuple(t)) {    /* Definitions for product types           */
283         return mkIxBinds(0,t,tupleOf(t));
284     } else if (isTycon(t) && cfunOf(hd(tycon(t).defn))==0) {
285         return mkIxBinds(tycon(t).line,
286                          hd(tycon(t).defn),
287                          userArity(hd(tycon(t).defn)));
288     }
289     ERRMSG(tycon(t).line)
290         "Can only derive instances of Ix for enumeration or product types"
291     EEND;
292     return NIL;/* NOTREACHED*/
293 }
294
295 /* instance  Ix T  where
296  *     range (c1,c2)       =  map tagToCon [conToTag c1 .. conToTag c2]
297  *     index b@(c1,c2) ci
298  *         | inRange b ci  =  conToTag ci - conToTag c1
299  *         | otherwise     =  error "Ix.index.T: Index out of range."
300  *     inRange (c1,c2) ci  =  conToTag c1 <= i && i <= conToTag c2
301  *                            where i = conToTag ci
302  */
303 static List local mkIxBindsEnum(t)
304 Tycon t; {
305     Int l = tycon(t).line;
306     Name tagToCon = tycon(t).tagToCon;
307     Name conToTag = tycon(t).conToTag;
308     Cell b  = inventVar();
309     Cell c1 = inventVar();
310     Cell c2 = inventVar();
311     Cell ci = inventVar();
312     return cons(mkBind("range",  singleton(pair(singleton(ap2(mkTuple(2),
313                                  c1,c2)), pair(mkInt(l),ap2(nameMap,tagToCon,
314                                  ap2(nameFromTo,ap(conToTag,c1),
315                                  ap(conToTag,c2))))))),
316            cons(mkBind("index",  singleton(pair(doubleton(ap(ASPAT,pair(b,
317                                  ap2(mkTuple(2),c1,c2))),ci), 
318                                  pair(mkInt(l),ap(COND,
319                                  triple(ap2(nameInRange,b,ci),
320                                  ap2(nameMinus,ap(conToTag,ci),
321                                  ap(conToTag,c1)),
322                                  ap(nameError,mkStr(findText(
323                                  "Ix.index: Index out of range"))))))))),
324            cons(mkBind("inRange",singleton(pair(doubleton(ap2(mkTuple(2),
325                                  c1,c2),ci), pair(mkInt(l),ap2(nameAnd,
326                                  ap2(nameLe,ap(conToTag,c1),ap(conToTag,ci)),
327                                  ap2(nameLe,ap(conToTag,ci),
328                                  ap(conToTag,c2))))))), 
329                                         /* ToDo: share conToTag ci         */
330            NIL)));
331 }
332
333 static List local mkIxBinds(line,h,n)   /* build bindings for derived Ix on*/
334 Int  line;                              /* a product type                  */
335 Cell h;
336 Int  n; {
337     List vs   = getDiVars(3*n);
338     Cell ls   = h;
339     Cell us   = h;
340     Cell is   = h;
341     Cell pr   = NIL;
342     Cell pats = NIL;
343     Int  i;
344
345     for (i=0; i<n; ++i, vs=tl(vs)) {    /* build three patterns for values */
346         ls = ap(ls,hd(vs));             /* of the datatype concerned       */
347         us = ap(us,hd(vs=tl(vs)));
348         is = ap(is,hd(vs=tl(vs)));
349     }
350     pr   = ap2(mkTuple(2),ls,us);       /* Build (ls,us)                   */
351     pats = cons(pr,cons(is,NIL));       /* Build [(ls,us),is]              */
352
353     return cons(prodRange(line,singleton(pr),ls,us,is),
354            cons(prodIndex(line,pats,ls,us,is),
355            cons(prodInRange(line,pats,ls,us,is),
356            NIL)));
357 }
358
359 static Cell local prodRange(line,pats,ls,us,is)
360 Int  line;                              /* Make definition of range for a  */
361 List pats;                              /* product type                    */
362 Cell ls, us, is; {
363     /* range :: (a,a) -> [a]
364      * range (X a b c, X p q r)
365      *   = [ X x y z | x <- range (a,p), y <- range (b,q), z <- range (c,r) ]
366      */
367     Cell is1 = is;
368     List e   = NIL;
369     for (; isAp(ls); ls=fun(ls), us=fun(us), is=fun(is)) {
370         e = cons(ap(FROMQUAL,pair(arg(is),
371                                   ap(nameRange,ap2(mkTuple(2),
372                                                    arg(ls),
373                                                    arg(us))))),e);
374     }
375     e = ap(COMP,pair(is1,e));
376     e = singleton(pair(pats,pair(mkInt(line),e)));
377     return mkBind("range",e);
378 }
379
380 static Cell local prodIndex(line,pats,ls,us,is)
381 Int  line;                              /* Make definition of index for a  */
382 List pats;                              /* product type                    */
383 Cell ls, us, is; {
384     /* index :: (a,a) -> a -> Bool
385      * index (X a b c, X p q r) (X x y z)
386      *  = index (c,r) z + rangeSize (c,r) * (
387      *     index (b,q) y + rangeSize (b,q) * (
388      *      index (a,x) x))
389      */
390     List xs = NIL;
391     Cell e  = NIL;
392     for (; isAp(ls); ls=fun(ls), us=fun(us), is=fun(is)) {
393         xs = cons(ap2(nameIndex,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)),xs);
394     }
395     for (e=hd(xs); nonNull(xs=tl(xs));) {
396         Cell x = hd(xs);
397         e = ap2(namePlus,x,ap2(nameMult,ap(nameRangeSize,arg(fun(x))),e));
398     }
399     e = singleton(pair(pats,pair(mkInt(line),e)));
400     return mkBind("index",e);
401 }
402
403 static Cell local prodInRange(line,pats,ls,us,is)
404 Int  line;                              /* Make definition of inRange for a*/
405 List pats;                              /* product type                    */
406 Cell ls, us, is; {
407     /* inRange :: (a,a) -> a -> Bool
408      * inRange (X a b c, X p q r) (X x y z)
409      *          = inRange (a,p) x && inRange (b,q) y && inRange (c,r) z
410      */
411     Cell e = ap2(nameInRange,ap2(mkTuple(2),arg(ls),arg(us)),arg(is));
412     while (ls=fun(ls), us=fun(us), is=fun(is), isAp(ls)) {
413         e = ap2(nameAnd,
414                 ap2(nameInRange,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)),
415                 e);
416     }
417     e = singleton(pair(pats,pair(mkInt(line),e)));
418     return mkBind("inRange",e);
419 }
420
421
422 /* --------------------------------------------------------------------------
423  * Deriving Show:
424  * ------------------------------------------------------------------------*/
425
426 List deriveShow(t)              /* Construct definition of text conversion */
427 Tycon t; {
428     List alts = NIL;
429     if (isTycon(t)) {                   /* deal with type constrs          */
430         List cs = tycon(t).defn;
431         for (; hasCfun(cs); cs=tl(cs)) {
432             alts = cons(mkAltShow(tycon(t).line,hd(cs),userArity(hd(cs))),
433                         alts);
434         }
435         alts = rev(alts);
436     } else {                            /* special case for tuples         */
437         alts = singleton(mkAltShow(0,t,tupleOf(t)));
438     }
439     return singleton(mkBind("showsPrec",alts));
440 }
441
442 static Cell local mkAltShow(line,h,a)   /* make alt for showsPrec eqn      */
443 Int  line;
444 Cell h;
445 Int  a; {
446     List vs   = getDiVars(a+1);
447     Cell d    = hd(vs);
448     Cell pat  = h;
449     List pats = NIL;
450     Int  i    = 0;
451     for (vs=tl(vs); i<a; i++) {
452         pat = ap(pat,hd(vs));
453         vs  = tl(vs);
454     }
455     pats = cons(d,cons(pat,NIL));
456     return pair(pats,pair(mkInt(line),showsPrecRhs(d,pat,a)));
457 }
458
459 #define shows0   ap(nameShowsPrec,mkInt(0))
460 #define shows10  ap(nameShowsPrec,mkInt(10))
461 #define showsOP  ap(nameComp,consChar('('))
462 #define showsOB  ap(nameComp,consChar('{'))
463 #define showsCM  ap(nameComp,consChar(','))
464 #define showsSP  ap(nameComp,consChar(' '))
465 #define showsBQ  ap(nameComp,consChar('`'))
466 #define showsCP  consChar(')')
467 #define showsCB  consChar('}')
468
469 static Cell local showsPrecRhs(d,pat,a) /* build a rhs for showsPrec for a */
470 Cell d, pat;                            /* given pattern, pat              */
471 Int  a; {
472     Cell h   = getHead(pat);
473     List cfs = cfunSfuns;
474
475     if (isTuple(h)) {
476         /* To display a tuple:
477          *    showsPrec d (a,b,c,d) = showChar '(' . showsPrec 0 a .
478          *                            showChar ',' . showsPrec 0 b .
479          *                            showChar ',' . showsPrec 0 c .
480          *                            showChar ',' . showsPrec 0 d .
481          *                            showChar ')'
482          */
483         Int  i   = tupleOf(h);
484         Cell rhs = showsCP;
485         for (; i>1; --i) {
486             rhs = ap(showsCM,ap2(nameComp,ap(shows0,arg(pat)),rhs));
487             pat = fun(pat);
488         }
489         return ap(showsOP,ap2(nameComp,ap(shows0,arg(pat)),rhs));
490     }
491
492     for (; nonNull(cfs) && h!=fst(hd(cfs)); cfs=tl(cfs)) {
493     }
494     if (nonNull(cfs)) {
495         /* To display a value using record syntax:
496          *    showsPrec d C{x=e, y=f, z=g} = showString "C"  . showChar '{' .
497          *                                   showField "x" e . showChar ',' .
498          *                                   showField "y" f . showChar ',' .
499          *                                   showField "z" g . showChar '}'
500          *    showField lab val
501          *      = showString lab . showChar '=' . shows val
502          */
503         Cell rhs     = showsCB;
504         List vs      = dupOnto(snd(hd(cfs)),NIL);
505         if (isAp(pat)) {
506             for (;;) {
507                 rhs = ap2(nameComp,
508                           ap2(nameShowField,
509                               mkStr(textOf(hd(vs))),
510                               arg(pat)),
511                           rhs);
512                 pat = fun(pat);
513                 vs  = tl(vs);
514                 if (isAp(pat)) {
515                     rhs = ap(showsCM,rhs);
516                 } else {
517                     break;
518                 }
519             }
520         }
521         rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),ap(showsOB,rhs));
522         return rhs;
523     }
524     else if (a==0) {
525         /* To display a nullary constructor:
526          *    showsPrec d Foo = showString "Foo"
527          */
528         return ap(nameApp,mkStr(name(h).text));
529     } else {
530         Syntax s = syntaxOf(h);
531         if (a==2 && assocOf(s)!=APPLIC) {
532             /* For a binary constructor with prec p:
533              * showsPrec d (a :* b) = showParen (d > p)
534              *                          (showsPrec lp a . showChar ' ' .
535              *                           showsString s  . showChar ' ' .
536              *                           showsPrec rp b)
537              */
538             Int  p   = precOf(s);
539             Int  lp  = (assocOf(s)==LEFT_ASS)  ? p : (p+1);
540             Int  rp  = (assocOf(s)==RIGHT_ASS) ? p : (p+1);
541             Cell rhs = ap(showsSP,ap2(nameShowsPrec,mkInt(rp),arg(pat)));
542             if (defaultSyntax(name(h).text)==APPLIC) {
543                 rhs = ap(showsBQ,
544                          ap2(nameComp,
545                              ap(nameApp,mkStr(name(h).text)),
546                              ap(showsBQ,rhs)));
547             } else {
548                 rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),rhs);
549             }
550
551             rhs = ap2(nameComp,
552                       ap2(nameShowsPrec,mkInt(lp),arg(fun(pat))),
553                       ap(showsSP,rhs));
554             rhs = ap2(nameShowParen,ap2(nameLe,mkInt(p+1),d),rhs);
555             return rhs;
556         }
557         else {
558             /* To display a non-nullary constructor with applicative syntax:
559              *    showsPrec d (Foo x y) = showParen (d>=10)
560              *                             (showString "Foo" .
561              *                              showChar ' ' . showsPrec 10 x .
562              *                              showChar ' ' . showsPrec 10 y)
563              */
564             Cell rhs = ap(showsSP,ap(shows10,arg(pat)));
565             for (pat=fun(pat); isAp(pat); pat=fun(pat)) {
566                 rhs = ap(showsSP,ap2(nameComp,ap(shows10,arg(pat)),rhs));
567             }
568             rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),rhs);
569             rhs = ap2(nameShowParen,ap2(nameLe,mkInt(10),d),rhs);
570             return rhs;
571         }
572     }
573 }
574 #undef  shows10
575 #undef  shows0
576 #undef  showsOP
577 #undef  showsOB
578 #undef  showsCM
579 #undef  showsSP
580 #undef  showsBQ
581 #undef  showsCP
582 #undef  showsCB
583
584 /* --------------------------------------------------------------------------
585  * Deriving Read:
586  * ------------------------------------------------------------------------*/
587
588 #define Tuple2(f,s)      ap2(mkTuple(2),f,s)
589 #define Lex(r)           ap(nameLex,r)  
590 #define ZFexp(h,q)       ap(FROMQUAL, pair(h,q))
591 #define ReadsPrec(n,e)   ap2(nameReadsPrec,n,e)
592 #define Lambda(v,e)      ap(LAMBDA,pair(v, pair(mkInt(0),e)))
593 #define ReadParen(a,b,c) ap(ap2(nameReadParen,a,b),c)
594 #define ReadField(f,s)   ap2(nameReadField,f,s)
595 #define GT(l,r)          ap2(nameGt,l,r)
596 #define Append(a,b)      ap2(nameApp,a,b)      
597
598 /*  Construct the readsPrec function of the form:
599  *
600  *    readsPrec d r = (readParen (d>p1) (\r -> [ (C1 ...,s) | ... ]) r ++
601  *                    (readParen (d>p2) (\r -> [ (C2 ...,s) | ... ]) r ++
602  *                    ...
603  *                    (readParen (d>pn) (\r -> [ (Cn ...,s) | ... ]) r) ... ))
604  */
605 List deriveRead(t)              /* construct definition of text reader     */
606 Cell t; {
607     Cell alt  = NIL;
608     Cell exp  = NIL;
609     Cell d    = inventVar();
610     Cell r    = inventVar();
611     List pat  = cons(d,cons(r,NIL));
612     Int  line = 0;
613
614     if (isTycon(t)) {
615         List cs = tycon(t).defn;
616         List exps = NIL;
617         for (; hasCfun(cs); cs=tl(cs)) {
618             exps = cons(mkReadCon(hd(cs),d,r),exps);
619         }
620         /* reverse concatenate list of subexpressions */
621         exp = hd(exps);
622         for (exps=tl(exps); nonNull(exps); exps=tl(exps)) {
623             exp = ap2(nameApp,hd(exps),exp);
624         }
625         line = tycon(t).line;
626     }
627     else { /* Tuples */
628         exp = ap(mkReadTuple(t),r);
629     }
630     /* printExp(stdout,exp); putc('\n',stdout); */
631     alt  = pair(pat,pair(mkInt(line),exp)); 
632     return singleton(mkBind("readsPrec",singleton(alt)));
633 }
634
635 /* Generate an expression of the form:
636  *
637  *   readParen (d > p) <derived expression> r
638  *
639  * for a (non-tuple) constructor "con" of precedence "p".
640  */
641
642 static Cell local mkReadCon(con, d, r) /* generate reader for a constructor */
643 Name con;
644 Cell d;
645 Cell r; {
646     Cell exp = NIL;
647     Int  p   = 0;
648     Syntax s = syntaxOf(con);
649     List cfs = cfunSfuns;
650     for (; nonNull(cfs) && con!=fst(hd(cfs)); cfs=tl(cfs)) {
651     }
652     if (nonNull(cfs)) {
653         exp = mkReadRecord(con,snd(hd(cfs)));
654         return ReadParen(nameFalse, exp, r);
655     }
656
657     if (userArity(con)==2 && assocOf(s)!=APPLIC) {
658         exp = mkReadInfix(con);
659         p   = precOf(s);
660     } else {
661         exp = mkReadPrefix(con);
662         p   = 9;
663     }
664     return ReadParen(userArity(con)==0 ? nameFalse : GT(d,mkInt(p)), exp, r);
665 }
666
667 /* Given an n-ary prefix constructor, generate a single lambda
668  * expression, such that
669  *
670  *   data T ... = Constr a1 a2 .. an | ....
671  *
672  * derives 
673  *
674  *   \ r -> [ (Constr t1 t2 ... tn, sn) | ("Constr",s0) <- lex r,
675  *                                        (t1,s1) <- readsPrec 10 s0,
676  *                                        (t2,s2) <- readsPrec 10 s1,
677  *                                        ...,
678  *                                        (tn,sn) <- readsPrec 10 sn-1 ]
679  *
680  */
681 static Cell local mkReadPrefix(con)    /* readsPrec for prefix constructor */
682 Cell con; {
683     Int  arity  = userArity(con);
684     Cell cn     = mkStr(name(con).text);
685     Cell r      = inventVar();
686     Cell prev_s = inventVar();
687     Cell exp    = con;
688     List quals  = NIL;
689     Int  i;
690
691     /* build (reversed) list of qualifiers and constructor */
692     quals = cons(ZFexp(Tuple2(cn,prev_s),Lex(r)),quals);
693     for(i=0; i<arity; i++) { 
694         Cell t = inventVar();
695         Cell s = inventVar();
696         quals  = cons(ZFexp(Tuple2(t,s),ReadsPrec(mkInt(10),prev_s)), quals);
697         exp    = ap(exp,t);
698         prev_s = s;
699     }
700
701     /* \r -> [ (exp, prev_s) | quals ] */
702     return Lambda(singleton(r),ap(COMP,pair(Tuple2(exp, prev_s), rev(quals))));
703 }
704
705 /* Given a binary infix constructor of precedence p
706  *
707  *   ... | T1 `con` T2 | ...
708  * 
709  * generate the lambda expression
710  *
711  *   \ r -> [ (u `con` v, s2) | (u,s0)     <- readsPrec lp r,
712  *                              ("con",s1) <- lex s0,
713  *                              (v,s2)     <- readsPrec rp s1 ]
714  *
715  * where lp and rp are either p or p+1 depending on associativity
716  */
717 static Cell local mkReadInfix( con )
718 Cell con;
719 {
720     Syntax s  = syntaxOf(con);
721     Int    p  = precOf(s); 
722     Int    lp = assocOf(s)==LEFT_ASS  ? p : (p+1);
723     Int    rp = assocOf(s)==RIGHT_ASS ? p : (p+1);
724     Cell   cn = mkStr(name(con).text);  
725     Cell   r  = inventVar();
726     Cell   s0 = inventVar();
727     Cell   s1 = inventVar();
728     Cell   s2 = inventVar();
729     Cell   u  = inventVar();
730     Cell   v  = inventVar();
731     List quals = NIL;
732
733     quals = cons(ZFexp(Tuple2(u, s0), ReadsPrec(mkInt(lp),r)),  quals);
734     quals = cons(ZFexp(Tuple2(cn,s1), Lex(s0)),                 quals);
735     quals = cons(ZFexp(Tuple2(v, s2), ReadsPrec(mkInt(rp),s1)), quals);
736
737     return Lambda(singleton(r), 
738                   ap(COMP,pair(Tuple2(ap2(con,u,v),s2),rev(quals))));
739 }
740
741 /* Given the n-ary tuple constructor return a lambda expression:
742  *
743  *   \ r -> [ ((t1,t2,...tn),s(2n+1)) | ("(",s0)      <- lex r,
744  *                                      (t1, s1)      <- readsPrec 0 s0,
745  *                                      ...
746  *                                      (",",s(2n-1)) <- lex s(2n-2),
747  *                                      (tn, s(2n))   <- readsPrec 0 s(2n-1),
748  *                                      (")",s(2n+1)) <- lex s(2n) ]
749  */
750 static Cell local mkReadTuple( tup ) /* readsPrec for n-tuple */
751 Cell tup; {
752     Int  arity  = tupleOf(tup);
753     Cell lp     = mkStr(findText("("));
754     Cell rp     = mkStr(findText(")"));
755     Cell co     = mkStr(findText(","));
756     Cell sep    = lp;
757     Cell r      = inventVar();
758     Cell prev_s = r;
759     Cell s      = inventVar();
760     Cell exp    = tup;
761     List quals  = NIL;
762     Int  i;
763
764     /* build (reversed) list of qualifiers and constructor */
765     for(i=0; i<arity; i++) { 
766         Cell t  = inventVar();
767         Cell si = inventVar();
768         Cell sj = inventVar();
769         quals  = cons(ZFexp(Tuple2(sep,si),Lex(prev_s)),quals); 
770         quals  = cons(ZFexp(Tuple2(t,sj),ReadsPrec(mkInt(0),si)), quals);
771         exp    = ap(exp,t);
772         prev_s = sj;
773         sep    = co;
774     }
775     quals = cons(ZFexp(Tuple2(rp,s),Lex(prev_s)),quals);
776
777     /* \ r -> [ (exp,s) | quals ] */
778     return Lambda(singleton(r),ap(COMP,pair(Tuple2(exp,s),rev(quals))));
779 }
780
781 /* Given a record constructor 
782  *
783  *   ... | C { f1 :: T1, ... fn :: Tn } | ...
784  *
785  * generate the expression:
786  *
787  *   \ r -> [(C t1 t2 ... tn,s(2n+1)) | ("C", s0)    <- lex r,
788  *                                      ("{", s1)    <- lex s0,
789  *                                      (t1,  s2)    <- readField "f1" s1,
790  *                                      ...
791  *                                      (",", s(2n-1)) <- lex s(2n),
792  *                                      (tn,  s(2n)) <- readField "fn" s(2n+1),
793  *                                      ("}", s(2n+1)) <- lex s(2n+2) ]
794  *
795  * where
796  *
797  *   readField    :: Read a => String -> ReadS a
798  *   readField m s0 = [ r | (t,  s1) <- lex s0, t == m,
799  *                          ("=",s2) <- lex s1,
800  *                          r        <- readsPrec 10 s2 ]
801  */
802 static Cell local mkReadRecord(con, fs) /* readsPrec for record constructor */
803 Cell con; 
804 List fs; {
805     Cell cn     = mkStr(name(con).text);  
806     Cell lb     = mkStr(findText("{"));
807     Cell rb     = mkStr(findText("}"));
808     Cell co     = mkStr(findText(","));
809     Cell sep    = lb;
810     Cell r      = inventVar();
811     Cell s0     = inventVar();
812     Cell prev_s = s0;
813     Cell s      = inventVar();
814     Cell exp    = con;
815     List quals  = NIL;
816
817     /* build (reversed) list of qualifiers and constructor */
818     quals  = cons(ZFexp(Tuple2(cn,s0),Lex(r)), quals); 
819     for(; nonNull(fs); fs=tl(fs)) { 
820         Cell f  = mkStr(textOf(hd(fs))); 
821         Cell t  = inventVar();
822         Cell si = inventVar();
823         Cell sj = inventVar();
824         quals  = cons(ZFexp(Tuple2(sep,si),Lex(prev_s)),     quals); 
825         quals  = cons(ZFexp(Tuple2(t,  sj),ReadField(f,si)), quals);
826         exp    = ap(exp,t);
827         prev_s = sj;
828         sep    = co;
829     }
830     quals = cons(ZFexp(Tuple2(rb,s),Lex(prev_s)),quals);
831
832     /* \ r -> [ (exp,s) | quals ] */
833     return Lambda(singleton(r),ap(COMP,pair(Tuple2(exp,s),rev(quals))));
834 }
835
836 #undef Tuple2
837 #undef Lex
838 #undef ZFexp
839 #undef ReadsPrec
840 #undef Lambda
841 #undef ReadParen
842 #undef ReadField
843 #undef GT
844 #undef Append
845
846 /* --------------------------------------------------------------------------
847  * Deriving Bounded:
848  * ------------------------------------------------------------------------*/
849
850 List deriveBounded(t)             /* construct definition of bounds        */
851 Tycon t; {
852     if (isEnumType(t)) {
853         Cell last  = tycon(t).defn;
854         Cell first = hd(last);
855         while (hasCfun(tl(last))) {
856             last = tl(last);
857         }
858         return cons(mkBind("minBound",mkVarAlts(tycon(t).line,first)),
859                 cons(mkBind("maxBound",mkVarAlts(tycon(t).line,hd(last))),
860                  NIL));
861     } else if (isTuple(t)) {    /* Definitions for product types           */
862         return mkBndBinds(0,t,tupleOf(t));
863     } else if (isTycon(t) && cfunOf(hd(tycon(t).defn))==0) {
864         return mkBndBinds(tycon(t).line,
865                           hd(tycon(t).defn),
866                           userArity(hd(tycon(t).defn)));
867     }
868     ERRMSG(tycon(t).line)
869      "Can only derive instances of Bounded for enumeration and product types"
870     EEND;
871     return NIL;
872 }
873
874 static List local mkBndBinds(line,h,n)  /* build bindings for derived      */
875 Int  line;                              /* Bounded on a product type       */
876 Cell h;
877 Int  n; {
878     Cell minB = h;
879     Cell maxB = h;
880     while (n-- > 0) {
881         minB = ap(minB,nameMinBnd);
882         maxB = ap(maxB,nameMaxBnd);
883     }
884     return cons(mkBind("minBound",mkVarAlts(line,minB)),
885             cons(mkBind("maxBound",mkVarAlts(line,maxB)),
886              NIL));
887 }
888
889
890 /* --------------------------------------------------------------------------
891  * Helpers: conToTag and tagToCon
892  * ------------------------------------------------------------------------*/
893
894 /* \ v -> case v of { ...; Ci _ _ -> i; ... } */
895 Void implementConToTag(t)
896 Tycon t; {                    
897     if (isNull(tycon(t).conToTag)) {
898         List   cs  = tycon(t).defn;
899         Name   nm  = newName(inventText(),NIL);
900         StgVar v   = mkStgVar(NIL,NIL);
901         List alts  = NIL; /* can't fail */
902
903         assert(isTycon(t) && (tycon(t).what==DATATYPE 
904                               || tycon(t).what==NEWTYPE));
905         for (; hasCfun(cs); cs=tl(cs)) {
906             Name    c   = hd(cs);
907             Int     num = cfunOf(c) == 0 ? 0 : cfunOf(c)-1;
908             StgVar  r   = mkStgVar(mkStgCon(nameMkI,singleton(mkInt(num))),
909                                    NIL);
910             StgExpr tag = mkStgLet(singleton(r),r);
911             List    vs  = NIL;
912             Int i;
913             for(i=0; i < name(c).arity; ++i) {
914                 vs = cons(mkStgVar(NIL,NIL),vs);
915             }
916             alts = cons(mkStgCaseAlt(c,vs,tag),alts);
917         }
918
919         name(nm).line   = tycon(t).line;
920         name(nm).type   = conToTagType(t);
921         name(nm).arity  = 1;
922         name(nm).stgVar = mkStgVar(mkStgLambda(singleton(v),mkStgCase(v,alts)),
923                                    NIL);
924         name(nm).stgSize = stgSize(stgVarBody(name(nm).stgVar));
925         tycon(t).conToTag = nm;
926         /* hack to make it print out */
927         stgGlobals = cons(pair(nm,name(nm).stgVar),stgGlobals); 
928     }
929 }
930
931 /* \ v -> case v of { ...; i -> Ci; ... } */
932 Void implementTagToCon(t)
933 Tycon t; {
934     if (isNull(tycon(t).tagToCon)) {
935         String tyconname;
936         List   cs;
937         Name   nm;
938         StgVar v1;
939         StgVar v2;
940         Cell   txt0;
941         StgVar bind1;
942         StgVar bind2;
943         StgVar bind3;
944         List   alts;
945         char   etxt[200];
946
947         assert(nameMkA);
948         assert(nameUnpackString);
949         assert(nameError);
950         assert(isTycon(t) && (tycon(t).what==DATATYPE 
951                               || tycon(t).what==NEWTYPE));
952
953         tyconname  = textToStr(tycon(t).text);
954         if (strlen(tyconname) > 100) 
955            internal("implementTagToCon: tycon name too long");
956
957         sprintf(etxt, 
958                 "out-of-range arg for `toEnum' "
959                 "in derived `instance Enum %s'", 
960                 tyconname);
961         
962         cs  = tycon(t).defn;
963         nm  = newName(inventText(),NIL);
964         v1  = mkStgVar(NIL,NIL);
965         v2  = mkStgPrimVar(NIL,mkStgRep(INT_REP),NIL);
966
967         txt0  = mkStr(findText(etxt));
968         bind1 = mkStgVar(mkStgCon(nameMkA,singleton(txt0)),NIL);
969         bind2 = mkStgVar(mkStgApp(nameUnpackString,singleton(bind1)),NIL);
970         bind3 = mkStgVar(mkStgApp(nameError,singleton(bind2)),NIL);
971
972         alts  = singleton(
973                    mkStgPrimAlt(
974                       singleton(
975                          mkStgPrimVar(NIL,mkStgRep(INT_REP),NIL)
976                       ),
977                       makeStgLet ( tripleton(bind1,bind2,bind3), bind3 )
978                    )
979                 );
980
981         for (; hasCfun(cs); cs=tl(cs)) {
982             Name   c   = hd(cs);
983             Int    num = cfunOf(c) == 0 ? 0 : cfunOf(c)-1;
984             StgVar pat = mkStgPrimVar(mkInt(num),mkStgRep(INT_REP),NIL);
985             assert(name(c).arity==0);
986             alts = cons(mkStgPrimAlt(singleton(pat),c),alts);
987         }
988
989         name(nm).line   = tycon(t).line;
990         name(nm).type   = tagToConType(t);
991         name(nm).arity  = 1;
992         name(nm).stgVar = mkStgVar(
993                             mkStgLambda(
994                               singleton(v1),
995                               mkStgCase(
996                                 v1,
997                                 singleton(
998                                   mkStgCaseAlt(
999                                     nameMkI,
1000                                     singleton(v2),
1001                                     mkStgPrimCase(v2,alts))))),
1002                             NIL
1003                           );
1004         name(nm).stgSize = stgSize(stgVarBody(name(nm).stgVar));
1005         tycon(t).tagToCon = nm;
1006         /* hack to make it print out */
1007         stgGlobals = cons(pair(nm,name(nm).stgVar),stgGlobals); 
1008     }
1009 }
1010
1011
1012 /* --------------------------------------------------------------------------
1013  * Derivation control:
1014  * ------------------------------------------------------------------------*/
1015
1016 Void deriveControl(what)
1017 Int what; {
1018     switch (what) {
1019         case INSTALL :
1020                 /* deliberate fall through */
1021         case RESET   : 
1022                 diVars      = NIL;
1023                 diNum       = 0;
1024                 cfunSfuns   = NIL;
1025                 break;
1026
1027         case MARK    : 
1028                 mark(diVars);
1029                 mark(cfunSfuns);
1030                 break;
1031     }
1032 }
1033
1034 /*-------------------------------------------------------------------------*/