home *** CD-ROM | disk | FTP | other *** search
- /* --------------------------------------------------------------------------
- * type.c: Copyright (c) Mark P Jones 1991-1993. All rights reserved.
- * See goferite.h for details and conditions of use etc...
- * Gofer version 2.28 January 1993
- *
- * This is the Gofer type checker: Based on the extended algorithm in my
- * PRG technical report PRG-TR-10-91, supporting the use of qualified types
- * in the form of multi-parameter type classes, according to my `new
- * approach' to type classes posted to the Haskell mailing list.
- * This program uses the optimisations for constant and locally-constant
- * overloading.
- * ------------------------------------------------------------------------*/
-
- #include "prelude.h"
- #include "storage.h"
- #include "connect.h"
- #include "errors.h"
-
- #if MPW
- #pragma segment Type
- #endif
-
- /*#define DEBUG_TYPES*/
- /*#define DEBUG_KINDS*/
-
- Bool coerceNumLiterals = FALSE; /* TRUE => insert fromInteger calls*/
- /* etc for numeric literals*/
- Bool catchAmbigs = FALSE; /* TRUE => functions with ambig. */
- /* types produce error */
- Bool overSingleton = TRUE; /* TRUE => overload singleton list */
- /* notation, [x] */
-
- Type typeString, typeDialogue; /* String & Dialogue types */
- Name nameTrue, nameFalse; /* primitive boolean constructors */
- Name nameNil, nameCons; /* primitive list constructors */
-
- #ifdef LAMBDAVAR
- static Type typeProc, typeVar; /* primitive Proc and Var types */
- Name nameVar; /* primitive Var constructor */
- Type typeProg; /* program Proc () */
- #endif
- #if MAC
- Type typeIO, typeState; /* Primitive IO and State types */
- Name nameIO; /* IO constructor */
- #endif
-
- #ifdef LAMBDANU
- static Type typeCmd, typeTag; /* primitive Cmd and Tag types */
- Name nameTag; /* primitive Tag constructor */
- Type typeLnProg; /* program Cmd a () */
- #endif
-
- Name nameReadFile, nameWriteFile; /* I/O name primitives */
- Name nameAppendFile, nameReadChan;
- Name nameAppendChan, nameEcho;
- Name nameGetArgs, nameGetProgName;
- Name nameGetEnv;
- Name nameSuccess, nameStr;
- Name nameFailure, nameStrList;
- Name nameWriteError;
- Name nameReadError, nameSearchError;
- Name nameFormatError, nameOtherError;
-
- #if MAC
- Name nameImperate;
- #endif
-
- /* --------------------------------------------------------------------------
- * Data structures for storing a substitution:
- *
- * For various reasons, this implementation uses structure sharing, instead of
- * a copying approach. In principal, this is fast and avoids the need to
- * build new type expressions. Unfortunately, this implementation will not
- * be able to handle *very* large expressions.
- *
- * The substitution is represented by an array of type variables each of
- * which is a triple:
- * bound a (skeletal) type expression, or NIL if the variable
- * is not bound.
- * offs offset of skeleton in bound. If isNull(bound), then offs is
- * used to indicate whether that variable is generic (i.e. free
- * in the current assumption set) or fixed (i.e. bound in the
- * current assumption set). Generic variables are assigned
- * offset numbers whilst copying type expressions (t,o) to
- * obtain their most general form.
- * kind kind of value bound to type variable (`type variable' is
- * rather inaccurate -- `constructor variable' would be better).
- * ------------------------------------------------------------------------*/
-
- typedef struct { /* Each type variable contains: */
- Type bound; /* A type skeleton (unbound==NIL) */
- Int offs; /* Offset for skeleton */
- Kind kind; /* kind annotation */
- } Tyvar;
-
- static Int numTyvars; /* no. type vars currently in use */
-
- #if DYNAMIC_STORAGE
- static Tyvar *tyvars; /* storage for type variables */
- #else
- #define num_tyvars NUM_TYVARS
- static Tyvar tyvars[NUM_TYVARS]; /* storage for type variables */
- #endif
-
- static Int typeOff; /* offset of result type */
- static Type typeIs; /* skeleton of result type */
- static List predsAre; /* list of predicates in type */
- #define tyvar(n) (tyvars+(n)) /* nth type variable */
- #define tyvNum(t) ((t)-tyvars) /* and the corresp. inverse funct. */
- static Int nextGeneric; /* number of generics found so far */
- static List genericVars; /* list of generic vars */
-
- /* offs values when isNull(bound): */
- #define FIXED_TYVAR 0 /* fixed in current assumption */
- #define UNUSED_GENERIC 1 /* not fixed, not yet encountered */
- #define GENERIC 2 /* GENERIC+n==nth generic var found*/
-
- /* --------------------------------------------------------------------------
- * Local function prototypes:
- * ------------------------------------------------------------------------*/
-
- static Void local emptySubstitution Args((Void));
- static Int local newTyvars Args((Int));
- static Int local newKindedVars Args((Kind));
- static Tyvar *local getTypeVar Args((Type,Int));
- static Void local tyvarType Args((Int));
- static Void local bindTv Args((Int,Type,Int));
- static Void local expandSynonym Args((Tycon, Type *, Int *));
- static Cell local getDerefHead Args((Type,Int));
-
- static Void local clearMarks Args((Void));
- static Void local resetGenericsFrom Args((Int));
- static Void local markTyvar Args((Int));
- static Void local markType Args((Type,Int));
-
- static Type local copyTyvar Args((Int));
- static Type local copyType Args((Type,Int));
- #ifdef DEBUG_TYPES
- static Type local debugTyvar Args((Int));
- static Type local debugType Args((Type,Int));
- #endif
-
- static Bool local doesntOccurIn Args((Type,Int));
-
- static Bool local varToVarBind Args((Tyvar *,Tyvar *));
- static Bool local varToTypeBind Args((Tyvar *,Type,Int));
- static Bool local kvarToVarBind Args((Tyvar *,Tyvar *));
- static Bool local kvarToTypeBind Args((Tyvar *,Type,Int));
- static Bool local unify Args((Type,Int,Type,Int));
- static Bool local sameType Args((Type,Int,Type,Int));
- static Bool local kunify Args((Kind,Int,Kind,Int));
-
- static Void local kindError Args((Int,Constr,Constr,String,Kind,Int));
- static Void local kindConstr Args((Int,Constr));
- static Kind local kindAtom Args((Constr));
- static Void local kindPred Args((Int,Cell));
- static Void local kindType Args((Int,String,Type));
- static Void local fixKinds Args((Void));
-
- static Void local initTyconKind Args((Tycon));
- static Void local kindTycon Args((Tycon));
- static Void local genTycon Args((Tycon));
- static Kind local copyKindvar Args((Int));
- static Kind local copyKind Args((Kind,Int));
-
- static Void local initClassKind Args((Class));
- static Void local kindClass Args((Class));
- static Void local genClassSig Args((Class));
-
- static Bool local eqKind Args((Kind,Kind));
- static Kind local getKind Args((Cell,Int));
-
- static Kind local makeSimpleKind Args((Int));
- static Kind local simpleKind Args((Int));
- static Kind local makeVarKind Args((Int));
- static Void local varKind Args((Int));
-
- static Void local emptyAssumption Args((Void));
- static Void local enterBindings Args((Void));
- static Void local leaveBindings Args((Void));
- static Void local markAssumList Args((List));
- static Cell local findAssum Args((Text));
- static Pair local findInAssumList Args((Text,List));
- static Int local newVarsBind Args((Cell));
- static Void local newDefnBind Args((Cell,Type));
- static Void local instantiate Args((Type));
-
- static Void local typeError Args((Int,Cell,Cell,String,Type,Int));
- static Cell local typeExpr Args((Int,Cell));
- static Cell local varIntro Args((Cell,Type));
- static Void local typeEsign Args((Int,Cell));
- static Void local typeCase Args((Int,Int,Cell));
- static Void local typeComp Args((Int,Type,Cell,List));
- static Void local typeMonadComp Args((Int,Cell));
- static Cell local compZero Args((List,Int));
- static Cell local typeFreshPat Args((Int,Cell));
-
- static Cell local typeAp Args((Int,Cell));
- static Void local typeAlt Args((Cell));
- static Int local funcType Args((Int));
-
- static Void local typeTuple Args((Cell));
- static Type local makeTupleType Args((Int));
-
- static Void local typeBindings Args((List));
- static Void local removeTypeSigs Args((Cell));
-
- static Void local noOverloading Args((List));
- static Void local restrictedBindAss Args((Cell));
- static Void local restrictedAss Args((Int,Cell,Type));
-
- static Void local explicitTyping Args((List));
- static List local gotoExplicit Args((List));
- static List local explPreds Args((Text,List,List));
-
- static Void local implicitTyping Args((List));
- static Void local addEvidParams Args((List,Cell));
-
- static Void local typeInstDefn Args((Inst));
- static Void local typeClassDefn Args((Class));
- static Void local typeMembers Args((String,List,List,Cell,Kind));
- static Void local typeMember Args((String,Name,Name,Cell,Kind));
-
- static Void local typeBind Args((Cell));
- static Void local typeDefAlt Args((Int,Cell,Pair));
- static Cell local typeRhs Args((Cell));
- static Void local guardedType Args((Int,Cell));
-
- static Void local generaliseBind Args((Int,List,Cell));
- static Void local generaliseAss Args((Int,List,Cell));
- static Type local generalise Args((List,Type));
-
- static Void local checkBindSigs Args((Cell));
- static Void local checkTypeSig Args((Int,Cell,Type));
- static Void local tooGeneral Args((Int,Cell,Type,Type));
-
- static Bool local equalSchemes Args((Type,Type));
- static Bool local equalQuals Args((List,List));
- static Bool local equalTypes Args((Type,Type));
-
- static Void local typeDefnGroup Args((List));
-
- static Void local initIOtypes Args((Void));
- #if DYNAMIC_STORAGE
- Void local Dynamic_Type_Init Args((Void));
- #endif
-
- /* --------------------------------------------------------------------------
- * Frequently used type skeletons:
- * ------------------------------------------------------------------------*/
-
- static Type var; /* mkOffset(0) */
- static Type arrow; /* mkOffset(0) -> mkOffset(1) */
- static Type typeList; /* [ mkOffset(0) ] */
- static Type typeBool; /* Bool */
- static Type typeInt; /* Int (or Num) */
- static Type typeFloat; /* Float */
- static Type typeUnit; /* () */
- static Type typeChar; /* Char */
- static Type typeIntToInt; /* Int -> Int */
-
- static Name nameFromInt; /* fromInteger function */
- static Class classNum; /* class Num */
- static Cell predNum; /* Num (mkOffset(0)) */
- static Class classMonad; /* class Monad */
- static Cell predMonad; /* Monad (mkOffset(0)) */
- static Class classMonad0; /* class Monad0 */
- static Cell predMonad0; /* Monad0 (mkOffset(0)) */
- static Kind starToStar; /* Type -> Type */
- static Kind monadSig; /* [Type -> Type] */
-
- /* --------------------------------------------------------------------------
- * Basic operations on current substitution:
- * ------------------------------------------------------------------------*/
-
- #include "subst.c"
-
- /* --------------------------------------------------------------------------
- * Kind expressions:
- *
- * In the same way that values have types, type constructors (and more
- * generally, expressions built from such constructors) have kinds.
- * The syntax of kinds in the current implementation is very simple:
- *
- * kind ::= STAR -- the kind of types
- * | kind => kind -- constructors
- * | variables -- either INTCELL or OFFSET
- *
- * ------------------------------------------------------------------------*/
-
- #include "kind.c"
-
- #if MPW
- #pragma segment Type
- #endif
-
- /* --------------------------------------------------------------------------
- * Assumptions:
- *
- * A basic typing statement is a pair (Var,Type) and an assumption contains
- * an ordered list of basic typing statements in which the type for a given
- * variable is given by the most recently added assumption about that var.
- *
- * In practice, the assumption set is split between a pair of lists, one
- * holding assumptions for vars defined in bindings, the other for vars
- * defined in patterns/binding parameters etc. The reason for this
- * separation is that vars defined in bindings may be overloaded (with the
- * overloading being unknown until the whole binding is typed), whereas the
- * vars defined in patterns have no overloading. A form of dependency
- * analysis (at least as far as calculating dependents within the same group
- * of value bindings) is required to implement this. Where it is known that
- * no overloaded values are defined in a binding (i.e. when the `dreaded
- * monomorphism restriction' strikes), the list used to record dependents
- * is flagged with a NODEPENDS tag to avoid gathering dependents at that
- * level.
- *
- * To interleave between vars for bindings and vars for patterns, we use
- * a list of lists of typing statements for each. These lists are always
- * the same length. The implementation here is very similar to that of the
- * dependency analysis used in the static analysis component of this system.
- * ------------------------------------------------------------------------*/
-
- static List defnBounds; /*::[[(Var,Type)]] possibly ovrlded*/
- static List varsBounds; /*::[[(Var,Type)]] not overloaded */
- static List depends; /*::[?[Var]] dependents/NODEPENDS */
-
- #define saveVarsAssump() List saveAssump = hd(varsBounds)
- #define restoreVarsAss() hd(varsBounds) = saveAssump
-
- static Void local emptyAssumption() { /* set empty type assumption */
- defnBounds = NIL;
- varsBounds = NIL;
- depends = NIL;
- }
-
- static Void local enterBindings() { /* Add new level to assumption sets */
- defnBounds = cons(NIL,defnBounds);
- varsBounds = cons(NIL,varsBounds);
- depends = cons(NIL,depends);
- }
-
- static Void local leaveBindings() { /* Drop one level of assumptions */
- defnBounds = tl(defnBounds);
- varsBounds = tl(varsBounds);
- depends = tl(depends);
- }
-
- static Void local markAssumList(as) /* Mark all types in assumption set */
- List as; { /* :: [(Var, Type)] */
- for (; nonNull(as); as=tl(as)) /* No need to mark generic types; */
- if (!isPolyType(snd(hd(as)))) /* the only free variables in those */
- markType(snd(hd(as)),0); /* must have been free earlier too */
- }
-
- static Cell local findAssum(t) /* Find most recent assumption about*/
- Text t; { /* variable named t, if any */
- List defnBounds1 = defnBounds; /* return translated variable, with */
- List varsBounds1 = varsBounds; /* type in typeIs */
- List depends1 = depends;
-
- while (nonNull(defnBounds1)) {
- Pair ass = findInAssumList(t,hd(varsBounds1));/* search varsBounds */
- if (nonNull(ass)) {
- typeIs = snd(ass);
- return fst(ass);
- }
-
- ass = findInAssumList(t,hd(defnBounds1)); /* search defnBounds */
- if (nonNull(ass)) {
- Cell v = fst(ass);
- typeIs = snd(ass);
-
- if (hd(depends1)!=NODEPENDS && /* save dependent? */
- isNull(v=varIsMember(t,hd(depends1))))
- /* N.B. make new copy of variable and store this on list of*/
- /* dependents, and in the assumption so that all uses of */
- /* the variable will be at the same node, if we need to */
- /* overwrite the call of a function with a translation... */
- hd(depends1) = cons(v=mkVar(t),hd(depends1));
-
- return v;
- }
-
- defnBounds1 = tl(defnBounds1); /* look in next level*/
- varsBounds1 = tl(varsBounds1); /* of assumption set */
- depends1 = tl(depends1);
- }
- return NIL;
- }
-
- static Pair local findInAssumList(t,as)/* Search for assumption for var */
- Text t; /* named t in list of assumptions as*/
- List as; {
- for (; nonNull(as); as=tl(as))
- if (textOf(fst(hd(as)))==t)
- return hd(as);
- return NIL;
- }
-
- #define findTopBinding(v) findInAssumList(textOf(v),hd(defnBounds))
-
- static Int local newVarsBind(v) /* make new assump for pattern var */
- Cell v; {
- Int beta = newTyvars(1);
- hd(varsBounds) = cons(pair(v,mkInt(beta)), hd(varsBounds));
- #ifdef DEBUG_TYPES
- printf("variable, assume ");
- printExp(stdout,v);
- printf(" :: _%d\n",beta);
- #endif
- return beta;
- }
-
- static Void local newDefnBind(v,type) /* make new assump for defn var */
- Cell v; /* and set type if given (nonNull) */
- Type type; {
- Int beta = newTyvars(1);
- hd(defnBounds) = cons(pair(v,mkInt(beta)), hd(defnBounds));
- instantiate(type);
- #ifdef DEBUG_TYPES
- printf("definition, assume ");
- printExp(stdout,v);
- printf(" :: _%d\n",beta);
- #endif
- bindTv(beta,typeIs,typeOff); /* Bind beta to new type skeleton */
- }
-
- static Void local instantiate(type) /* instantiate type expr, if nonNull*/
- Type type; {
- predsAre = NIL;
- typeIs = type;
- typeOff = 0;
-
- if (nonNull(typeIs)) { /* instantiate type expression ? */
-
- if (isPolyType(typeIs)) { /* Polymorphic type scheme ? */
- typeOff = newKindedVars(polySigOf(typeIs));
- typeIs = monoTypeOf(typeIs);
- }
-
- if (whatIs(typeIs)==QUAL) { /* Qualified type? */
- predsAre = fst(snd(typeIs));
- typeIs = snd(snd(typeIs));
- }
- }
- }
-
- /* --------------------------------------------------------------------------
- * Predicate sets:
- *
- * A predicate set is represented by a list of triples (C t, o, used)
- * which indicates that type (t,o) must be an instance of class C, with
- * evidence required at the node pointed to by used. Note that the `used'
- * node may need to be overwritten at a later stage if this evidence is
- * to be derived from some other predicates by entailment.
- * ------------------------------------------------------------------------*/
-
- #include "preds.c"
-
- /* --------------------------------------------------------------------------
- * Type errors:
- * ------------------------------------------------------------------------*/
-
- static Void local typeError(l,e,in,wh,t,o)
- Int l; /* line number near type error */
- String wh; /* place in which error occurs */
- Cell e; /* source of error */
- Cell in; /* context if any (NIL if not) */
- Type t; /* should be of type (t,o) */
- Int o; { /* type inferred is (typeIs,typeOff) */
-
- clearMarks(); /* types printed here are monotypes */
- /* use marking to give sensible names*/
- #ifdef DEBUG_KINDS
- { List vs = genericVars;
- for (; nonNull(vs); vs=tl(vs)) {
- Int v = intOf(hd(vs));
- printf("%c :: ", ('a'+tyvar(v)->offs));
- printKind(stdout,tyvar(v)->kind);
- putchar('\n');
- }
- }
- #endif
-
- ERROR(l) "Type error in %s", wh ETHEN
- if (nonNull(in)) {
- ERRTEXT "\n*** expression : " ETHEN ERREXPR(in);
- }
- ERRTEXT "\n*** term : " ETHEN ERREXPR(e);
- ERRTEXT "\n*** type : " ETHEN ERRTYPE(copyType(typeIs,typeOff));
- ERRTEXT "\n*** does not match : " ETHEN ERRTYPE(copyType(t,o));
- if (unifyFails) {
- ERRTEXT "\n*** because : %s", unifyFails ETHEN
- }
- ERRTEXT "\n"
- EEND;
- }
-
- #define shouldBe(l,e,in,where,t,o) if (!unify(typeIs,typeOff,t,o)) \
- typeError(l,e,in,where,t,o);
- #define check(l,e,in,where,t,o) e=typeExpr(l,e); shouldBe(l,e,in,where,t,o)
- #define inferType(t,o) typeIs=t; typeOff=o
-
- /* --------------------------------------------------------------------------
- * Typing of expressions:
- * ------------------------------------------------------------------------*/
-
- #if MAC
- extern Bool moduleCoerceNumLiterals;
- #endif
-
- static patternMode = FALSE; /* set TRUE to type check pattern */
-
- #ifdef DEBUG_TYPES
- static Cell local mytypeExpr Args((Int,Cell));
- static Cell local typeExpr(l,e)
- Int l;
- Cell e; {
- static int number = 0;
- Cell retv;
- int mynumber = number++;
- printf("%d) to check: ",mynumber);
- printExp(stdout,e);
- putchar('\n');
- retv = mytypeExpr(l,e);
- printf("%d) result: ",mynumber);
- printType(stdout,debugType(typeIs,typeOff));
- putchar('\n');
- return retv;
- }
- static Cell local mytypeExpr(l,e) /* Determine type of expr/pattern */
- #else
- static Cell local typeExpr(l,e) /* Determine type of expr/pattern */
- #endif
- Int l;
- Cell e; {
- static String cond = "conditional";
- static String list = "list";
- static String discr = "case discriminant";
- static String aspat = "as (@) pattern";
-
- STACK_CHECK; /* KH */
-
- switch (whatIs(e)) {
-
- /* The following cases can occur in either pattern or expr. mode */
-
- case AP : return typeAp(l,e);
-
- case NAME : if (isNull(name(e).type))
- internal("typeExpr1");
- return varIntro(e,name(e).type);
-
- case TUPLE : typeTuple(e);
- break;
-
- case INTCELL : if (!patternMode
- #if MAC
- && (coerceNumLiterals||moduleCoerceNumLiterals)
- #else
- && coerceNumLiterals
- #endif
- && nonNull(predNum)) {
- Int alpha = newTyvars(1);
- inferType(var,alpha);
- return ap(ap(nameFromInt,
- assumeEvid(predNum,alpha)),
- e);
- }
- else {
- inferType(typeInt,0);
- }
- break;
-
- case FLOATCELL : inferType(typeFloat,0);
- break;
-
- case STRCELL : inferType(typeString,0);
- break;
-
- case UNIT : inferType(typeUnit,0);
- break;
-
- case CHARCELL : inferType(typeChar,0);
- break;
-
- case VAROPCELL :
- case VARIDCELL : if (patternMode) {
- inferType(var,newVarsBind(e));
- }
- else {
- Cell a = findAssum(textOf(e));
- if (nonNull(a))
- return varIntro(a,typeIs);
- else {
- a = findName(textOf(e));
- if (isNull(a) || isNull(name(a).type))
- internal("typeExpr2");
- return varIntro(a,name(a).type);
- }
- }
- break;
-
- /* The following cases can only occur in expr mode */
-
- case COND : { Int beta = newTyvars(1);
- check(l,fst3(snd(e)),e,cond,typeBool,0);
- check(l,snd3(snd(e)),e,cond,var,beta);
- check(l,thd3(snd(e)),e,cond,var,beta);
- tyvarType(beta);
- }
- break;
-
- case LETREC : enterBindings();
- mapProc(typeBindings,fst(snd(e)));
- snd(snd(e)) = typeExpr(l,snd(snd(e)));
- leaveBindings();
- break;
- case FINLIST : if (!patternMode && nonNull(nameResult)
- && isNull(tl(snd(e)))
- && overSingleton)
- typeMonadComp(l,e);
- else {
- Int beta = newTyvars(1);
- List xs;
- for (xs=snd(e); nonNull(xs); xs=tl(xs)) {
- check(l,hd(xs),e,list,var,beta);
- }
- inferType(typeList,beta);
- }
- break;
-
- case COMP : if (nonNull(nameResult))
- typeMonadComp(l,e);
- else {
- Int beta = newTyvars(1);
- typeComp(l,typeList,snd(e),snd(snd(e)));
- bindTv(beta,typeIs,typeOff);
- inferType(typeList,beta);
- fst(e) = LISTCOMP;
- }
- break;
-
- case ESIGN : typeEsign(l,e);
- return fst(snd(e));
-
- case CASE : { Int beta = newTyvars(2); /* discr result */
- check(l,fst(snd(e)),NIL,discr,var,beta);
- map2Proc(typeCase,l,beta,snd(snd(e)));
- tyvarType(beta+1);
- }
- break;
-
- case LAMBDA : typeAlt(snd(e));
- break;
-
- /* The remaining cases can only occur in pattern mode: */
-
- case WILDCARD : inferType(var,newTyvars(1));
- break;
-
- case ASPAT : { Int beta = newTyvars(1);
- snd(snd(e)) = typeExpr(l,snd(snd(e)));
- bindTv(beta,typeIs,typeOff);
- check(l,fst(snd(e)),e,aspat,var,beta);
- tyvarType(beta);
- }
- break;
-
- case LAZYPAT : snd(e) = typeExpr(l,snd(e));
- break;
-
- case ADDPAT :
- case MULPAT : inferType(typeIntToInt,0);
- break;
-
- default : internal("typeExpr3");
- }
-
- return e;
- }
-
- static Cell local varIntro(v,type) /* make translation of var v with */
- Cell v; /* given type adding any extra dict*/
- Type type; { /* params required */
- /* N.B. In practice, v will either be a NAME or a VARID/OPCELL */
- for (instantiate(type); nonNull(predsAre); predsAre=tl(predsAre))
- v = ap(v,assumeEvid(hd(predsAre),typeOff));
- return v;
- }
-
- static Void local typeEsign(l,e) /* Type check expression type sig */
- Int l;
- Cell e; {
- static String typeSig = "type signature expression";
- List savePreds = preds;
- Int alpha = newTyvars(1);
- List expPreds; /* explicit preds in type sig */
- List qs; /* qualifying preds in infered type*/
- Type nt; /* complete infered type */
-
- preds = NIL;
- instantiate(snd(snd(e)));
- bindTv(alpha,typeIs,typeOff);
- expPreds = makeEvidArgs(predsAre,typeOff);
- check(l,fst(snd(e)),NIL,typeSig,var,alpha);
-
- clearMarks();
- mapProc(markAssumList,defnBounds);
- mapProc(markAssumList,varsBounds);
- mapProc(markPred,savePreds);
-
- savePreds = elimConstPreds(l,typeSig,e,savePreds);
-
- explicitProve(l,typeSig,fst(snd(e)),expPreds,preds);
-
- resetGenericsFrom(0);
- qs = copyPreds(expPreds);
- nt = generalise(qs,copyTyvar(alpha));
-
- if (!equalSchemes(nt,snd(snd(e))))
- tooGeneral(l,fst(snd(e)),snd(snd(e)),nt);
-
- tyvarType(alpha);
- preds = revOnto(expPreds,savePreds);
- }
-
- static Void local typeCase(l,beta,c) /* type check case: pat -> rhs */
- Int l; /* (case given by c == (pat,rhs)) */
- Int beta; /* need: pat :: (var,beta) */
- Cell c; { /* rhs :: (var,beta+1) */
- static String casePat = "case pattern";
- static String caseExpr = "case expression";
-
- saveVarsAssump();
-
- fst(c) = typeFreshPat(l,fst(c));
- shouldBe(l,fst(c),NIL,casePat,var,beta);
- snd(c) = typeRhs(snd(c));
- shouldBe(l,rhsExpr(snd(c)),NIL,caseExpr,var,beta+1);
-
- restoreVarsAss();
- }
-
- static Void local typeComp(l,m,e,qs) /* type check comprehension */
- Int l;
- Type m; /* monad (mkOffset(0)) */
- Cell e;
- List qs; {
- static String boolQual = "boolean qualifier";
- static String genQual = "generator";
-
- STACK_CHECK; /* KH */
-
- if (isNull(qs)) /* no qualifiers left */
- fst(e) = typeExpr(l,fst(e));
- else {
- Cell q = hd(qs);
- List qs1 = tl(qs);
- switch (whatIs(q)) {
- case BOOLQUAL : check(l,snd(q),NIL,boolQual,typeBool,0);
- typeComp(l,m,e,qs1);
- break;
-
- case QWHERE : enterBindings();
- mapProc(typeBindings,snd(q));
- typeComp(l,m,e,qs1);
- leaveBindings();
- break;
-
- case FROMQUAL : { Int beta = newTyvars(1);
- saveVarsAssump();
- check(l,snd(snd(q)),NIL,genQual,m,beta);
- fst(snd(q)) = typeFreshPat(l,fst(snd(q)));
- shouldBe(l,fst(snd(q)),NIL,genQual,var,beta);
- typeComp(l,m,e,qs1);
- restoreVarsAss();
- }
- break;
- }
- }
- }
-
- static Void local typeMonadComp(l,e) /* type check a monad comprehension*/
- Int l;
- Cell e; {
- Int alpha = newTyvars(1);
- Int beta = newKindedVars(monadSig);
- Cell mon = ap(mkInt(beta),var);
- typeComp(l,mon,snd(e),snd(snd(e)));
- bindTv(alpha,typeIs,typeOff);
- inferType(mon,alpha);
- fst(e) = MONADCOMP;
- snd(e) = pair(pair(assumeEvid(predMonad,beta),
- compZero(snd(snd(e)),beta)),snd(e));
- }
-
- static Cell local compZero(qs,beta) /* return evidence for Monad0 beta */
- List qs; /* if needed for qualifiers qs */
- Int beta; {
- for (; nonNull(qs); qs=tl(qs))
- switch (whatIs(hd(qs))) {
- case FROMQUAL : if (!refutable(fst(snd(hd(qs)))))
- break;
- /* intentional fall-thru */
- case BOOLQUAL : return assumeEvid(predMonad0,beta);
- }
- return NIL;
- }
-
- static Cell local typeFreshPat(l,p) /* find type of pattern, assigning */
- Int l; /* fresh type variables to each var */
- Cell p; { /* bound in the pattern */
- patternMode = TRUE;
- p = typeExpr(l,p);
- patternMode = FALSE;
- return p;
- }
-
- /* --------------------------------------------------------------------------
- * Note the pleasing duality in the typing of application and abstraction:-)
- * ------------------------------------------------------------------------*/
-
- static Cell local typeAp(l,e) /* Type check application */
- Int l;
- Cell e; {
- static String app = "application";
- Cell h = getHead(e); /* e = h e1 e2 ... en */
- Int n = argCount; /* save no. of arguments */
- Int beta = funcType(n);
- Cell p = NIL; /* points to previous AP node */
- Cell a = e; /* points to current AP node */
- Int i;
-
- check(l,h,e,app,var,beta); /* check h::t1->t2->...->tn->rn+1 */
- for (i=n; i>0; --i) { /* check e_i::t_i for each i */
- check(l,arg(a),e,app,var,beta+2*i-1);
- p = a;
- a = fun(a);
- }
- fun(p) = h; /* replace head with translation */
- tyvarType(beta+2*n); /* inferred type is r_n+1 */
- return e;
- }
-
- static Void local typeAlt(a) /* Type check abstraction (Alt) */
- Cell a; { /* a = ( [p1, ..., pn], rhs ) */
- List ps = fst(a);
- Int n = length(ps);
- Int beta = funcType(n);
- Int l = rhsLine(snd(a));
- Int i;
-
- saveVarsAssump();
-
- for (i=0; i<n; ++i) {
- hd(ps) = typeFreshPat(l,hd(ps));
- bindTv(beta+2*i+1,typeIs,typeOff);
- ps = tl(ps);
- }
- snd(a) = typeRhs(snd(a));
- bindTv(beta+2*n,typeIs,typeOff);
- tyvarType(beta);
-
- restoreVarsAss();
- }
-
- static Int local funcType(n) /*return skeleton for function type*/
- Int n; { /*with n arguments, taking the form*/
- Int beta = newTyvars(2*n+1); /* r1 t1 r2 t2 ... rn tn rn+1 */
- Int i; /* with r_i := t_i -> r_i+1 */
- for (i=0; i<n; ++i)
- bindTv(beta+2*i,arrow,beta+2*i+1);
- return beta;
- }
-
- /* --------------------------------------------------------------------------
- * Tuple type constructors: are generated as necessary. The most common
- * n-tuple constructors (n<MAXTUPCON) are held in a cache to avoid
- * repeated generation of the constructor types.
- *
- * ???Maybe this cache should extend to all valid tuple constrs???
- * ------------------------------------------------------------------------*/
-
- #define MAXTUPCON 10
- static Type tupleConTypes[MAXTUPCON];
-
- static Void local typeTuple(e) /* find type for tuple constr, using*/
- Cell e; { /* tupleConTypes to cache previously*/
- Int n = tupleOf(e); /* calculated tuple constr. types. */
- t k implementation i*/
- String wh; /* of member m at instance t */
- Name m; /* where ar = sig of vars in t*/
- Name i;
- Cell pi;
- Kind ar; {
- Int line = rhsLine(snd(hd(name(i).defn)));
- Int alpha, beta;
- Type rt = NIL; /* required type */
- Type it = NIL; /* inferred type */
- List evid; /* evidence assignment */
- List qs; /* predicate list */
-
- emptySubstitution();
- hd(defnBounds) = NIL;
- hd(depends) = NODEPENDS;
- preds = NIL;
-
- alpha = newTyvars(1); /* record expected type */
- beta = newKindedVars(ar);
- instantiate(name(m).type);
- bindTv(alpha,typeIs,typeOff);
- if (isNull(predsAre) || !oneWayMatches(hd(predsAre),typeOff,pi,beta))
- internal("typeMember1");
- evid = singleton(triple(hd(predsAre),mkInt(typeOff),dictVar));
-
- resetGenericsFrom(0); /* Set required type, rt */
- qs = copyPreds(evid);
- rt = generalise(qs,copyTyvar(alpha));
-
- map2Proc(typeDefAlt,alpha,m,name(i).defn); /* Type each alt in defn */
-
- clearMarks();
- if (nonNull(elimConstPreds(line,wh,m,NIL))) /* need to resolve constant*/
- internal("typeMember2"); /* overloading - shouldn't */
- /* be any locally constant */
- /* overloading at all! */
-
- explicitProve(line,wh,m,evid,preds); /* resolve remaining preds */
-
- resetGenericsFrom(0); /* Determine inferred type */
- qs = copyPreds(evid);
- it = generalise(qs,copyTyvar(alpha));
-
- if (!equalSchemes(rt,it)) /* check inferred type ok */
- tooGeneral(line,m,rt,it);
-
- map1Proc(qualify,evid,name(i).defn); /* add dictionary parameter*/
-
- overDefns = cons(i,overDefns);
- }
-
- /* --------------------------------------------------------------------------
- * Type check bodies of bindings:
- * ------------------------------------------------------------------------*/
-
- static Void local typeBind(b) /* Type check binding */
- Cell b; {
- if (isVar(fst(b))) { /* function binding */
- Cell ass = findTopBinding(fst(b));
- Int beta;
-
- if (isNull(ass) || !isInt(snd(ass)))
- internal("typeBind");
-
- beta = intOf(snd(ass));
- map2Proc(typeDefAlt,beta,fst(b),snd(snd(b)));
- }
- else { /* pattern binding */
- static String lhsPat = "lhs pattern";
- static String rhs = "right hand side";
- Int beta = newTyvars(1);
- Pair pb = snd(snd(b));
- Int l = rhsLine(snd(pb));
-
- check(l,fst(pb),NIL,lhsPat,var,beta);
- snd(pb) = typeRhs(snd(pb));
- shouldBe(l,rhsExpr(snd(pb)),NIL,rhs,var,beta);
- }
- }
-
- static Void local typeDefAlt(beta,v,a) /* type check alt in func. binding */
- Int beta;
- Cell v;
- Pair a; {
- static String valDef = "function binding";
- Int l = rhsLine(snd(a));
- typeAlt(a);
- shouldBe(l,v,NIL,valDef,var,beta);
- }
-
- static Cell local typeRhs(e) /* check type of rhs of definition */
- Cell e; {
- switch (whatIs(e)) {
- case GUARDED : { Int beta = newTyvars(1);
- map1Proc(guardedType,beta,snd(e));
- tyvarType(beta);
- }
- break;
-
- case LETREC : enterBindings();
- mapProc(typeBindings,fst(snd(e)));
- snd(snd(e)) = typeRhs(snd(snd(e)));
- leaveBindings();
- break;
-
- default : snd(e) = typeExpr(intOf(fst(e)),snd(e));
- break;
- }
- return e;
- }
-
- static Void local guardedType(beta,gded)/* check type of guard (li,(gd,ex))*/
- Int beta; /* should have gd :: Bool, */
- Cell gded; { /* ex :: (var,beta) */
- static String guarded = "guarded expression";
- static String guard = "guard";
- Int line = intOf(fst(gded));
-
- gded = snd(gded);
- check(line,fst(gded),NIL,guard,typeBool,0);
- check(line,snd(gded),NIL,guarded,var,beta);
- }
-
- Cell rhsExpr(rhs) /* find first expression on a rhs */
- Cell rhs; {
-
- STACK_CHECK; /* KH */
-
- switch (whatIs(rhs)) {
- case GUARDED : return snd(snd(hd(snd(rhs))));
- case LETREC : return rhsExpr(snd(snd(rhs)));
- default : return snd(rhs);
- }
- }
-
- Int rhsLine(rhs) /* find line number associated with */
- Cell rhs; { /* a right hand side */
-
-