/* -------------------------------------------------------------------------- * preds.c: Copyright (c) Mark P Jones 1991-1998. All rights reserved. * See NOTICE for details and conditions of use etc... * Hugs version 1.3b, January 1998 * * Part of type checker dealing with predicates and entailment. * ------------------------------------------------------------------------*/ /* -------------------------------------------------------------------------- * Local function prototypes: * ------------------------------------------------------------------------*/ static Cell local assumeEvid Args((Cell,Int)); static List local makeEvidArgs Args((List,Int)); static Void local markPred Args((Cell)); static List local copyPreds Args((List)); static Cell local copyPred Args((Cell,Int)); static Void local qualify Args((List,Cell)); static Void local qualifyBinding Args((List,Cell)); static List local simplify Args((List)); static Void local overEvid Args((Cell,Cell)); static Cell local tidyEvid Args((Cell)); static Cell local simpleEntails Args((List,Cell,Int)); static List local superSels Args((Class,Class)); static Bool local anyGenerics Args((Type,Int)); static List local elimConstPreds Args((Int,List)); static Cell local getEvid Args((Int,Class,Type,Int)); static Cell local haskSimp Args((Class,Type,Int)); static Cell local haskSpecific Args((Class,Int,Type,Int)); static Class local classConstraining Args((Int,Cell,Int)); static Bool local resolveDefs Args((List,List)); static Bool local resolveVar Args((Int,List)); static Void local makePendingDicts Args((Void)); static Void local installMembers Args((Inst,Cell)); static Cell local makeMember Args((Name,Cell)); /* -------------------------------------------------------------------------- * Predicate sets: * * A predicate set is represented by a list of triples (pi, o, used) * where o is the offset for types in pi, with evidence required at the * node pointed to by used (which is taken as a dictionary parameter if * no other evidence is available). Note that the used node will be * overwritten at a later stage if evidence for that predicate is found * subsequently. * ------------------------------------------------------------------------*/ static List preds; /* current predicate list */ static List evids; /* evidence for preds */ static List hpreds; /* Haskell form predicates */ static Cell local assumeEvid(pi,o) /* add predicate pi (offset o) to */ Cell pi; /* preds with new dict var nd */ Int o; { Cell nd = inventDictVar(); preds = cons(triple(pi,mkInt(o),nd),preds); return nd; } static List local makeEvidArgs(qs,o) /* make list of predicate assumps. */ List qs; /* from qs (offset o), w/ new dict */ Int o; { /* vars for each predicate */ List result; for (result=NIL; nonNull(qs); qs=tl(qs)) result = cons(triple(hd(qs),mkInt(o),inventDictVar()),result); return rev(result); } static Void local markPred(pi) /* marked fixed type vars in pi */ Cell pi; { Cell cl = fst3(pi); Int o = intOf(snd3(pi)); for (; isAp(cl); cl=fun(cl)) markType(arg(cl),o); } static List local copyPreds(qs) /* copy list of predicates */ List qs; { List result; for (result=NIL; nonNull(qs); qs=tl(qs)) { Cell pi = hd(qs); result = cons(copyPred(fst3(pi),intOf(snd3(pi))),result); } return rev(result); } static Cell local copyPred(pi,o) /* copy single predicate (or part */ Cell pi; /* thereof) ... */ Int o; { if (isAp(pi)) { Cell temp = copyPred(fun(pi),o);/* to ensure correct order of eval.*/ return ap(temp,copyType(arg(pi),o)); } else return pi; } static Void local qualify(qs,alt) /* Add extra dictionary args to */ List qs; /* qualify alt by predicates in qs */ Cell alt; { /* :: ([Pat],Rhs) */ List ds; for (ds=NIL; nonNull(qs); qs=tl(qs)) ds = cons(thd3(hd(qs)),ds); fst(alt) = revOnto(ds,fst(alt)); } static Void local qualifyBinding(qs,b) /* Add extra dict args to each */ List qs; /* alternative in function binding */ Cell b ; { if (!isVar(fst(b))) /* check for function binding */ internal("qualifyBinding"); map1Proc(qualify,qs,snd(snd(b))); } /* -------------------------------------------------------------------------- * Predicate set Simplification: * * Calculate a minimal equivalent subset of a given set of predicates. * ------------------------------------------------------------------------*/ static List local simplify(qs) /* Simplify predicates in qs, */ List qs; { /* returning equiv minimal subset */ Int n = length(qs); while (0 cclass(d).level) { List cs = cclass(c).supers; Int n = dictSupersStart(c); for (; nonNull(cs); cs=tl(cs), ++n) { Cell dSels = superSels(hd(cs),d); if (dSels!=NONE) return cons(mkSelect(n),dSels); } } return NONE; /* use NONE to indicate failure */ } /* -------------------------------------------------------------------------- * Deal with constant and locally constant predicates * ------------------------------------------------------------------------*/ static Bool mustQual = FALSE; /* TRUE => must qualify by pred. */ static Bool tryDefer = FALSE; /* TRUE => try to defer predicate */ static Int lineProve; static Bool local anyGenerics(t,o) /* Test for generic vars, and count*/ Type t; /* fixed variables */ Int o; { Type h = getDerefHead(t,o); /* This code is careful to expand */ Int a = argCount; /* synonyms; mark* & copy* do not. */ if (isSynonym(h) && a>=tycon(h).arity) { expandSyn(h,a,&t,&o); return anyGenerics(t,o); } else { Tyvar* tyv; for (; 0offs!=FIXED_TYVAR; } } static List local elimConstPreds(l,ps) /* Cycles through current preds */ Int l; /* eliminating constant predicates */ List ps; { /* adding locally constant preds to*/ List qs = NIL; /* ps (which is used as the return */ hpreds = NIL; /* value), simplifying and then */ evids = NIL; /* calculating Haskell equiv of any*/ lineProve = l; /* predicates that remain. */ for (preds=simplify(preds); nonNull(preds);) { Cell pi = hd(preds); Cell nx = tl(preds); Cell ev = NIL; mustQual = tryDefer = FALSE; ev = haskSimp(fun(fst3(pi)),arg(fst3(pi)),intOf(snd3(pi))); if (mustQual) { /* contains generic*/ tl(preds) = qs; qs = preds; evids = cons(ev,evids); } else if (tryDefer) { /* only fixed vars */ tl(preds) = ps; ps = preds; } else { /* constant types */ Cell d = makeDictFor(ev,NIL); fst(thd3(pi)) = mkSelect(0); snd(thd3(pi)) = d; } preds = nx; } preds = qs; hpreds = simplify(hpreds); return ps; } static Cell local getEvid(l,c,t,o) /* Get evidence for known type */ Int l; Class c; Type t; Int o; { lineProve = l; mustQual = tryDefer = FALSE; hpreds = NIL; return haskSimp(c,t,o); } static Cell local haskSimp(c,t,o) /* Simplify unary pred with class c*/ Class c; /* and type (t,o) to Haskell form */ Type t; /* (i.e. class variable pairs), */ Int o; { /* and returning appropriate evid. */ Type ht; Int ho; Int a = 0; Tyvar *tyv; deRef(tyv,t,o); /* Find head of type and count args*/ for (ht=t, ho=o; isAp(ht); a++) { ht = fun(ht); deRef(tyv,ht,ho); } if (isSynonym(ht) && /* Check for synonyms, and expand */ a>=tycon(ht).arity) { /* as necessary */ expandSyn(ht,a,&t,&o); return haskSimp(c,t,o); } else if (!tyv) { /* Constructor constant at head */ Cell in = findInst(c,ht); /* Begin supertype check (yes, this code is more or less identical */ /* to parts in subst.c...) */ /* N.B. Should perhaps allow downcasting for types in POSV classes */ /* as well, but this seems to be of marginal practical use. */ if (isNull(in) && cclass(c).variance == NEGV) { List ts = NIL, ts1 = NIL, ts2; if (tycon(ht).what == DATATYPE) { Tycon tc = TYCMIN, tc2 = lastTycon(); for (; tc<=tc2; tc++) if (tycon(tc).what == DATATYPE && findAxiom(tc,ht) && findInst(c,tc)) ts = cons(tc,ts); } else { List axs = tycon(ht).axioms; for (; nonNull(axs); axs=tl(axs)) { Tycon tc = getHead(monoType(hd(axs))); if (findInst(c,tc)) ts = cons(tc,ts); } } for (ts2 = ts; nonNull(ts2); ts2=tl(ts2)) if (allSubtypes(ts,hd(ts2),NEGV)) ts1 = cons(hd(ts2),ts1); if (nonNull(ts1) && isNull(tl(ts1))) { Tycon tc = hd(ts1); Type t1, t2; Int off, n = tycon(ht).arity - a; if (tycon(ht).what == DATATYPE) { t1 = findAxiom(tc,ht); t2 = satTycon(tc); instantiate(t1,&t1,&off,NIL); } else { t2 = findAxiom(ht,tc); t1 = satTycon(ht); instantiate(t2,&t2,&off,NIL); } if (n <= tycon(tc).arity) { Int hi = tycon(ht).arity - 1, lo = hi - n; a = tycon(tc).arity - n; for (; n>0; n--, t1=fun(t1), t2=fun(t2)) if (!isOffset(arg(t1)) || arg(t1) != arg(t2)) break; if (!n && !offsetsBetween(lo,hi,t1) && !offsetsBetween(lo,hi,t2) && unify(t,o,t1,off)) { t = t2; o = off; in = findInst(c,tc); } } } } /* End supertype check */ if (isNull(in)) { ERRMSG(lineProve) "" ETHEN ERRTYPE(copyType(t,o)); ERRTEXT " is not an instance of class \"%s\"", textToStr(cclass(c).text) EEND; } else if (a!=inst(in).arity) internal("arity mismatch"); else if (nonNull(inst(in).specifics)) { List sps = inst(in).specifics; for (; nonNull(sps); sps=tl(sps)) in = ap(in,haskSpecific(fun(hd(sps)), a-offsetOf(arg(hd(sps)))-1, t, o)); } return in; } else if (a>0) { /* Variable applied to >0 args */ if ((isUnbound(tyv) && tyv->offs!=FIXED_TYVAR) || anyGenerics(t,o)) { ERRMSG(lineProve) "Illegal class constraint " ETHEN ERRPRED(pair(c,copyType(t,o))); ERRTEXT " in inferred type." EEND; } /* intentional fall-thru */ } else if (isUnbound(tyv) && tyv->offs!=FIXED_TYVAR) { /* Generic variable */ Cell nd = inventDictVar(); Int vn = tyvNum(tyv); Cell pi = ap(c,mkInt(vn)); hpreds = cons(triple(pi,mkInt(0),nd),hpreds); mustQual = TRUE; return nd; } /* Here if we encounter a predicate containing no generics with a fixed * var at its head. In this case, locally constant overloading applies * and we can choose to defer to an outer scope where the fixed var will * either be bound, or become generic and hence trigger a later error. */ tryDefer = TRUE; return NIL; } static Cell local haskSpecific(c,n,t,o) /* take n args down from the root */ Class c; /* of (t,o) and construct corresp. */ Int n; /* instance of class c */ Type t; Int o; { Tyvar *tyv; for (; 00; --i, ++di) { printf("dict(%d+%d)@%d = ",dictOf(dc),di,dc); printExp(stdout,dictGet(dc,di)); putchar('\n'); } } #endif } static Cell local makeMember(n,dc) /* set initial value of member fn */ Name n; Cell dc; { return (nonNull(name(n).type)) ? ap(ap(nameMakeMem,dc),n) : n; } /*-------------------------------------------------------------------------*/