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/02/03 17:08:27 $
12 * ------------------------------------------------------------------------*/
23 static Cell varCompAux; /* auxiliary function for compares */
24 static Cell varCompare;
28 static Cell varRangeSize; /* calculate size of index range */
29 static Cell varInRange;
39 static Cell varToEnum;
40 static Cell varFromEnum;
41 static Cell varEnumFromTo;
42 static Cell varEnumFromThenTo;
45 static Cell varMinBound;
46 static Cell varMaxBound;
50 static Cell varShowField; /* display single field */
51 static Cell varShowParen; /* wrap with parens */
52 static Cell varCompose; /* function composition */
53 static Cell varShowsPrec;
57 static Cell varReadField; /* read single field */
58 static Cell varReadParen; /* unwrap from parens */
59 static Cell varLex; /* lexer */
60 static Cell varReadsPrec;
63 #if DERIVE_SHOW || DERIVE_READ
64 static Cell varAppend; /* list append */
65 List cfunSfuns; /* List of (Cfun,[SelectorVar]) */
67 #if DERIVE_EQ || DERIVE_IX
68 static Cell varAnd; /* built-in logical connectives */
70 #if DERIVE_EQ || DERIVE_ORD
75 /* --------------------------------------------------------------------------
76 * local function prototypes:
77 * ------------------------------------------------------------------------*/
79 static List local getDiVars Args((Int));
80 static Cell local mkBind Args((String,List));
81 static Cell local mkVarAlts Args((Int,Cell));
83 #if DERIVE_EQ || DERIVE_ORD
84 static List local makeDPats2 Args((Cell,Int));
86 #if DERIVE_ORD || DERIVE_ENUM || DERIVE_IX || DERIVE_BOUNDED
87 static Bool local isEnumType Args((Tycon));
90 static Pair local mkAltEq Args((Int,List));
91 static Pair local mkAltOrd Args((Int,List));
92 static Cell local prodRange Args((Int,List,Cell,Cell,Cell));
93 static Cell local prodIndex Args((Int,List,Cell,Cell,Cell));
94 static Cell local prodInRange Args((Int,List,Cell,Cell,Cell));
95 static List local mkIxBinds Args((Int,Cell,Int));
96 static Cell local mkAltShow Args((Int,Cell,Int));
97 static Cell local showsPrecRhs Args((Cell,Cell,Int));
98 static Cell local mkReadCon Args((Name,Cell,Cell));
99 static Cell local mkReadPrefix Args((Cell));
100 static Cell local mkReadInfix Args((Cell));
101 static Cell local mkReadTuple Args((Cell));
102 static Cell local mkReadRecord Args((Cell,List));
103 static List local mkBndBinds Args((Int,Cell,Int));
107 /* --------------------------------------------------------------------------
109 * ------------------------------------------------------------------------*/
111 List diVars = NIL; /* Acts as a cache of invented vars*/
114 static List local getDiVars(n) /* get list of at least n vars for */
115 Int n; { /* derived instance generation */
116 for (; diNum<n; diNum++) {
117 diVars = cons(inventVar(),diVars);
122 static Cell local mkBind(s,alts) /* make a binding for a variable */
125 return pair(mkVar(findText(s)),pair(NIL,alts));
128 static Cell local mkVarAlts(line,r) /* make alts for binding a var to */
129 Int line; /* a simple expression */
131 return singleton(pair(NIL,pair(mkInt(line),r)));
134 /* --------------------------------------------------------------------------
135 * Given a datatype: data T a b = A a b | B Int | C deriving (Eq, Ord)
136 * The derived definitions of equality and ordering are given by:
138 * A a b == A x y = a==x && b==y
143 * compare (A a b) (A x y) = primCompAux a x (compare b y)
144 * compare (B a) (B x) = compare a x
146 * compare a x = cmpConstr a x
148 * In each case, the last line is only needed if there are multiple
149 * constructors in the datatype definition.
150 * ------------------------------------------------------------------------*/
152 #define ap2(f,x,y) ap(ap(f,x),y)
154 List local deriveEq(t) /* generate binding for derived == */
155 Type t; { /* for some TUPLE or DATATYPE t */
157 if (isTycon(t)) { /* deal with type constrs */
158 List cs = tycon(t).defn;
159 for (; hasCfun(cs); cs=tl(cs)) {
160 alts = cons(mkAltEq(tycon(t).line,
161 makeDPats2(hd(cs),userArity(hd(cs)))),
164 if (cfunOf(hd(tycon(t).defn))!=0) {
165 alts = cons(pair(cons(WILDCARD,cons(WILDCARD,NIL)),
166 pair(mkInt(tycon(t).line),nameFalse)),alts);
170 else { /* special case for tuples */
171 alts = singleton(mkAltEq(0,makeDPats2(t,tupleOf(t))));
173 return singleton(mkBind("==",alts));
176 static Pair local mkAltEq(line,pats) /* make alt for an equation for == */
177 Int line; /* using patterns in pats for lhs */
178 List pats; { /* arguments */
180 Cell q = hd(tl(pats));
184 e = ap2(nameEq,arg(p),arg(q));
185 for (p=fun(p), q=fun(q); isAp(p); p=fun(p), q=fun(q)) {
186 e = ap2(nameAnd,ap2(nameEq,arg(p),arg(q)),e);
189 return pair(pats,pair(mkInt(line),e));
192 List deriveOrd(t) /* make binding for derived compare*/
193 Type t; { /* for some TUPLE or DATATYPE t */
195 if (isEnumType(t)) { /* special case for enumerations */
196 alts = mkVarAlts(tycon(t).line,nameConCmp);
197 } else if (isTycon(t)) { /* deal with type constrs */
198 List cs = tycon(t).defn;
199 for (; hasCfun(cs); cs=tl(cs)) {
200 alts = cons(mkAltOrd(tycon(t).line,
201 makeDPats2(hd(cs),userArity(hd(cs)))),
204 if (cfunOf(hd(tycon(t).defn))!=0) {
205 Cell u = inventVar();
206 Cell w = inventVar();
207 alts = cons(pair(cons(u,singleton(w)),
208 pair(mkInt(tycon(t).line),
209 ap2(nameConCmp,u,w))),alts);
212 } else { /* special case for tuples */
213 alts = singleton(mkAltOrd(0,makeDPats2(t,tupleOf(t))));
215 return singleton(mkBind("compare",alts));
218 static Pair local mkAltOrd(line,pats) /* make alt for eqn for compare */
219 Int line; /* using patterns in pats for lhs */
220 List pats; { /* arguments */
222 Cell q = hd(tl(pats));
226 e = ap2(nameCompare,arg(p),arg(q));
227 for (p=fun(p), q=fun(q); isAp(p); p=fun(p), q=fun(q)) {
228 e = ap(ap2(nameCompAux,arg(p),arg(q)),e);
232 return pair(pats,pair(mkInt(line),e));
235 static List local makeDPats2(h,n) /* generate pattern list */
236 Cell h; /* by putting two new patterns with*/
237 Int n; { /* head h and new var components */
238 List us = getDiVars(2*n);
243 for (i=0, p=h; i<n; ++i) { /* make first version of pattern */
249 for (i=0, p=h; i<n; ++i) { /* make second version of pattern */
256 /* --------------------------------------------------------------------------
257 * Deriving Ix and Enum:
258 * ------------------------------------------------------------------------*/
260 List deriveEnum(t) /* Construct definition of enumeration */
262 Int l = tycon(t).line;
264 if (!isEnumType(t)) {
265 ERRMSG(l) "Can only derive instances of Enum for enumeration types"
269 return cons(mkBind("toEnum",mkVarAlts(l,ap(nameEnToEn,hd(tycon(t).defn)))),
270 cons(mkBind("fromEnum",mkVarAlts(l,nameEnFrEn)),
271 cons(mkBind("enumFrom",mkVarAlts(l,nameEnFrom)),
272 cons(mkBind("enumFromTo",mkVarAlts(l,nameEnFrTo)),
273 cons(mkBind("enumFromThen",mkVarAlts(l,nameEnFrTh)),NIL)))));
276 List deriveIx(t) /* Construct definition of indexing */
278 if (isEnumType(t)) { /* Definitions for enumerations */
279 return cons(mkBind("range",mkVarAlts(tycon(t).line,nameEnRange)),
280 cons(mkBind("index",mkVarAlts(tycon(t).line,nameEnIndex)),
281 cons(mkBind("inRange",mkVarAlts(tycon(t).line,nameEnInRng)),
283 } else if (isTuple(t)) { /* Definitions for product types */
284 return mkIxBinds(0,t,tupleOf(t));
285 } else if (isTycon(t) && cfunOf(hd(tycon(t).defn))==0) {
286 return mkIxBinds(tycon(t).line,
288 userArity(hd(tycon(t).defn)));
290 ERRMSG(tycon(t).line)
291 "Can only derive instances of Ix for enumeration or product types"
293 return NIL;/* NOTREACHED*/
296 static Bool local isEnumType(t) /* Determine whether t is an enumeration */
297 Tycon t; { /* type (i.e. all constructors arity == 0) */
298 if (isTycon(t) && (tycon(t).what==DATATYPE || tycon(t).what==NEWTYPE)) {
299 List cs = tycon(t).defn;
300 for (; hasCfun(cs); cs=tl(cs)) {
301 if (name(hd(cs)).arity!=0) {
305 /* ToDo: correct? addCfunTable(t); */
311 static List local mkIxBinds(line,h,n) /* build bindings for derived Ix on*/
312 Int line; /* a product type */
315 List vs = getDiVars(3*n);
323 for (i=0; i<n; ++i, vs=tl(vs)) { /* build three patterns for values */
324 ls = ap(ls,hd(vs)); /* of the datatype concerned */
325 us = ap(us,hd(vs=tl(vs)));
326 is = ap(is,hd(vs=tl(vs)));
328 pr = ap2(mkTuple(2),ls,us); /* Build (ls,us) */
329 pats = cons(pr,cons(is,NIL)); /* Build [(ls,us),is] */
331 return cons(prodRange(line,singleton(pr),ls,us,is),
332 cons(prodIndex(line,pats,ls,us,is),
333 cons(prodInRange(line,pats,ls,us,is),NIL)));
336 static Cell local prodRange(line,pats,ls,us,is)
337 Int line; /* Make definition of range for a */
338 List pats; /* product type */
340 /* range :: (a,a) -> [a]
341 * range (X a b c, X p q r)
342 * = [ X x y z | x <- range (a,p), y <- range (b,q), z <- range (c,r) ]
346 for (; isAp(ls); ls=fun(ls), us=fun(us), is=fun(is)) {
347 e = cons(ap(FROMQUAL,pair(arg(is),
348 ap(nameRange,ap2(mkTuple(2),
352 e = ap(COMP,pair(is1,e));
353 e = singleton(pair(pats,pair(mkInt(line),e)));
354 return mkBind("range",e);
357 static Cell local prodIndex(line,pats,ls,us,is)
358 Int line; /* Make definition of index for a */
359 List pats; /* product type */
361 /* index :: (a,a) -> a -> Bool
362 * index (X a b c, X p q r) (X x y z)
363 * = index (c,r) z + rangeSize (c,r) * (
364 * index (b,q) y + rangeSize (b,q) * (
369 for (; isAp(ls); ls=fun(ls), us=fun(us), is=fun(is)) {
370 xs = cons(ap2(nameIndex,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)),xs);
372 for (e=hd(xs); nonNull(xs=tl(xs));) {
374 e = ap2(namePlus,x,ap2(nameMult,ap(nameRangeSize,arg(fun(x))),e));
376 e = singleton(pair(pats,pair(mkInt(line),e)));
377 return mkBind("index",e);
380 static Cell local prodInRange(line,pats,ls,us,is)
381 Int line; /* Make definition of inRange for a*/
382 List pats; /* product type */
384 /* inRange :: (a,a) -> a -> Bool
385 * inRange (X a b c, X p q r) (X x y z)
386 * = inRange (a,p) x && inRange (b,q) y && inRange (c,r) z
388 Cell e = ap2(nameInRange,ap2(mkTuple(2),arg(ls),arg(us)),arg(is));
389 while (ls=fun(ls), us=fun(us), is=fun(is), isAp(ls)) {
391 ap2(nameInRange,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)),
394 e = singleton(pair(pats,pair(mkInt(line),e)));
395 return mkBind("inRange",e);
398 /* --------------------------------------------------------------------------
400 * ------------------------------------------------------------------------*/
402 List deriveShow(t) /* Construct definition of text conversion */
405 if (isTycon(t)) { /* deal with type constrs */
406 List cs = tycon(t).defn;
407 for (; hasCfun(cs); cs=tl(cs)) {
408 alts = cons(mkAltShow(tycon(t).line,hd(cs),userArity(hd(cs))),
412 } else { /* special case for tuples */
413 alts = singleton(mkAltShow(0,t,tupleOf(t)));
415 return singleton(mkBind("showsPrec",alts));
418 static Cell local mkAltShow(line,h,a) /* make alt for showsPrec eqn */
422 List vs = getDiVars(a+1);
427 for (vs=tl(vs); i<a; i++) {
428 pat = ap(pat,hd(vs));
431 pats = cons(d,cons(pat,NIL));
432 return pair(pats,pair(mkInt(line),showsPrecRhs(d,pat,a)));
435 #define shows0 ap(nameShowsPrec,mkInt(0))
436 #define shows10 ap(nameShowsPrec,mkInt(10))
437 #define showsOP ap(nameComp,consChar('('))
438 #define showsOB ap(nameComp,consChar('{'))
439 #define showsCM ap(nameComp,consChar(','))
440 #define showsSP ap(nameComp,consChar(' '))
441 #define showsBQ ap(nameComp,consChar('`'))
442 #define showsCP consChar(')')
443 #define showsCB consChar('}')
445 static Cell local showsPrecRhs(d,pat,a) /* build a rhs for showsPrec for a */
446 Cell d, pat; /* given pattern, pat */
448 Cell h = getHead(pat);
449 List cfs = cfunSfuns;
452 /* To display a tuple:
453 * showsPrec d (a,b,c,d) = showChar '(' . showsPrec 0 a .
454 * showChar ',' . showsPrec 0 b .
455 * showChar ',' . showsPrec 0 c .
456 * showChar ',' . showsPrec 0 d .
462 rhs = ap(showsCM,ap2(nameComp,ap(shows0,arg(pat)),rhs));
465 return ap(showsOP,ap2(nameComp,ap(shows0,arg(pat)),rhs));
468 for (; nonNull(cfs) && h!=fst(hd(cfs)); cfs=tl(cfs)) {
471 /* To display a value using record syntax:
472 * showsPrec d C{x=e, y=f, z=g} = showString "C" . showChar '{' .
473 * showField "x" e . showChar ',' .
474 * showField "y" f . showChar ',' .
475 * showField "z" g . showChar '}'
477 * = showString lab . showChar '=' . shows val
480 List vs = dupOnto(snd(hd(cfs)),NIL);
485 mkStr(textOf(hd(vs))),
491 rhs = ap(showsCM,rhs);
497 rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),ap(showsOB,rhs));
501 /* To display a nullary constructor:
502 * showsPrec d Foo = showString "Foo"
504 return ap(nameApp,mkStr(name(h).text));
506 Syntax s = syntaxOf(h);
507 if (a==2 && assocOf(s)!=APPLIC) {
508 /* For a binary constructor with prec p:
509 * showsPrec d (a :* b) = showParen (d > p)
510 * (showsPrec lp a . showChar ' ' .
511 * showsString s . showChar ' ' .
515 Int lp = (assocOf(s)==LEFT_ASS) ? p : (p+1);
516 Int rp = (assocOf(s)==RIGHT_ASS) ? p : (p+1);
517 Cell rhs = ap(showsSP,ap2(nameShowsPrec,mkInt(rp),arg(pat)));
518 if (defaultSyntax(name(h).text)==APPLIC) {
521 ap(nameApp,mkStr(name(h).text)),
524 rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),rhs);
528 ap2(nameShowsPrec,mkInt(lp),arg(fun(pat))),
530 rhs = ap2(nameShowParen,ap2(nameLe,mkInt(p+1),d),rhs);
534 /* To display a non-nullary constructor with applicative syntax:
535 * showsPrec d (Foo x y) = showParen (d>=10)
536 * (showString "Foo" .
537 * showChar ' ' . showsPrec 10 x .
538 * showChar ' ' . showsPrec 10 y)
540 Cell rhs = ap(showsSP,ap(shows10,arg(pat)));
541 for (pat=fun(pat); isAp(pat); pat=fun(pat)) {
542 rhs = ap(showsSP,ap2(nameComp,ap(shows10,arg(pat)),rhs));
544 rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),rhs);
545 rhs = ap2(nameShowParen,ap2(nameLe,mkInt(10),d),rhs);
560 /* --------------------------------------------------------------------------
562 * ------------------------------------------------------------------------*/
564 #define Tuple2(f,s) ap2(mkTuple(2),f,s)
565 #define Lex(r) ap(nameLex,r)
566 #define ZFexp(h,q) ap(FROMQUAL, pair(h,q))
567 #define ReadsPrec(n,e) ap2(nameReadsPrec,n,e)
568 #define Lambda(v,e) ap(LAMBDA,pair(v, pair(mkInt(0),e)))
569 #define ReadParen(a,b,c) ap(ap2(nameReadParen,a,b),c)
570 #define ReadField(f,s) ap2(nameReadField,f,s)
571 #define GT(l,r) ap2(nameGt,l,r)
572 #define Append(a,b) ap2(nameApp,a,b)
574 /* Construct the readsPrec function of the form:
576 * readsPrec d r = (readParen (d>p1) (\r -> [ (C1 ...,s) | ... ]) r ++
577 * (readParen (d>p2) (\r -> [ (C2 ...,s) | ... ]) r ++
579 * (readParen (d>pn) (\r -> [ (Cn ...,s) | ... ]) r) ... ))
581 List deriveRead(t) /* construct definition of text reader */
585 Cell d = inventVar();
586 Cell r = inventVar();
587 List pat = cons(d,cons(r,NIL));
591 List cs = tycon(t).defn;
593 for (; hasCfun(cs); cs=tl(cs)) {
594 exps = cons(mkReadCon(hd(cs),d,r),exps);
596 /* reverse concatenate list of subexpressions */
598 for (exps=tl(exps); nonNull(exps); exps=tl(exps)) {
599 exp = ap2(nameApp,hd(exps),exp);
601 line = tycon(t).line;
604 exp = ap(mkReadTuple(t),r);
606 /* printExp(stdout,exp); putc('\n',stdout); */
607 alt = pair(pat,pair(mkInt(line),exp));
608 return singleton(mkBind("readsPrec",singleton(alt)));
611 /* Generate an expression of the form:
613 * readParen (d > p) <derived expression> r
615 * for a (non-tuple) constructor "con" of precedence "p".
618 static Cell local mkReadCon(con, d, r) /* generate reader for a constructor */
624 Syntax s = syntaxOf(con);
625 List cfs = cfunSfuns;
626 for (; nonNull(cfs) && con!=fst(hd(cfs)); cfs=tl(cfs)) {
629 exp = mkReadRecord(con,snd(hd(cfs)));
630 return ReadParen(nameFalse, exp, r);
633 if (userArity(con)==2 && assocOf(s)!=APPLIC) {
634 exp = mkReadInfix(con);
637 exp = mkReadPrefix(con);
640 return ReadParen(userArity(con)==0 ? nameFalse : GT(d,mkInt(p)), exp, r);
643 /* Given an n-ary prefix constructor, generate a single lambda
644 * expression, such that
646 * data T ... = Constr a1 a2 .. an | ....
650 * \ r -> [ (Constr t1 t2 ... tn, sn) | ("Constr",s0) <- lex r,
651 * (t1,s1) <- readsPrec 10 s0,
652 * (t2,s2) <- readsPrec 10 s1,
654 * (tn,sn) <- readsPrec 10 sn-1 ]
657 static Cell local mkReadPrefix(con) /* readsPrec for prefix constructor */
659 Int arity = userArity(con);
660 Cell cn = mkStr(name(con).text);
661 Cell r = inventVar();
662 Cell prev_s = inventVar();
667 /* build (reversed) list of qualifiers and constructor */
668 quals = cons(ZFexp(Tuple2(cn,prev_s),Lex(r)),quals);
669 for(i=0; i<arity; i++) {
670 Cell t = inventVar();
671 Cell s = inventVar();
672 quals = cons(ZFexp(Tuple2(t,s),ReadsPrec(mkInt(10),prev_s)), quals);
677 /* \r -> [ (exp, prev_s) | quals ] */
678 return Lambda(singleton(r),ap(COMP,pair(Tuple2(exp, prev_s), rev(quals))));
681 /* Given a binary infix constructor of precedence p
683 * ... | T1 `con` T2 | ...
685 * generate the lambda expression
687 * \ r -> [ (u `con` v, s2) | (u,s0) <- readsPrec lp r,
688 * ("con",s1) <- lex s0,
689 * (v,s2) <- readsPrec rp s1 ]
691 * where lp and rp are either p or p+1 depending on associativity
693 static Cell local mkReadInfix( con )
696 Syntax s = syntaxOf(con);
698 Int lp = assocOf(s)==LEFT_ASS ? p : (p+1);
699 Int rp = assocOf(s)==RIGHT_ASS ? p : (p+1);
700 Cell cn = mkStr(name(con).text);
701 Cell r = inventVar();
702 Cell s0 = inventVar();
703 Cell s1 = inventVar();
704 Cell s2 = inventVar();
705 Cell u = inventVar();
706 Cell v = inventVar();
709 quals = cons(ZFexp(Tuple2(u, s0), ReadsPrec(mkInt(lp),r)), quals);
710 quals = cons(ZFexp(Tuple2(cn,s1), Lex(s0)), quals);
711 quals = cons(ZFexp(Tuple2(v, s2), ReadsPrec(mkInt(rp),s1)), quals);
713 return Lambda(singleton(r),
714 ap(COMP,pair(Tuple2(ap2(con,u,v),s2),rev(quals))));
717 /* Given the n-ary tuple constructor return a lambda expression:
719 * \ r -> [ ((t1,t2,...tn),s(2n+1)) | ("(",s0) <- lex r,
720 * (t1, s1) <- readsPrec 0 s0,
722 * (",",s(2n-1)) <- lex s(2n-2),
723 * (tn, s(2n)) <- readsPrec 0 s(2n-1),
724 * (")",s(2n+1)) <- lex s(2n) ]
726 static Cell local mkReadTuple( tup ) /* readsPrec for n-tuple */
728 Int arity = tupleOf(tup);
729 Cell lp = mkStr(findText("("));
730 Cell rp = mkStr(findText(")"));
731 Cell co = mkStr(findText(","));
733 Cell r = inventVar();
735 Cell s = inventVar();
740 /* build (reversed) list of qualifiers and constructor */
741 for(i=0; i<arity; i++) {
742 Cell t = inventVar();
743 Cell si = inventVar();
744 Cell sj = inventVar();
745 quals = cons(ZFexp(Tuple2(sep,si),Lex(prev_s)),quals);
746 quals = cons(ZFexp(Tuple2(t,sj),ReadsPrec(mkInt(0),si)), quals);
751 quals = cons(ZFexp(Tuple2(rp,s),Lex(prev_s)),quals);
753 /* \ r -> [ (exp,s) | quals ] */
754 return Lambda(singleton(r),ap(COMP,pair(Tuple2(exp,s),rev(quals))));
757 /* Given a record constructor
759 * ... | C { f1 :: T1, ... fn :: Tn } | ...
761 * generate the expression:
763 * \ r -> [(C t1 t2 ... tn,s(2n+1)) | ("C", s0) <- lex r,
764 * ("{", s1) <- lex s0,
765 * (t1, s2) <- readField "f1" s1,
767 * (",", s(2n-1)) <- lex s(2n),
768 * (tn, s(2n)) <- readField "fn" s(2n+1),
769 * ("}", s(2n+1)) <- lex s(2n+2) ]
773 * readField :: Read a => String -> ReadS a
774 * readField m s0 = [ r | (t, s1) <- lex s0, t == m,
775 * ("=",s2) <- lex s1,
776 * r <- readsPrec 10 s2 ]
778 static Cell local mkReadRecord(con, fs) /* readsPrec for record constructor */
781 Cell cn = mkStr(name(con).text);
782 Cell lb = mkStr(findText("{"));
783 Cell rb = mkStr(findText("}"));
784 Cell co = mkStr(findText(","));
786 Cell r = inventVar();
787 Cell s0 = inventVar();
789 Cell s = inventVar();
793 /* build (reversed) list of qualifiers and constructor */
794 quals = cons(ZFexp(Tuple2(cn,s0),Lex(r)), quals);
795 for(; nonNull(fs); fs=tl(fs)) {
796 Cell f = mkStr(textOf(hd(fs)));
797 Cell t = inventVar();
798 Cell si = inventVar();
799 Cell sj = inventVar();
800 quals = cons(ZFexp(Tuple2(sep,si),Lex(prev_s)), quals);
801 quals = cons(ZFexp(Tuple2(t, sj),ReadField(f,si)), quals);
806 quals = cons(ZFexp(Tuple2(rb,s),Lex(prev_s)),quals);
808 /* \ r -> [ (exp,s) | quals ] */
809 return Lambda(singleton(r),ap(COMP,pair(Tuple2(exp,s),rev(quals))));
822 /* --------------------------------------------------------------------------
824 * ------------------------------------------------------------------------*/
828 List deriveBounded(t) /* construct definition of bounds */
831 Cell last = tycon(t).defn;
832 Cell first = hd(last);
833 while (hasCfun(tl(last))) {
836 return cons(mkBind("minBound",mkVarAlts(tycon(t).line,first)),
837 cons(mkBind("maxBound",mkVarAlts(tycon(t).line,hd(last))),
839 } else if (isTuple(t)) { /* Definitions for product types */
840 return mkBndBinds(0,t,tupleOf(t));
841 } else if (isTycon(t) && cfunOf(hd(tycon(t).defn))==0) {
842 return mkBndBinds(tycon(t).line,
844 userArity(hd(tycon(t).defn)));
846 ERRMSG(tycon(t).line)
847 "Can only derive instances of Bounded for enumeration and product types"
852 static List local mkBndBinds(line,h,n) /* build bindings for derived */
853 Int line; /* Bounded on a product type */
859 minB = ap(minB,nameMinBnd);
860 maxB = ap(maxB,nameMaxBnd);
862 return cons(mkBind("minBound",mkVarAlts(line,minB)),
863 cons(mkBind("maxBound",mkVarAlts(line,maxB)),
866 #endif /* DERIVE_BOUNDED */
869 /* --------------------------------------------------------------------------
870 * Derivation control:
871 * ------------------------------------------------------------------------*/
873 Void deriveControl(what)
875 Text textPrelude = findText("PreludeBuiltin");
878 varTrue = mkQVar(textPrelude,findText("True"));
879 varFalse = mkQVar(textPrelude,findText("False"));
881 varCompAux = mkQVar(textPrelude,findText("primCompAux"));
882 varCompare = mkQVar(textPrelude,findText("compare"));
883 varEQ = mkQVar(textPrelude,findText("EQ"));
886 varRangeSize = mkQVar(textPrelude,findText("rangeSize"));
887 varInRange = mkQVar(textPrelude,findText("inRange"));
888 varRange = mkQVar(textPrelude,findText("range"));
889 varIndex = mkQVar(textPrelude,findText("index"));
890 varMult = mkQVar(textPrelude,findText("*"));
891 varPlus = mkQVar(textPrelude,findText("+"));
892 varMap = mkQVar(textPrelude,findText("map"));
893 varMinus = mkQVar(textPrelude,findText("-"));
894 varError = mkQVar(textPrelude,findText("error"));
897 varToEnum = mkQVar(textPrelude,findText("toEnum"));
898 varFromEnum = mkQVar(textPrelude,findText("fromEnum"));
899 varEnumFromTo = mkQVar(textPrelude,findText("enumFromTo"));
900 varEnumFromThenTo = mkQVar(textPrelude,findText("enumFromThenTo"));
903 varMinBound = mkQVar(textPrelude,findText("minBound"));
904 varMaxBound = mkQVar(textPrelude,findText("maxBound"));
907 conCons = mkQCon(textPrelude,findText(":"));
908 varShowField = mkQVar(textPrelude,findText("primShowField"));
909 varShowParen = mkQVar(textPrelude,findText("showParen"));
910 varCompose = mkQVar(textPrelude,findText("."));
911 varShowsPrec = mkQVar(textPrelude,findText("showsPrec"));
912 varLe = mkQVar(textPrelude,findText("<="));
915 varReadField = mkQVar(textPrelude,findText("primReadField"));
916 varReadParen = mkQVar(textPrelude,findText("readParen"));
917 varLex = mkQVar(textPrelude,findText("lex"));
918 varReadsPrec = mkQVar(textPrelude,findText("readsPrec"));
919 varGt = mkQVar(textPrelude,findText(">"));
921 #if DERIVE_SHOW || DERIVE_READ
922 varAppend = mkQVar(textPrelude,findText("++"));
924 #if DERIVE_EQ || DERIVE_IX
925 varAnd = mkQVar(textPrelude,findText("&&"));
927 #if DERIVE_EQ || DERIVE_ORD
928 varEq = mkQVar(textPrelude,findText("=="));
930 /* deliberate fall through */
934 #if DERIVE_SHOW | DERIVE_READ
941 #if DERIVE_SHOW | DERIVE_READ
966 mark(varEnumFromThenTo);
987 #if DERIVE_SHOW || DERIVE_READ
990 #if DERIVE_EQ || DERIVE_IX
993 #if DERIVE_EQ || DERIVE_ORD
1000 /*-------------------------------------------------------------------------*/