2 /* --------------------------------------------------------------------------
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
9 * $RCSfile: derive.c,v $
11 * $Date: 1999/03/01 14:46:44 $
12 * ------------------------------------------------------------------------*/
19 #include "Assembler.h"
25 static Cell varCompAux; /* auxiliary function for compares */
26 static Cell varCompare;
30 static Cell varRangeSize; /* calculate size of index range */
31 static Cell varInRange;
37 static Cell qvarMinus;
41 static Cell varToEnum;
42 static Cell varFromEnum;
43 static Cell varEnumFromTo;
44 static Cell varEnumFromThenTo;
47 static Cell varMinBound;
48 static Cell varMaxBound;
52 static Cell varShowField; /* display single field */
53 static Cell varShowParen; /* wrap with parens */
54 static Cell varCompose; /* function composition */
55 static Cell varShowsPrec;
59 static Cell varReadField; /* read single field */
60 static Cell varReadParen; /* unwrap from parens */
61 static Cell varLex; /* lexer */
62 static Cell varReadsPrec;
65 #if DERIVE_SHOW || DERIVE_READ
66 static Cell varAppend; /* list append */
67 List cfunSfuns; /* List of (Cfun,[SelectorVar]) */
69 #if DERIVE_EQ || DERIVE_IX
70 static Cell varAnd; /* built-in logical connectives */
72 #if DERIVE_EQ || DERIVE_ORD
77 /* --------------------------------------------------------------------------
78 * local function prototypes:
79 * ------------------------------------------------------------------------*/
81 static List local getDiVars Args((Int));
82 static Cell local mkBind Args((String,List));
83 static Cell local mkVarAlts Args((Int,Cell));
85 #if DERIVE_EQ || DERIVE_ORD
86 static List local makeDPats2 Args((Cell,Int));
88 #if DERIVE_ORD || DERIVE_ENUM || DERIVE_IX || DERIVE_BOUNDED
89 static Bool local isEnumType Args((Tycon));
92 static Pair local mkAltEq Args((Int,List));
93 static Pair local mkAltOrd Args((Int,List));
94 static Cell local prodRange Args((Int,List,Cell,Cell,Cell));
95 static Cell local prodIndex Args((Int,List,Cell,Cell,Cell));
96 static Cell local prodInRange Args((Int,List,Cell,Cell,Cell));
97 static List local mkIxBinds Args((Int,Cell,Int));
98 static Cell local mkAltShow Args((Int,Cell,Int));
99 static Cell local showsPrecRhs Args((Cell,Cell,Int));
100 static Cell local mkReadCon Args((Name,Cell,Cell));
101 static Cell local mkReadPrefix Args((Cell));
102 static Cell local mkReadInfix Args((Cell));
103 static Cell local mkReadTuple Args((Cell));
104 static Cell local mkReadRecord Args((Cell,List));
105 static List local mkBndBinds Args((Int,Cell,Int));
109 /* --------------------------------------------------------------------------
111 * ------------------------------------------------------------------------*/
113 List diVars = NIL; /* Acts as a cache of invented vars*/
116 static List local getDiVars(n) /* get list of at least n vars for */
117 Int n; { /* derived instance generation */
118 for (; diNum<n; diNum++) {
119 diVars = cons(inventVar(),diVars);
124 static Cell local mkBind(s,alts) /* make a binding for a variable */
127 return pair(mkVar(findText(s)),pair(NIL,alts));
130 static Cell local mkVarAlts(line,r) /* make alts for binding a var to */
131 Int line; /* a simple expression */
133 return singleton(pair(NIL,pair(mkInt(line),r)));
136 #if DERIVE_EQ || DERIVE_ORD
137 static List local makeDPats2(h,n) /* generate pattern list */
138 Cell h; /* by putting two new patterns with*/
139 Int n; { /* head h and new var components */
140 List us = getDiVars(2*n);
145 for (i=0, p=h; i<n; ++i) { /* make first version of pattern */
151 for (i=0, p=h; i<n; ++i) { /* make second version of pattern */
159 #if DERIVE_ORD || DERIVE_ENUM || DERIVE_IX || DERIVE_BOUNDED
160 static Bool local isEnumType(t) /* Determine whether t is an enumeration */
161 Tycon t; { /* type (i.e. all constructors arity == 0) */
162 if (isTycon(t) && (tycon(t).what==DATATYPE || tycon(t).what==NEWTYPE)) {
163 List cs = tycon(t).defn;
164 for (; hasCfun(cs); cs=tl(cs)) {
165 if (name(hd(cs)).arity!=0) {
169 /* ToDo: correct? addCfunTable(t); */
176 /* --------------------------------------------------------------------------
177 * Given a datatype: data T a b = A a b | B Int | C deriving (Eq, Ord)
178 * The derived definitions of equality and ordering are given by:
180 * A a b == A x y = a==x && b==y
185 * compare (A a b) (A x y) = primCompAux a x (compare b y)
186 * compare (B a) (B x) = compare a x
188 * compare a x = cmpConstr a x
190 * In each case, the last line is only needed if there are multiple
191 * constructors in the datatype definition.
192 * ------------------------------------------------------------------------*/
196 static Pair local mkAltEq Args((Int,List));
198 List deriveEq(t) /* generate binding for derived == */
199 Type t; { /* for some TUPLE or DATATYPE t */
201 if (isTycon(t)) { /* deal with type constrs */
202 List cs = tycon(t).defn;
203 for (; hasCfun(cs); cs=tl(cs)) {
204 alts = cons(mkAltEq(tycon(t).line,
205 makeDPats2(hd(cs),name(hd(cs)).arity)),
208 if (cfunOf(hd(tycon(t).defn))!=0) {
209 alts = cons(pair(cons(WILDCARD,cons(WILDCARD,NIL)),
210 pair(mkInt(tycon(t).line),varFalse)),alts);
213 } else { /* special case for tuples */
214 alts = singleton(mkAltEq(0,makeDPats2(t,tupleOf(t))));
216 return singleton(mkBind("==",alts));
219 static Pair local mkAltEq(line,pats) /* make alt for an equation for == */
220 Int line; /* using patterns in pats for lhs */
221 List pats; { /* arguments */
223 Cell q = hd(tl(pats));
227 e = ap2(varEq,arg(p),arg(q));
228 for (p=fun(p), q=fun(q); isAp(p); p=fun(p), q=fun(q)) {
229 e = ap2(varAnd,ap2(varEq,arg(p),arg(q)),e);
232 return pair(pats,pair(mkInt(line),e));
234 #endif /* DERIVE_EQ */
238 static Pair local mkAltOrd Args((Int,List));
240 List deriveOrd(t) /* make binding for derived compare*/
241 Type t; { /* for some TUPLE or DATATYPE t */
243 if (isEnumType(t)) { /* special case for enumerations */
244 Cell u = inventVar();
245 Cell w = inventVar();
247 if (cfunOf(hd(tycon(t).defn))!=0) {
248 implementConToTag(t);
249 rhs = ap2(varCompare,
250 ap(tycon(t).conToTag,u),
251 ap(tycon(t).conToTag,w));
255 alts = singleton(pair(doubleton(u,w),pair(mkInt(tycon(t).line),rhs)));
256 } else if (isTycon(t)) { /* deal with type constrs */
257 List cs = tycon(t).defn;
258 for (; hasCfun(cs); cs=tl(cs)) {
259 alts = cons(mkAltOrd(tycon(t).line,
260 makeDPats2(hd(cs),name(hd(cs)).arity)),
263 if (cfunOf(hd(tycon(t).defn))!=0) {
264 Cell u = inventVar();
265 Cell w = inventVar();
266 implementConToTag(t);
267 alts = cons(pair(doubleton(u,w),
268 pair(mkInt(tycon(t).line),
270 ap(tycon(t).conToTag,u),
271 ap(tycon(t).conToTag,w)))),
275 } else { /* special case for tuples */
276 alts = singleton(mkAltOrd(0,makeDPats2(t,tupleOf(t))));
278 return singleton(mkBind("compare",alts));
281 static Pair local mkAltOrd(line,pats) /* make alt for eqn for compare */
282 Int line; /* using patterns in pats for lhs */
283 List pats; { /* arguments */
285 Cell q = hd(tl(pats));
289 e = ap2(varCompare,arg(p),arg(q));
290 for (p=fun(p), q=fun(q); isAp(p); p=fun(p), q=fun(q)) {
291 e = ap3(varCompAux,arg(p),arg(q),e);
295 return pair(pats,pair(mkInt(line),e));
297 #endif /* DERIVE_ORD */
300 /* --------------------------------------------------------------------------
301 * Deriving Ix and Enum:
302 * ------------------------------------------------------------------------*/
305 List deriveEnum(t) /* Construct definition of enumeration */
307 Int l = tycon(t).line;
308 Cell x = inventVar();
309 Cell y = inventVar();
310 Cell first = hd(tycon(t).defn);
311 Cell last = tycon(t).defn;
313 if (!isEnumType(t)) {
314 ERRMSG(l) "Can only derive instances of Enum for enumeration types"
317 while (hasCfun(tl(last))) {
321 implementConToTag(t);
322 implementTagToCon(t);
323 return cons(mkBind("toEnum", mkVarAlts(l,tycon(t).tagToCon)),
324 cons(mkBind("fromEnum", mkVarAlts(l,tycon(t).conToTag)),
325 cons(mkBind("enumFrom", singleton(pair(singleton(x),
327 ap2(varEnumFromTo,x,last))))),
328 /* default instance of enumFromTo is good */
329 cons(mkBind("enumFromThen",singleton(pair(doubleton(x,y),
331 ap3(varEnumFromThenTo,x,y,
332 ap(COND,triple(ap2(varLe,x,y),
334 /* default instance of enumFromThenTo is good */
337 #endif /* DERIVE_ENUM */
340 static List local mkIxBindsEnum Args((Tycon));
341 static List local mkIxBinds Args((Int,Cell,Int));
342 static Cell local prodRange Args((Int,List,Cell,Cell,Cell));
343 static Cell local prodIndex Args((Int,List,Cell,Cell,Cell));
344 static Cell local prodInRange Args((Int,List,Cell,Cell,Cell));
346 List deriveIx(t) /* Construct definition of indexing */
348 if (isEnumType(t)) { /* Definitions for enumerations */
349 implementConToTag(t);
350 implementTagToCon(t);
351 return mkIxBindsEnum(t);
352 } else if (isTuple(t)) { /* Definitions for product types */
353 return mkIxBinds(0,t,tupleOf(t));
354 } else if (isTycon(t) && cfunOf(hd(tycon(t).defn))==0) {
355 return mkIxBinds(tycon(t).line,
357 name(hd(tycon(t).defn)).arity);
359 ERRMSG(tycon(t).line)
360 "Can only derive instances of Ix for enumeration or product types"
362 return NIL;/* NOTREACHED*/
365 /* instance Ix T where
366 * range (c1,c2) = map tagToCon [conToTag c1 .. conToTag c2]
368 * | inRange b ci = conToTag ci - conToTag c1
369 * | otherwise = error "Ix.index.T: Index out of range."
370 * inRange (c1,c2) ci = conToTag c1 <= i && i <= conToTag c2
371 * where i = conToTag ci
373 static List local mkIxBindsEnum(t)
375 Int l = tycon(t).line;
376 Name tagToCon = tycon(t).tagToCon;
377 Name conToTag = tycon(t).conToTag;
378 Cell b = inventVar();
379 Cell c1 = inventVar();
380 Cell c2 = inventVar();
381 Cell ci = inventVar();
382 return cons(mkBind("range", singleton(pair(singleton(ap2(mkTuple(2),
383 c1,c2)), pair(mkInt(l),ap2(varMap,tagToCon,
384 ap2(varEnumFromTo,ap(conToTag,c1),
385 ap(conToTag,c2))))))),
386 cons(mkBind("index", singleton(pair(doubleton(ap(ASPAT,pair(b,
387 ap2(mkTuple(2),c1,c2))),ci),
388 pair(mkInt(l),ap(COND,
389 triple(ap2(varInRange,b,ci),
390 ap2(qvarMinus,ap(conToTag,ci),
392 ap(varError,mkStr(findText(
393 "Ix.index: Index out of range"))))))))),
394 cons(mkBind("inRange",singleton(pair(doubleton(ap2(mkTuple(2),
395 c1,c2),ci), pair(mkInt(l),ap2(varAnd,
396 ap2(varLe,ap(conToTag,c1),ap(conToTag,ci)),
397 ap2(varLe,ap(conToTag,ci),
398 ap(conToTag,c2))))))),
399 /* ToDo: share conToTag ci */
403 static List local mkIxBinds(line,h,n) /* build bindings for derived Ix on*/
404 Int line; /* a product type */
407 List vs = getDiVars(3*n);
415 for (i=0; i<n; ++i, vs=tl(vs)) { /* build three patterns for values */
416 ls = ap(ls,hd(vs)); /* of the datatype concerned */
417 us = ap(us,hd(vs=tl(vs)));
418 is = ap(is,hd(vs=tl(vs)));
420 pr = ap2(mkTuple(2),ls,us); /* Build (ls,us) */
421 pats = cons(pr,cons(is,NIL)); /* Build [(ls,us),is] */
423 return cons(prodRange(line,singleton(pr),ls,us,is),
424 cons(prodIndex(line,pats,ls,us,is),
425 cons(prodInRange(line,pats,ls,us,is),
429 static Cell local prodRange(line,pats,ls,us,is)
430 Int line; /* Make definition of range for a */
431 List pats; /* product type */
433 /* range :: (a,a) -> [a]
434 * range (X a b c, X p q r)
435 * = [ X x y z | x <- range (a,p), y <- range (b,q), z <- range (c,r) ]
439 for (; isAp(ls); ls=fun(ls), us=fun(us), is=fun(is)) {
440 e = cons(ap(FROMQUAL,pair(arg(is),
441 ap(varRange,ap2(mkTuple(2),
445 e = ap(COMP,pair(is1,e));
446 e = singleton(pair(pats,pair(mkInt(line),e)));
447 return mkBind("range",e);
450 static Cell local prodIndex(line,pats,ls,us,is)
451 Int line; /* Make definition of index for a */
452 List pats; /* product type */
454 /* index :: (a,a) -> a -> Bool
455 * index (X a b c, X p q r) (X x y z)
456 * = index (c,r) z + rangeSize (c,r) * (
457 * index (b,q) y + rangeSize (b,q) * (
462 for (; isAp(ls); ls=fun(ls), us=fun(us), is=fun(is)) {
463 xs = cons(ap2(varIndex,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)),xs);
465 for (e=hd(xs); nonNull(xs=tl(xs));) {
467 e = ap2(qvarPlus,x,ap2(varMult,ap(varRangeSize,arg(fun(x))),e));
469 e = singleton(pair(pats,pair(mkInt(line),e)));
470 return mkBind("index",e);
473 static Cell local prodInRange(line,pats,ls,us,is)
474 Int line; /* Make definition of inRange for a*/
475 List pats; /* product type */
477 /* inRange :: (a,a) -> a -> Bool
478 * inRange (X a b c, X p q r) (X x y z)
479 * = inRange (a,p) x && inRange (b,q) y && inRange (c,r) z
481 Cell e = ap2(varInRange,ap2(mkTuple(2),arg(ls),arg(us)),arg(is));
482 while (ls=fun(ls), us=fun(us), is=fun(is), isAp(ls)) {
484 ap2(varInRange,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)),
487 e = singleton(pair(pats,pair(mkInt(line),e)));
488 return mkBind("inRange",e);
490 #endif /* DERIVE_IX */
493 /* --------------------------------------------------------------------------
495 * ------------------------------------------------------------------------*/
497 List deriveShow(t) /* Construct definition of text conversion */
500 if (isTycon(t)) { /* deal with type constrs */
501 List cs = tycon(t).defn;
502 for (; hasCfun(cs); cs=tl(cs)) {
503 alts = cons(mkAltShow(tycon(t).line,hd(cs),userArity(hd(cs))),
507 } else { /* special case for tuples */
508 alts = singleton(mkAltShow(0,t,tupleOf(t)));
510 return singleton(mkBind("showsPrec",alts));
513 static Cell local mkAltShow(line,h,a) /* make alt for showsPrec eqn */
517 List vs = getDiVars(a+1);
522 for (vs=tl(vs); i<a; i++) {
523 pat = ap(pat,hd(vs));
526 pats = cons(d,cons(pat,NIL));
527 return pair(pats,pair(mkInt(line),showsPrecRhs(d,pat,a)));
530 #define shows0 ap(nameShowsPrec,mkInt(0))
531 #define shows10 ap(nameShowsPrec,mkInt(10))
532 #define showsOP ap(nameComp,consChar('('))
533 #define showsOB ap(nameComp,consChar('{'))
534 #define showsCM ap(nameComp,consChar(','))
535 #define showsSP ap(nameComp,consChar(' '))
536 #define showsBQ ap(nameComp,consChar('`'))
537 #define showsCP consChar(')')
538 #define showsCB consChar('}')
540 static Cell local showsPrecRhs(d,pat,a) /* build a rhs for showsPrec for a */
541 Cell d, pat; /* given pattern, pat */
543 Cell h = getHead(pat);
544 List cfs = cfunSfuns;
547 /* To display a tuple:
548 * showsPrec d (a,b,c,d) = showChar '(' . showsPrec 0 a .
549 * showChar ',' . showsPrec 0 b .
550 * showChar ',' . showsPrec 0 c .
551 * showChar ',' . showsPrec 0 d .
557 rhs = ap(showsCM,ap2(nameComp,ap(shows0,arg(pat)),rhs));
560 return ap(showsOP,ap2(nameComp,ap(shows0,arg(pat)),rhs));
563 for (; nonNull(cfs) && h!=fst(hd(cfs)); cfs=tl(cfs)) {
566 /* To display a value using record syntax:
567 * showsPrec d C{x=e, y=f, z=g} = showString "C" . showChar '{' .
568 * showField "x" e . showChar ',' .
569 * showField "y" f . showChar ',' .
570 * showField "z" g . showChar '}'
572 * = showString lab . showChar '=' . shows val
575 List vs = dupOnto(snd(hd(cfs)),NIL);
580 mkStr(textOf(hd(vs))),
586 rhs = ap(showsCM,rhs);
592 rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),ap(showsOB,rhs));
596 /* To display a nullary constructor:
597 * showsPrec d Foo = showString "Foo"
599 return ap(nameApp,mkStr(name(h).text));
601 Syntax s = syntaxOf(h);
602 if (a==2 && assocOf(s)!=APPLIC) {
603 /* For a binary constructor with prec p:
604 * showsPrec d (a :* b) = showParen (d > p)
605 * (showsPrec lp a . showChar ' ' .
606 * showsString s . showChar ' ' .
610 Int lp = (assocOf(s)==LEFT_ASS) ? p : (p+1);
611 Int rp = (assocOf(s)==RIGHT_ASS) ? p : (p+1);
612 Cell rhs = ap(showsSP,ap2(nameShowsPrec,mkInt(rp),arg(pat)));
613 if (defaultSyntax(name(h).text)==APPLIC) {
616 ap(nameApp,mkStr(name(h).text)),
619 rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),rhs);
623 ap2(nameShowsPrec,mkInt(lp),arg(fun(pat))),
625 rhs = ap2(nameShowParen,ap2(nameLe,mkInt(p+1),d),rhs);
629 /* To display a non-nullary constructor with applicative syntax:
630 * showsPrec d (Foo x y) = showParen (d>=10)
631 * (showString "Foo" .
632 * showChar ' ' . showsPrec 10 x .
633 * showChar ' ' . showsPrec 10 y)
635 Cell rhs = ap(showsSP,ap(shows10,arg(pat)));
636 for (pat=fun(pat); isAp(pat); pat=fun(pat)) {
637 rhs = ap(showsSP,ap2(nameComp,ap(shows10,arg(pat)),rhs));
639 rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),rhs);
640 rhs = ap2(nameShowParen,ap2(nameLe,mkInt(10),d),rhs);
655 /* --------------------------------------------------------------------------
657 * ------------------------------------------------------------------------*/
659 #define Tuple2(f,s) ap2(mkTuple(2),f,s)
660 #define Lex(r) ap(nameLex,r)
661 #define ZFexp(h,q) ap(FROMQUAL, pair(h,q))
662 #define ReadsPrec(n,e) ap2(nameReadsPrec,n,e)
663 #define Lambda(v,e) ap(LAMBDA,pair(v, pair(mkInt(0),e)))
664 #define ReadParen(a,b,c) ap(ap2(nameReadParen,a,b),c)
665 #define ReadField(f,s) ap2(nameReadField,f,s)
666 #define GT(l,r) ap2(nameGt,l,r)
667 #define Append(a,b) ap2(nameApp,a,b)
669 /* Construct the readsPrec function of the form:
671 * readsPrec d r = (readParen (d>p1) (\r -> [ (C1 ...,s) | ... ]) r ++
672 * (readParen (d>p2) (\r -> [ (C2 ...,s) | ... ]) r ++
674 * (readParen (d>pn) (\r -> [ (Cn ...,s) | ... ]) r) ... ))
676 List deriveRead(t) /* construct definition of text reader */
680 Cell d = inventVar();
681 Cell r = inventVar();
682 List pat = cons(d,cons(r,NIL));
686 List cs = tycon(t).defn;
688 for (; hasCfun(cs); cs=tl(cs)) {
689 exps = cons(mkReadCon(hd(cs),d,r),exps);
691 /* reverse concatenate list of subexpressions */
693 for (exps=tl(exps); nonNull(exps); exps=tl(exps)) {
694 exp = ap2(nameApp,hd(exps),exp);
696 line = tycon(t).line;
699 exp = ap(mkReadTuple(t),r);
701 /* printExp(stdout,exp); putc('\n',stdout); */
702 alt = pair(pat,pair(mkInt(line),exp));
703 return singleton(mkBind("readsPrec",singleton(alt)));
706 /* Generate an expression of the form:
708 * readParen (d > p) <derived expression> r
710 * for a (non-tuple) constructor "con" of precedence "p".
713 static Cell local mkReadCon(con, d, r) /* generate reader for a constructor */
719 Syntax s = syntaxOf(con);
720 List cfs = cfunSfuns;
721 for (; nonNull(cfs) && con!=fst(hd(cfs)); cfs=tl(cfs)) {
724 exp = mkReadRecord(con,snd(hd(cfs)));
725 return ReadParen(nameFalse, exp, r);
728 if (userArity(con)==2 && assocOf(s)!=APPLIC) {
729 exp = mkReadInfix(con);
732 exp = mkReadPrefix(con);
735 return ReadParen(userArity(con)==0 ? nameFalse : GT(d,mkInt(p)), exp, r);
738 /* Given an n-ary prefix constructor, generate a single lambda
739 * expression, such that
741 * data T ... = Constr a1 a2 .. an | ....
745 * \ r -> [ (Constr t1 t2 ... tn, sn) | ("Constr",s0) <- lex r,
746 * (t1,s1) <- readsPrec 10 s0,
747 * (t2,s2) <- readsPrec 10 s1,
749 * (tn,sn) <- readsPrec 10 sn-1 ]
752 static Cell local mkReadPrefix(con) /* readsPrec for prefix constructor */
754 Int arity = userArity(con);
755 Cell cn = mkStr(name(con).text);
756 Cell r = inventVar();
757 Cell prev_s = inventVar();
762 /* build (reversed) list of qualifiers and constructor */
763 quals = cons(ZFexp(Tuple2(cn,prev_s),Lex(r)),quals);
764 for(i=0; i<arity; i++) {
765 Cell t = inventVar();
766 Cell s = inventVar();
767 quals = cons(ZFexp(Tuple2(t,s),ReadsPrec(mkInt(10),prev_s)), quals);
772 /* \r -> [ (exp, prev_s) | quals ] */
773 return Lambda(singleton(r),ap(COMP,pair(Tuple2(exp, prev_s), rev(quals))));
776 /* Given a binary infix constructor of precedence p
778 * ... | T1 `con` T2 | ...
780 * generate the lambda expression
782 * \ r -> [ (u `con` v, s2) | (u,s0) <- readsPrec lp r,
783 * ("con",s1) <- lex s0,
784 * (v,s2) <- readsPrec rp s1 ]
786 * where lp and rp are either p or p+1 depending on associativity
788 static Cell local mkReadInfix( con )
791 Syntax s = syntaxOf(con);
793 Int lp = assocOf(s)==LEFT_ASS ? p : (p+1);
794 Int rp = assocOf(s)==RIGHT_ASS ? p : (p+1);
795 Cell cn = mkStr(name(con).text);
796 Cell r = inventVar();
797 Cell s0 = inventVar();
798 Cell s1 = inventVar();
799 Cell s2 = inventVar();
800 Cell u = inventVar();
801 Cell v = inventVar();
804 quals = cons(ZFexp(Tuple2(u, s0), ReadsPrec(mkInt(lp),r)), quals);
805 quals = cons(ZFexp(Tuple2(cn,s1), Lex(s0)), quals);
806 quals = cons(ZFexp(Tuple2(v, s2), ReadsPrec(mkInt(rp),s1)), quals);
808 return Lambda(singleton(r),
809 ap(COMP,pair(Tuple2(ap2(con,u,v),s2),rev(quals))));
812 /* Given the n-ary tuple constructor return a lambda expression:
814 * \ r -> [ ((t1,t2,...tn),s(2n+1)) | ("(",s0) <- lex r,
815 * (t1, s1) <- readsPrec 0 s0,
817 * (",",s(2n-1)) <- lex s(2n-2),
818 * (tn, s(2n)) <- readsPrec 0 s(2n-1),
819 * (")",s(2n+1)) <- lex s(2n) ]
821 static Cell local mkReadTuple( tup ) /* readsPrec for n-tuple */
823 Int arity = tupleOf(tup);
824 Cell lp = mkStr(findText("("));
825 Cell rp = mkStr(findText(")"));
826 Cell co = mkStr(findText(","));
828 Cell r = inventVar();
830 Cell s = inventVar();
835 /* build (reversed) list of qualifiers and constructor */
836 for(i=0; i<arity; i++) {
837 Cell t = inventVar();
838 Cell si = inventVar();
839 Cell sj = inventVar();
840 quals = cons(ZFexp(Tuple2(sep,si),Lex(prev_s)),quals);
841 quals = cons(ZFexp(Tuple2(t,sj),ReadsPrec(mkInt(0),si)), quals);
846 quals = cons(ZFexp(Tuple2(rp,s),Lex(prev_s)),quals);
848 /* \ r -> [ (exp,s) | quals ] */
849 return Lambda(singleton(r),ap(COMP,pair(Tuple2(exp,s),rev(quals))));
852 /* Given a record constructor
854 * ... | C { f1 :: T1, ... fn :: Tn } | ...
856 * generate the expression:
858 * \ r -> [(C t1 t2 ... tn,s(2n+1)) | ("C", s0) <- lex r,
859 * ("{", s1) <- lex s0,
860 * (t1, s2) <- readField "f1" s1,
862 * (",", s(2n-1)) <- lex s(2n),
863 * (tn, s(2n)) <- readField "fn" s(2n+1),
864 * ("}", s(2n+1)) <- lex s(2n+2) ]
868 * readField :: Read a => String -> ReadS a
869 * readField m s0 = [ r | (t, s1) <- lex s0, t == m,
870 * ("=",s2) <- lex s1,
871 * r <- readsPrec 10 s2 ]
873 static Cell local mkReadRecord(con, fs) /* readsPrec for record constructor */
876 Cell cn = mkStr(name(con).text);
877 Cell lb = mkStr(findText("{"));
878 Cell rb = mkStr(findText("}"));
879 Cell co = mkStr(findText(","));
881 Cell r = inventVar();
882 Cell s0 = inventVar();
884 Cell s = inventVar();
888 /* build (reversed) list of qualifiers and constructor */
889 quals = cons(ZFexp(Tuple2(cn,s0),Lex(r)), quals);
890 for(; nonNull(fs); fs=tl(fs)) {
891 Cell f = mkStr(textOf(hd(fs)));
892 Cell t = inventVar();
893 Cell si = inventVar();
894 Cell sj = inventVar();
895 quals = cons(ZFexp(Tuple2(sep,si),Lex(prev_s)), quals);
896 quals = cons(ZFexp(Tuple2(t, sj),ReadField(f,si)), quals);
901 quals = cons(ZFexp(Tuple2(rb,s),Lex(prev_s)),quals);
903 /* \ r -> [ (exp,s) | quals ] */
904 return Lambda(singleton(r),ap(COMP,pair(Tuple2(exp,s),rev(quals))));
917 /* --------------------------------------------------------------------------
919 * ------------------------------------------------------------------------*/
923 List deriveBounded(t) /* construct definition of bounds */
926 Cell last = tycon(t).defn;
927 Cell first = hd(last);
928 while (hasCfun(tl(last))) {
931 return cons(mkBind("minBound",mkVarAlts(tycon(t).line,first)),
932 cons(mkBind("maxBound",mkVarAlts(tycon(t).line,hd(last))),
934 } else if (isTuple(t)) { /* Definitions for product types */
935 return mkBndBinds(0,t,tupleOf(t));
936 } else if (isTycon(t) && cfunOf(hd(tycon(t).defn))==0) {
937 return mkBndBinds(tycon(t).line,
939 userArity(hd(tycon(t).defn)));
941 ERRMSG(tycon(t).line)
942 "Can only derive instances of Bounded for enumeration and product types"
947 static List local mkBndBinds(line,h,n) /* build bindings for derived */
948 Int line; /* Bounded on a product type */
954 minB = ap(minB,nameMinBnd);
955 maxB = ap(maxB,nameMaxBnd);
957 return cons(mkBind("minBound",mkVarAlts(line,minB)),
958 cons(mkBind("maxBound",mkVarAlts(line,maxB)),
961 #endif /* DERIVE_BOUNDED */
965 /* --------------------------------------------------------------------------
966 * Helpers: conToTag and tagToCon
967 * ------------------------------------------------------------------------*/
969 /* \ v -> case v of { ...; Ci _ _ -> i; ... } */
970 Void implementConToTag(t)
972 if (isNull(tycon(t).conToTag)) {
973 List cs = tycon(t).defn;
974 Name nm = newName(inventText(),NIL);
975 StgVar v = mkStgVar(NIL,NIL);
976 List alts = NIL; /* can't fail */
978 assert(isTycon(t) && (tycon(t).what==DATATYPE
979 || tycon(t).what==NEWTYPE));
980 for (; hasCfun(cs); cs=tl(cs)) {
982 Int num = cfunOf(c) == 0 ? 0 : cfunOf(c)-1;
983 StgVar r = mkStgVar(mkStgCon(nameMkI,singleton(mkInt(num))),
985 StgExpr tag = mkStgLet(singleton(r),r);
988 for(i=0; i < name(c).arity; ++i) {
989 vs = cons(mkStgVar(NIL,NIL),vs);
991 alts = cons(mkStgCaseAlt(c,vs,tag),alts);
994 name(nm).line = tycon(t).line;
995 name(nm).type = conToTagType(t);
997 name(nm).stgVar = mkStgVar(mkStgLambda(singleton(v),mkStgCase(v,alts)),
999 tycon(t).conToTag = nm;
1000 /* hack to make it print out */
1001 stgGlobals = cons(pair(nm,name(nm).stgVar),stgGlobals);
1005 /* \ v -> case v of { ...; i -> Ci; ... } */
1006 Void implementTagToCon(t)
1008 if (isNull(tycon(t).tagToCon)) {
1022 assert(nameUnpackString);
1024 assert(isTycon(t) && (tycon(t).what==DATATYPE
1025 || tycon(t).what==NEWTYPE));
1027 tyconname = textToStr(tycon(t).text);
1028 etxt = malloc(100+strlen(tyconname));
1031 "out-of-range arg for `toEnum' "
1032 "in derived `instance Enum %s'",
1036 nm = newName(inventText(),NIL);
1037 v1 = mkStgVar(NIL,NIL);
1038 v2 = mkStgPrimVar(NIL,mkStgRep(INT_REP),NIL);
1040 txt0 = mkStr(findText(etxt));
1041 bind1 = mkStgVar(mkStgCon(nameMkA,singleton(txt0)),NIL);
1042 bind2 = mkStgVar(mkStgApp(nameUnpackString,singleton(bind1)),NIL);
1043 bind3 = mkStgVar(mkStgApp(nameError,singleton(bind2)),NIL);
1048 mkStgPrimVar(NIL,mkStgRep(INT_REP),NIL)
1050 makeStgLet ( tripleton(bind1,bind2,bind3), bind3 )
1054 for (; hasCfun(cs); cs=tl(cs)) {
1056 Int num = cfunOf(c) == 0 ? 0 : cfunOf(c)-1;
1057 StgVar pat = mkStgPrimVar(mkInt(num),mkStgRep(INT_REP),NIL);
1058 assert(name(c).arity==0);
1059 alts = cons(mkStgPrimAlt(singleton(pat),c),alts);
1062 name(nm).line = tycon(t).line;
1063 name(nm).type = tagToConType(t);
1065 name(nm).stgVar = mkStgVar(
1074 mkStgPrimCase(v2,alts))))),
1077 tycon(t).tagToCon = nm;
1078 /* hack to make it print out */
1079 stgGlobals = cons(pair(nm,name(nm).stgVar),stgGlobals);
1080 if (etxt) free(etxt);
1085 /* --------------------------------------------------------------------------
1086 * Derivation control:
1087 * ------------------------------------------------------------------------*/
1089 Void deriveControl(what)
1091 Text textPrelude = findText("Prelude");
1094 varTrue = mkQVar(textPrelude,findText("True"));
1095 varFalse = mkQVar(textPrelude,findText("False"));
1097 varCompAux = mkQVar(textPrelude,findText("primCompAux"));
1098 varCompare = mkQVar(textPrelude,findText("compare"));
1099 varEQ = mkQVar(textPrelude,findText("EQ"));
1102 varRangeSize = mkQVar(textPrelude,findText("rangeSize"));
1103 varInRange = mkQVar(textPrelude,findText("inRange"));
1104 varRange = mkQVar(textPrelude,findText("range"));
1105 varIndex = mkQVar(textPrelude,findText("index"));
1106 varMult = mkQVar(textPrelude,findText("*"));
1107 qvarPlus = mkQVar(textPrelude,findText("+"));
1108 varMap = mkQVar(textPrelude,findText("map"));
1109 qvarMinus = mkQVar(textPrelude,findText("-"));
1110 varError = mkQVar(textPrelude,findText("error"));
1113 varToEnum = mkQVar(textPrelude,findText("toEnum"));
1114 varFromEnum = mkQVar(textPrelude,findText("fromEnum"));
1115 varEnumFromTo = mkQVar(textPrelude,findText("enumFromTo"));
1116 varEnumFromThenTo = mkQVar(textPrelude,findText("enumFromThenTo"));
1119 varMinBound = mkQVar(textPrelude,findText("minBound"));
1120 varMaxBound = mkQVar(textPrelude,findText("maxBound"));
1123 conCons = mkQCon(textPrelude,findText(":"));
1124 varShowField = mkQVar(textPrelude,findText("primShowField"));
1125 varShowParen = mkQVar(textPrelude,findText("showParen"));
1126 varCompose = mkQVar(textPrelude,findText("."));
1127 varShowsPrec = mkQVar(textPrelude,findText("showsPrec"));
1128 varLe = mkQVar(textPrelude,findText("<="));
1131 varReadField = mkQVar(textPrelude,findText("primReadField"));
1132 varReadParen = mkQVar(textPrelude,findText("readParen"));
1133 varLex = mkQVar(textPrelude,findText("lex"));
1134 varReadsPrec = mkQVar(textPrelude,findText("readsPrec"));
1135 varGt = mkQVar(textPrelude,findText(">"));
1137 #if DERIVE_SHOW || DERIVE_READ
1138 varAppend = mkQVar(textPrelude,findText("++"));
1140 #if DERIVE_EQ || DERIVE_IX
1141 varAnd = mkQVar(textPrelude,findText("&&"));
1143 #if DERIVE_EQ || DERIVE_ORD
1144 varEq = mkQVar(textPrelude,findText("=="));
1146 /* deliberate fall through */
1150 #if DERIVE_SHOW | DERIVE_READ
1157 #if DERIVE_SHOW | DERIVE_READ
1181 mark(varEnumFromTo);
1182 mark(varEnumFromThenTo);
1203 #if DERIVE_SHOW || DERIVE_READ
1206 #if DERIVE_EQ || DERIVE_IX
1209 #if DERIVE_EQ || DERIVE_ORD
1216 /*-------------------------------------------------------------------------*/