[project @ 1999-11-24 10:38:10 by andy]
[ghc-hetmet.git] / ghc / interpreter / static.c
index 7a61668..a54ff1e 100644 (file)
@@ -9,8 +9,8 @@
  * included in the distribution.
  *
  * $RCSfile: static.c,v $
- * $Revision: 1.13 $
- * $Date: 1999/10/26 17:27:45 $
+ * $Revision: 1.17 $
+ * $Date: 1999/11/17 16:57:44 $
  * ------------------------------------------------------------------------*/
 
 #include "prelude.h"
@@ -55,6 +55,7 @@ static Type   local instantiateSyn      Args((Type,Type));
 static Void   local checkClassDefn      Args((Class));
 static Cell   local depPredExp         Args((Int,List,Cell));
 static Void   local checkMems           Args((Class,List,Cell));
+static Void   local checkMems2           Args((Class,Cell));
 static Void   local addMembers          Args((Class));
 static Name   local newMember           Args((Int,Int,Cell,Type,Class));
 static Name   local newDSel             Args((Class,Int));
@@ -65,7 +66,6 @@ static List   local classBindings       Args((String,Class,List));
 static Name   local memberName          Args((Class,Text));
 static List   local numInsert           Args((Int,Cell,List));
 
-       List   local typeVarsIn         Args((Cell,List,List,List));
 static List   local maybeAppendVar      Args((Cell,List));
 
 static Type   local checkSigType        Args((Int,String,Cell,Type));
@@ -953,8 +953,9 @@ Cell  cd; {                             /* definitions (w or w/o deriving) */
             con      = ty;
         }
 
