home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-05-11 | 14.5 KB | 240 lines | [TEXT/MPS ] |
- /* --------------------------------------------------------------------------
- * subst.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
- *
- * Part of type checker dealing with operations on current substitution.
- * ------------------------------------------------------------------------*/
-
- #if MPW
- #pragma segment Subst
- #endif
-
- static Void local emptySubstitution() { /* clear current substitution */
- numTyvars = 0;
- nextGeneric = 0;
- genericVars = NIL;
- typeIs = NIL;
- predsAre = NIL;
- }
-
- static Int local newTyvars(n) /* allocate new type variables */
- Int n; { /* all of kind STAR */
- Int beta = numTyvars;
-
- if (numTyvars+n>num_tyvars) {
- ERROR(0) "Too many type variables (%d) in type checker", (Int)(numTyvars + n)
- EEND;
- }
- for (numTyvars+=n; n>0; n--) {
- tyvars[numTyvars-n].offs = UNUSED_GENERIC;
- tyvars[numTyvars-n].bound = NIL;
- tyvars[numTyvars-n].kind = STAR;
- #ifdef DEBUG_TYPES
- printf("new type variable: _%d ::: ",numTyvars-n);
- printKind(stdout,tyvars[numTyvars-n].kind);
- putchar('\n');
- #endif
- }
- return beta;
- }
-
- static Int local newKindedVars(k) /* allocate new variables with */
- Kind k; { /* specified kinds */
- Int beta = numTyvars; /* if k = k0 -> k1 -> ... -> kn */
- for (; isAp(k); k=snd(k)) { /* then allocate n vars with kinds */
- if (numTyvars+1>num_tyvars) { /* k0, k1, ..., k(n-1) */
- ERROR(0) "Too many type variables in type checker (%d+1)",
- num_tyvars
- EEND;
- }
- tyvars[numTyvars].offs = UNUSED_GENERIC;
- tyvars[numTyvars].bound = NIL;
- tyvars[numTyvars].kind = fst(k);
- #ifdef DEBUG_TYPES
- printf("new type variable: _%d ::: ",numTyvars);
- printKind(stdout,tyvars[numTyvars].kind);
- putchar('\n');
- #endif
- numTyvars++;
- }
- return beta;
- }
-
- #define freeTypeVars(beta) numTyvars=beta
-
- #define deRef(tyv,t,o) while ((tyv=getTypeVar(t,o)) && tyv->bound) { \
- t = tyv->bound; \
- o = tyv->offs; \
- }
-
- static Tyvar *local getTypeVar(t,o) /* get number of type variable */
- Type t; /* represented by (t,o) [if any]. */
- Int o; {
- switch (whatIs(t)) {
- case INTCELL : return tyvar(intOf(t));
- case OFFSET : return tyvar(o+offsetOf(t));
- }
- return ((Tyvar *)0);
- }
-
- static Void local tyvarType(vn) /* load type held in type variable */
- Int vn; { /* vn into (typeIs,typeOff) */
- Tyvar *tyv;
-
- while ((tyv=tyvar(vn))->bound)
- switch(whatIs(tyv->bound)) {
- case INTCELL : vn = intOf(tyv->bound);
- break;
-
- case OFFSET : vn = offsetOf(tyv->bound)+(tyv->offs);
- break;
-
- default : typeIs = tyv->bound;
- typeOff = tyv->offs;
- return;
- }
- typeIs = var;
- typeOff = vn;
- }
-
- static Void local bindTv(vn,t,o) /* set type variable vn to (t,o) */
- Int vn;
- Type t;
- Int o; {
- Tyvar *tyv = ty
- else
- if (tyv2) {
- Cell h1 = getDerefHead(t1,o1); /* t2 variable, t1 not */
- if (isSynonym(h1) && argCount==tycon(h1).arity) {
- expandSynonym(h1,&t1,&o1);
- deRef(tyv1,t1,o1);
- goto un;
- }
- return varToTypeBind(tyv2,t1,o1);
- }
- else { /* t1, t2 not vars */
- Type h1 = getDerefHead(t1,o1);
- Int a1 = argCount;
- Type h2 = getDerefHead(t2,o2);
- Int a2 = argCount;
-
- if (isOffset(h1) || isInt(h1)) h1=NIL; /* represent var by NIL*/
- if (isOffset(h2) || isInt(h2)) h2=NIL;
-
- if (nonNull(h1) && h1==h2) {/* Assuming well-formed types, both*/
- if (a1!=a2) /* t1, t2 must have same no of args*/
- internal("unify");
- while (isAp(t1)) {
- if (!unify(arg(t1),o1,arg(t2),o2))
- return FALSE;
- t1 = fun(t1);
- deRef(tyv1,t1,o1);
- t2 = fun(t2);
- deRef(tyv2,t2,o2);
- }
- return TRUE;
- }
-
- /* Types do not match -- look for type synonyms to expand */
-
- if (isSynonym(h1) && a1==tycon(h1).arity) {
- expandSynonym(h1,&t1,&o1);
- deRef(tyv1,t1,o1);
- goto un;
- }
- if (isSynonym(h2) && a2==tycon(h2).arity) {
- expandSynonym(h2,&t2,&o2);
- deRef(tyv2,t2,o2);
- goto un;
- }
-
- if ((isNull(h1) && a1<=a2) || /* last attempt -- maybe */
- (isNull(h2) && a2<=a1)) { /* one head is a variable? */
- for (;;) {
- deRef(tyv1,t1,o1);
- deRef(tyv2,t2,o2);
-
- if (tyv1) /* unify heads! */
- if (tyv2)
- return varToVarBind(tyv1,tyv2);
- else
- return varToTypeBind(tyv1,t2,o2);
- else if (tyv2)
- return varToTypeBind(tyv2,t1,o1);
-
- /* at this point, neither t1 nor t2 is a variable. In */
- /* addition, they must both be APs unless one of the */
- /* head variables has been bound during unification of */
- /* the arguments. */
-
- if (!isAp(t1) || !isAp(t2)) { /* might not be APs*/
- unifyFails = 0;
- return t1==t2;
- }
- if (!unify(arg(t1),o1,arg(t2),o2)) /* o/w must be APs */
- return FALSE;
- t1 = fun(t1);
- t2 = fun(t2);
- }
- }
- }
- unifyFails = 0;
- return FALSE;
- }
-
- static Bool local sameType(t1,o1,t2,o2)/* Compare types without binding */
- Type t1,t2;
- Int o1,o2; {
- Bool result;
- matchMode = TRUE;
- result = unify(t1,o1,t2,o2);
- matchMode = FALSE;
- return result;
- }
-
- Bool typeMatches(type,mt) /* test if type matches monotype mt*/
- Type type, mt; {
- Bool result;
- if (isPolyType(type) || whatIs(type)==QUAL)
- return FALSE;
- typeChecker(RESET);
- matchMode = TRUE;
- result = unify(mt,0,type,0);
- matchMode = FALSE;
- typeChecker(RESET);
- return result;
- }
-
- /* --------------------------------------------------------------------------
- * Unify kind expressions:
- * ------------------------------------------------------------------------*/
-
- static Bool local kunify(k1,o1,k2,o2) /* Unify kind expr (k1,o1) with */
- Kind k1,k2; /* (k2,o2) */
- Int o1,o2; {
- Tyvar *kyv1, *kyv2;
-
- deRef(kyv1,k1,o1);
- deRef(kyv2,k2,o2);
-
- if (kyv1)
- if (kyv2)
- return kvarToVarBind(kyv1,kyv2); /* k1, k2 variables */
- else
- return kvarToTypeBind(kyv1,k2,o2); /* k1 variable, k2 not */
- else
- if (kyv2)
- return kvarToTypeBind(kyv2,k1,o1); /* k2 variable, k1 not */
- else
- if (k1==STAR && k2==STAR) /* k1, k2 not vars */
- return TRUE;
- else if (isAp(k1) && isAp(k2))
- return kunify(fst(k1),o1,fst(k2),o2) &&
- kunify(snd(k1),o1,snd(k2),o2);
- unifyFails = 0;
- return FALSE;
- }
-
- /*-------------------------------------------------------------------------*/
-