-        if (nr2>0)                      /* Add rank 2 annotation           */
-            type = ap(RANK2,pair(mkInt(nr2),type));
+       if (nr2>0) {                    /* Add rank 2 annotation           */
+           type = ap(RANK2,pair(mkInt(nr2-length(lps)),type));
+       }
 
         if (nonNull(evs)) {             /* Add existential annotation      */
             if (nonNull(derivs)) {
@@ -1238,6 +1239,7 @@ List fds; {                              /* functional dependencies          */
        cclass(nw).members = ms;
        cclass(nw).level   = 0;
        cclass(nw).fds     = fds;
+       cclass(nw).xfds    = NIL;
        classDefns         = cons(nw,classDefns);
        if (arity!=1)
            h98DoesntSupport(line,"multiple parameter classes");
@@ -1296,7 +1298,7 @@ Class c; {
 
        /* Check for trivial dependency
         */
-       if (isNull(snd(fd))) {
+       if (isNull(vs)) {
            ERRMSG(cclass(c).line) "Functional dependency is trivial"
            EEND;
        }
@@ -1358,6 +1360,80 @@ Class c; {
     tcDeps              = NIL;
 }
 
+
+/* --------------------------------------------------------------------------
+ * Functional dependencies are inherited from superclasses.
+ * For example, if I've got the following classes:
+ *
+ * class C a b | a -> b
+ * class C [b] a => D a b
+ *
+ * then C will have the dependency ([a], [b]) as expected, and D will inherit
+ * the dependency ([b], [a]) from C.
+ * When doing pairwise improvement, we have to consider not just improving
+ * when we see a pair of Cs or a pair of Ds in the context, but when we've
+ * got a C and a D as well.  In this case, we only improve when the
+ * predicate in question matches the type skeleton in the relevant superclass
+ * constraint.  E.g., we improve the pair (C [Int] a, D b Int) (unifying
+ * a and b), but we don't improve the pair (C Int a, D b Int).
+ * To implement functional dependency inheritance, we calculate
+ * the closure of all functional dependencies, and store the result
+ * in an additional field `xfds' (extended functional dependencies).
+ * The `xfds' field is a list of functional dependency lists, annotated
+ * with a list of predicate skeletons constraining when improvement can
+ * happen against this dependency list.  For example, the xfds field
+ * for C above would be:
+ *     [([C a b], [([a], [b])])]
+ * and the xfds field for D would be:
+ *     [([C [b] a, D a b], [([b], [a])])]
+ * Self-improvement (of a C with a C, or a D with a D) is treated as a
+ * special case of an inherited dependency.
+ * ------------------------------------------------------------------------*/
+static List local inheritFundeps(c,pi,o)
+Class c;
+Cell pi;
+Int o; {
+    Int alpha = newKindedVars(cclass(c).kinds);
+    List scs = cclass(c).supers;
+    List xfds = NIL;
+    Cell this = NIL;
+    /* better not fail ;-) */
+    if (!matchPred(pi,o,cclass(c).head,alpha))
+       internal("inheritFundeps - predicate failed to match it's own head!");
+    this = copyPred(pi,o);
+    for (; nonNull(scs); scs=tl(scs)) {
+       Class s = getHead(hd(scs));
+       if (isClass(s)) {
+           List sfds = inheritFundeps(s,hd(scs),alpha);
+           for (; nonNull(sfds); sfds=tl(sfds)) {
+               Cell h = hd(sfds);
+               xfds = cons(pair(cons(this,fst(h)),snd(h)),xfds);
+           }
+       }
+    }
+    if (nonNull(cclass(c).fds)) {
+       List fds = NIL, fs = cclass(c).fds;
+       for (; nonNull(fs); fs=tl(fs)) {
+           fds = cons(pair(otvars(this,fst(hd(fs))),
+                           otvars(this,snd(hd(fs)))),fds);
+       }
+       xfds = cons(pair(cons(this,NIL),fds),xfds);
+    }
+    return xfds;
+}
+
+static Void local extendFundeps(c)
+Class c; {
+    Int alpha;
+    emptySubstitution();
+    alpha = newKindedVars(cclass(c).kinds);
+    cclass(c).xfds = inheritFundeps(c,cclass(c).head,alpha);
+
+    /* we can now check for ambiguity */
+    map1Proc(checkMems2,c,fst(cclass(c).members));
+}
+
+
 static Cell local depPredExp(line,tyvars,pred)
 Int  line;
 List tyvars;
@@ -1460,6 +1536,14 @@ Cell  m; {
     h98CheckType(line,"member type",hd(vs),t);
 }
 
+static Void local checkMems2(c,m) /* check member function details   */
+Class c;
+Cell  m; {
+    Int  line = intOf(fst3(m));
+    List vs   = snd3(m);
+    Type t    = thd3(m);
+}
+
 static Void local addMembers(c)         /* Add definitions of member funs  */
 Class c; {                              /* and other parts of class struct.*/
     List ms  = fst(cclass(c).members);
@@ -1541,7 +1625,6 @@ Class parent; {
     name(m).arity    = 1;
     name(m).number   = mfunNo(no);
     name(m).type     = t;
-    name(m).inlineMe = TRUE;
     return m;
 }
 
@@ -2005,7 +2088,9 @@ List vs; {
                        else
                            return cons(t,vs);
 
-       case OFFSET   : internal("zonkTyvarsIn");
+       /* this case will lead to a type error --
+          much better than reporting an internal error ;-) */
+       /* case OFFSET   : internal("zonkTyvarsIn"); */
 
        default       : return vs;
     }
@@ -2025,7 +2110,6 @@ static List local otvarsZonk(pi,os,o)     /* same as above, but zonks        */
 Cell pi;
 List os; {
     List us = NIL;
-    List vs = NIL;
     for (; nonNull(os); os=tl(os)) {
         Type t = zonkType(nthArg(offsetOf(hd(os)),pi),o);
        us = zonkTyvarsIn(t,us);
@@ -2102,11 +2186,14 @@ List ps; {
        Cell pi = hd(ps);
        Cell c  = getHead(pi);
        if (isClass(c)) {
-           List fs = cclass(c).fds;
-           for (; nonNull(fs); fs=tl(fs)) {
-               fds = cons(pair(otvars(pi,fst(hd(fs))),
-                               otvars(pi,snd(hd(fs)))),fds);
-           }
+           List xfs = cclass(c).xfds;
+           for (; nonNull(xfs); xfs=tl(xfs)) {
+               List fs = snd(hd(xfs));
+               for (; nonNull(fs); fs=tl(fs)) {
+                   fds = cons(pair(otvars(pi,fst(hd(fs))),
+                                   otvars(pi,snd(hd(fs)))),fds);
+               }
+           }
        }
 #if IPARAM
        else if (isIP(c)) {
@@ -2126,10 +2213,13 @@ List ps; {
        Cell c  = getHead(pi);
        Int o = intOf(snd3(pi3));
        if (isClass(c)) {
-           List fs = cclass(c).fds;
-           for (; nonNull(fs); fs=tl(fs)) {
-               fds = cons(pair(otvarsZonk(pi,fst(hd(fs)),o),
-                               otvarsZonk(pi,snd(hd(fs)),o)),fds);
+           List xfs = cclass(c).xfds;
+           for (; nonNull(xfs); xfs=tl(xfs)) {
+               List fs = snd(hd(xfs));
+               for (; nonNull(fs); fs=tl(fs)) {
+                   fds = cons(pair(otvarsZonk(pi,fst(hd(fs)),o),
+                                   otvarsZonk(pi,snd(hd(fs)),o)),fds);
+               }
            }
        }
 #if IPARAM
@@ -2545,6 +2635,30 @@ Inst in; {
         ERRMSG(line) "Illegal predicate in instance declaration"
         EEND;
     }
+
+    if (nonNull(cclass(inst(in).c).fds)) {
+        List fds = cclass(inst(in).c).fds;
+        for (; nonNull(fds); fds=tl(fds)) {
+            List as = otvars(inst(in).head, fst(hd(fds)));
+            List bs = otvars(inst(in).head, snd(hd(fds)));
+           List fs = calcFunDeps(inst(in).specifics);
+           as = oclose(fs,as);
+            if (!osubset(bs,as)) {
+               ERRMSG(inst(in).line)
+                  "Instance is more general than a dependency allows"
+               ETHEN
+               ERRTEXT "\n*** Instance         : "
+               ETHEN ERRPRED(inst(in).head);
+               ERRTEXT "\n*** For class        : "
+               ETHEN ERRPRED(cclass(inst(in).c).head);
+               ERRTEXT "\n*** Under dependency : "
+               ETHEN ERRFD(hd(fds));
+               ERRTEXT "\n"
+               EEND;
+            }
+        }
+    }
+
     kindInst(in,length(tyvars));
     insertInst(in);
 
@@ -2884,6 +2998,7 @@ Inst in; {                              /* of the context for a derived    */
     List spcs   = fst(snd(inst(in).specifics));
     Int  beta   = inst(in).numSpecifics;
     Int  its    = 1;
+    Int  factor = 1+length(ps);
 
 #ifdef DEBUG_DERIVING
     Printf("calcInstPreds: ");
@@ -2894,7 +3009,7 @@ Inst in; {                              /* of the context for a derived    */
     while (nonNull(ps)) {
         Cell p = hd(ps);
         ps     = tl(ps);
-       if (its++ >= cutoff) {
+       if (its++ >= factor*cutoff) {
            Cell bpi = inst(in).head;
            Cell pi  = copyPred(fun(p),intOf(snd(p)));
            ERRMSG(inst(in).line) "\n*** Cannot derive " ETHEN ERRPRED(bpi);
@@ -4865,7 +4980,8 @@ Void checkExp() {                       /* Top level static check on Expr  */
     staticAnalysis(RESET);
 }
 
-Void checkContext() {                  /* Top level static check on Expr  */
+#if EXPLAIN_INSTANCE_RESOLUTION
+Void checkContext(void) {              /* Top level static check on Expr  */
     List vs, qs;
 
     staticAnalysis(RESET);
@@ -4879,6 +4995,7 @@ Void checkContext() {                     /* Top level static check on Expr  */
     leaveScope();
     staticAnalysis(RESET);
 }
+#endif
 
 Void checkDefns() {                     /* Top level static analysis       */
     Module thisModule = lastModule();
@@ -4908,6 +5025,7 @@ Void checkDefns() {                     /* Top level static analysis       */
     checkSynonyms(tyconDefns);          /* check synonym definitions       */
     mapProc(checkClassDefn,classDefns); /* process class definitions       */
     mapProc(kindTCGroup,tcscc(tyconDefns,classDefns)); /* attach kinds     */
+    mapProc(extendFundeps,classDefns);  /* finish class definitions       */
     mapProc(addMembers,classDefns);     /* add definitions for member funs */
     mapProc(visitClass,classDefns);     /* check class hierarchy           */
     linkPreludeCM();                    /* Get prelude cfuns and mfuns     */