Unify.cxx

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright (C) 2008, Johns Hopkins University.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or
00007  * without modification, are permitted provided that the following
00008  * conditions are met:
00009  *
00010  *   - Redistributions of source code must contain the above 
00011  *     copyright notice, this list of conditions, and the following
00012  *     disclaimer. 
00013  *
00014  *   - Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions, and the following
00016  *     disclaimer in the documentation and/or other materials 
00017  *     provided with the distribution.
00018  *
00019  *   - Neither the names of the copyright holders nor the names of any
00020  *     of any contributors may be used to endorse or promote products
00021  *     derived from this software without specific prior written
00022  *     permission. 
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  **************************************************************************/
00037 
00038 #include <assert.h>
00039 #include <stdint.h>
00040 #include <stdlib.h>
00041 #include <dirent.h>
00042 #include <fstream>
00043 #include <iostream>
00044 #include <sstream>
00045 #include <string>
00046 #include <libsherpa/UExcept.hxx>
00047 
00048 #include "Options.hxx"
00049 #include "UocInfo.hxx"
00050 #include "AST.hxx"
00051 #include "Type.hxx"
00052 #include "TypeInfer.hxx"
00053 #include "TypeScheme.hxx"
00054 #include "TypeMut.hxx"
00055 #include "Typeclass.hxx"
00056 #include "inter-pass.hxx"
00057 #include "Unify.hxx"
00058 #include "WorkList.hxx"
00059 #include "Unify.hxx"
00060 
00061 using namespace boost;
00062 using namespace sherpa;
00063 
00064 static bool
00065 typeError(std::ostream& errStream, const LexLoc &errLoc,
00066           shared_ptr<Type> t1, shared_ptr<Type> t2)
00067 {
00068   errStream << errLoc << ": Type Error. "
00069             << "Expected " << t1->asString(GC_NULL) 
00070             << ", Obtained " << t2->asString(GC_NULL)
00071             << std::endl;
00072   
00073     if (errStream == std::cerr)
00074       errStream << "Real Error!" << std::endl;
00075   
00076   // MUST always return false.
00077   return false;
00078 }
00079 
00080 // Get an instance of a primary type defined in the Prelude.
00081 bool
00082 unifyPrim(std::ostream& errStream,
00083           shared_ptr<Trail> trail, const LexLoc &errLoc,
00084           shared_ptr<Type> tau, const std::string ptype) 
00085 {
00086   bool errFree = true;
00087 
00088   shared_ptr<Type> primType = Type::make(Type::LookupTypeTag(ptype));
00089   CHKERR(errFree, unify(errStream, trail, errLoc, primType, tau, UFLG_NO_FLAGS));
00090   return errFree;
00091 }
00092 
00093 static bool
00094 Unify(std::ostream& errStream,
00095       shared_ptr<Trail> trail, 
00096       const LexLoc &errLoc,
00097       shared_ptr<Type> ft, shared_ptr<Type> st, 
00098       UnifyFlags uflags);
00099 
00100 // Handle unification of struct/union decl+decl or decl+def
00101 static bool 
00102 UnifyDecl(std::ostream& errStream,
00103           shared_ptr<Trail> trail,
00104           const LexLoc &errLoc,
00105           shared_ptr<Type> t1, shared_ptr<Type> t2,
00106           UnifyFlags uflags) 
00107 {
00108   bool errFree = true;
00109 
00110   DEBUG(UNIFY) std::cout << "UnifyDecl " 
00111                         << t1->asString(Options::debugTvP) 
00112                         << " ==? " 
00113                         << t2->asString(Options::debugTvP)
00114                         << std::endl;
00115 
00116   assert(t1->defAst == t2->defAst);
00117   assert(t1->typeTag != ty_uconv || t1->typeTag != ty_uconr);
00118   assert(t1->typeTag != ty_uvalv || t1->typeTag != ty_uvalr);
00119 
00120   if (t1->typeArgs.size() != t2->typeArgs.size())
00121     return typeError(errStream, errLoc, t1, t2);
00122     
00123   for (size_t i=0; i<t1->typeArgs.size(); i++)
00124     CHKERR(errFree, Unify(errStream, trail, errLoc, t1->TypeArg(i), 
00125                           t2->TypeArg(i), uflags)); 
00126     
00127   return errFree;
00128 }
00129     
00130 
00131 static bool 
00132 UnifyStructUnion(std::ostream& errStream,
00133                  shared_ptr<Trail> trail,
00134                  const LexLoc &errLoc,
00135                  shared_ptr<Type> t1, shared_ptr<Type> t2,
00136                  UnifyFlags uflags) 
00137 {
00138   bool errFree = true;
00139 
00140   DEBUG(UNIFY) std::cout << "UnifyStructUnion " 
00141                         << t1->asString(Options::debugTvP) 
00142                         << " ==? "
00143                         << t2->asString(Options::debugTvP)
00144                         << std::endl;
00145 
00146   if (t1->isULeg() || t2->isULeg()) {
00147     if (t1->myContainer != t2->myContainer)
00148       return typeError(errStream, errLoc, t1, t2);
00149   }
00150   else {
00151     if (t1->defAst != t2->defAst)
00152       return typeError(errStream, errLoc, t1, t2);
00153 
00154     if (t1->components.size() == 0 || t2->components.size() == 0) 
00155       return UnifyDecl(errStream, trail, errLoc, t1, t2, uflags);
00156   }
00157   
00158   size_t n = trail->snapshot();
00159   trail->link(t1, t2);  
00160   
00161   assert(t1->typeArgs.size() == t2->typeArgs.size());  
00162   for (size_t i=0; i<t1->typeArgs.size(); i++) 
00163     CHKERR(errFree, Unify(errStream, trail, errLoc, t1->TypeArg(i), 
00164                           t2->TypeArg(i), uflags));
00165   
00166   if (!errFree)
00167     trail->rollBack(n);
00168   
00169   return errFree;
00170 }
00171 
00172 #ifdef DEAD_CODE
00173 // Unification of a maybe type with a core type.
00174 static bool 
00175 UnifyMbCt(std::ostream& errStream, shared_ptr<Trail> trail,
00176           shared_ptr<Type> mb, shared_ptr<Type> ct)
00177 {
00178   mb = mb->getType();
00179   ct = ct->getType();
00180   shared_ptr<Type> var = mb->Var()->getType();
00181   shared_ptr<Type> core = mb->Core()->getType();
00182   
00183   trail->subst(var, ct);
00184   
00185   return true;
00186 }
00187 #endif
00188 
00189 // While unifying two fnArgs, it is better to report the entire
00190 // function type rather than the argument types (if we know the 
00191 // full function type).
00192 // Therefore, this function is called from the Unifier
00193 // from both ty_fn case (in which case the errt1 and errt2
00194 // types are the full function types) and the
00195 // ty_fnarg case (in which case errt1 = t1 and errt2=t2)
00196 // In both cases, what is passed to us here as t1, t2 is the
00197 // ty_fnarg element.
00198 static bool 
00199 UnifyFnArgs(std::ostream& errStream, shared_ptr<Trail> trail,
00200             const LexLoc &errLoc,
00201              shared_ptr<Type> errt1, shared_ptr<Type> errt2,
00202             shared_ptr<Type> t1, shared_ptr<Type> t2,
00203             UnifyFlags uflags)
00204 {
00205   bool errFree = true;
00206   t1 = t1->getType();
00207   t2 = t2->getType();
00208   assert(t1->typeTag == ty_fnarg);
00209   assert(t2->typeTag == ty_fnarg);
00210   
00211   if (t1->components.size() != t2->components.size())
00212     return typeError(errStream, errLoc, errt1, errt2);
00213   
00214   for (size_t i=0; i< t1->components.size(); i++) {
00215     
00216     if ((t1->CompFlags(i) & COMP_MAYBE_BYREF) &&
00217         ((t2->CompFlags(i) & COMP_MAYBE_BYREF) == 0)) {
00218       t1->CompFlags(i) &= ~COMP_MAYBE_BYREF;
00219       t1->CompFlags(i) |= t2->CompFlags(i) & COMP_BYREF;
00220     }
00221     else if ((t2->CompFlags(i) & COMP_MAYBE_BYREF) &&
00222              ((t1->CompFlags(i) & COMP_MAYBE_BYREF) == 0)) {
00223       t2->CompFlags(i) &= ~COMP_MAYBE_BYREF;
00224       t2->CompFlags(i) |= t1->CompFlags(i) & COMP_BYREF;
00225     }
00226     else if (t1->CompFlags(i) != t2->CompFlags(i)) {
00227       errFree = typeError(errStream, errLoc, errt1, errt2);
00228       break;
00229     }
00230     
00231     CHKERR(errFree, Unify(errStream, trail, errLoc,
00232                           t1->CompType(i), 
00233                           t2->CompType(i), uflags));
00234   }
00235 
00236   return errFree;
00237 }
00238 
00239 // Wrapper over the propagateMutability member function,
00240 // which includes printing error message.
00241 static bool
00242 PropagateMutability(std::ostream& errStream,
00243                     shared_ptr<Trail> trail, 
00244                     const LexLoc &errLoc,
00245                     shared_ptr<Type> t) 
00246 {
00247   bool errFree = true;
00248   CHKERR(errFree, t->propagateMutability(trail));
00249   if(!errFree)
00250     errStream << errLoc << ": Unsound Mutable type: "
00251               << t->asString()
00252               << std::endl;
00253   // else
00254   //     errStream << errLoc << ": Mutability propagation okay for: "
00255   //               << t->asString()
00256   //               << std::endl;
00257   return errFree;
00258 }
00259 
00260 static bool
00261 Unify(std::ostream& errStream,
00262       shared_ptr<Trail> trail, 
00263       const LexLoc &errLoc,
00264       shared_ptr<Type> ft, shared_ptr<Type> st, 
00265       UnifyFlags uflags) 
00266 {
00267   shared_ptr<Type> t1 = ft->getType();
00268   shared_ptr<Type> t2 = st->getType();
00269   bool errFree = true;
00270 
00271   DEBUG(UNIFY) std::cerr << "Unifier: " 
00272                         << ft->asString(Options::debugTvP)
00273                         << " ==? " 
00274                         << st->asString(Options::debugTvP)
00275                         << std::endl;  
00276   
00277   if (t1->uniqueID == t2->uniqueID)
00278     return true;
00279 
00280   bool unifyingSameType = (t1->typeTag == t2->typeTag);
00281 
00282   switch(unifyingSameType) {
00283   case false:
00284     {
00285       if (t1->isUType(false) && t2->isUType(false) && 
00286           t1->isRefType() == t2->isRefType()) {
00287         CHKERR(errFree, UnifyStructUnion(errStream, trail, errLoc, 
00288                                          t1, t2, uflags));
00289         break;
00290       }
00291     
00292       if (uflags & UFLG_UNIFY_STRICT) {
00293         errFree = typeError(errStream, errLoc, t1, t2);
00294         break;
00295       }
00296       
00297       /* 1. Handle the case of Type Variables unifying with 
00298          another type
00299          2. If no such unification is possible, handle the case of
00300          a mbFull unifying with a mbTop or other non-maybe type
00301          3. If no such unification is possible, handle the case of 
00302          a mbTop unifying with a non-maybe type.      */
00303       
00304       if(t1->isTvar() || t2->isTvar()) {
00305         shared_ptr<Type> var = t1->isTvar() ? t1 : t2;
00306         shared_ptr<Type> other = t1->isTvar() ? t2 : t1;
00307 
00308         // The current unification case is 'a = t. 
00309         // If 'a is a rigid variable, we just immediately return an
00310         // error, since unification through other cases will be less
00311         // precise (that is, if t is a maybe type, we will get a type
00312         // whole variability wrt mutability is lost.
00313 
00314 
00315         if(!var->isUnifiableVar()) { // i.e. if it is rigid
00316           errStream << errLoc << " Rigid variable "
00317                     << var->asString() << " cannot be unified with "
00318                     << other->asString() << std::endl;
00319           errFree = false;
00320 
00321           if (errStream == std::cerr)
00322             errStream << "Real Error!" << std::endl;
00323         
00324 
00325           break;
00326         }
00327 
00328         // Now, we check to make sure that substitution of t for 'a
00329         // does not lead to cyclic substitution.
00330         // If 'a does not occur in t, we can substitute t for 'a and
00331         // declare victory. 
00332         // 
00333         // However, if 'a is bound in t, we cannot immediately declare
00334         // an error, but must try other options. For example, this case
00335         // arises in the solver and generalizer where a type is unified
00336         // with its (deeply) most immutable version.
00337         //
00338         // One of the possibilities we can end up here is 'a = 'b|'a,
00339         // where the intension really is to ensure that the mutability
00340         // should be fixed to the immutable version. This case is
00341         // handled below in the fall-through.
00342 
00343         if(!other->boundInType(var)) { // easy case
00344           trail->subst(var, other);
00345           break;
00346         }
00347         // Otherwise, try other options ...
00348       }
00349 
00350       // Note that if there was a possibility of substitution yielding
00351       // a cycle, either t1 or t2 could be a type variable here.
00352 
00353       if (t1->isMbFull() || t2->isMbFull()) {
00354         shared_ptr<Type> mb = t1->isMbFull() ? t1 : t2;
00355         shared_ptr<Type> other = t1->isMbFull() ? t2 : t1;
00356       
00357         if(!mb->isUnifiableVar()) { // i.e. it is rigid
00358           errStream << errLoc << "Rigid type "
00359                     << mb->asString() << " cannot be unified with "
00360                     << other->asString() << std::endl;
00361           errFree = false;
00362           break;
00363         }
00364 
00365         // Handle the special case: U('s|'b == M'a): Under the normal
00366         // unification rules, this will result in the type 's|'b = M'a
00367         // = M'a|'a, but what we want is 's|'b = M'a = (M'c)|'b
00368         //
00369         // This kind of unification constraint can only arise out of
00370         // explicit qualification, and must therefore be handled
00371         // specially (theory does not mention it). We cannot interpret
00372         // all M'a types as M'a|'b, since such qualifications might be
00373         // within composite type definitions.
00374         //
00375         // Shap needs an illustrating use case.
00376         //
00377         // Ex. We have a parameter wanting type 'b. It's internal type
00378         // is therefore 's|'b. We end up unifying it with (mutable e), 
00379         //
00380         // e infers to (MBF 'e), then
00381         // (mutable 'a) ~ (MBF 'e) -> (mutable 'e)
00382         //
00383         // What is going on here is that an explicit mutable wrapper
00384         // can only arise out of annotation.
00385 
00386         if(t2->isMutable() && t2->Base()->isTvar()) {
00387           CHKERR(errFree, Unify(errStream, trail, errLoc, mb->Var(),
00388                                 Type::make(ty_mutable, newTvar()), uflags));
00389         
00390           trail->link(other, mb);
00391         }
00392         else {
00393           CHKERR(errFree, Unify(errStream, trail, errLoc, 
00394                                 mb->minMutConstless(), 
00395                                 other->minMutConstless(), uflags));
00396         
00397           CHKERR(errFree, Unify(errStream, trail, errLoc, 
00398                                 mb->Var(), other, uflags));
00399         }
00400       
00401       
00402         if(errFree && (other->isMutable() || mb->Var()->isMutable()))
00403           CHKERR(errFree, PropagateMutability(errStream, trail, 
00404                                               errLoc, mb));
00405       
00406         break;
00407       }
00408 
00409       if (t1->isMbTop() || t2->isMbTop()) {
00410         shared_ptr<Type> mb = t1->isMbTop() ? t1 : t2;
00411         shared_ptr<Type> other = t1->isMbTop() ? t2 : t1;
00412       
00413         if(!mb->isUnifiableVar()) {
00414           errStream << errLoc << "Rigid type "
00415                     << mb->asString() << " cannot be unified with "
00416                     << other->asString() << std::endl;
00417           errFree = false;
00418           break;
00419         }
00420       
00421         CHKERR(errFree, Unify(errStream, trail, errLoc, 
00422                               mb->minimizeTopMutability(), 
00423                               other->minimizeTopMutability(), uflags));
00424       
00425         CHKERR(errFree, Unify(errStream, trail, errLoc, 
00426                               mb->Var(), other, uflags));
00427         break;
00428       }
00429 
00430       /* Certain types have multiple equivalent representations. 
00431          For example,
00432          1) (array (mutable int32)) == (mutable (array (mutable int32)))
00433          2) An unboxed structure is mutable as a whole if all of its
00434          components are mutable.  
00435        
00436          Therefore, (array T) must potentially unify with 
00437          (mutable T) and (mutable 'a)|t.  The following rule
00438          checks to see if such a match is possible */
00439     
00440       if(t1->isMutType() || t2->isMutType()) {
00441         shared_ptr<Type> mut = t1->isMutType() ? t1 : t2;
00442         shared_ptr<Type> other = t1->isMutType() ? t2 : t1;
00443       
00444         assert(!other->isMutType() &&  // Otherwise, it would be 
00445                !other->isMaybe());     // handled already.  
00446       
00447         if(other->typeTag == ty_array || other->typeTag == ty_structv) {
00448           CHKERR(errFree, Unify(errStream, trail, errLoc, 
00449                                 mut, Mutable(other), uflags));
00450           break;
00451         }
00452       }
00453 
00454       /* Const equivalent representation handling
00455          For example: (const (bool, bool)) == (bool, bool) */
00456 
00457       if(t1->isConst() || t2->isConst()) {
00458         shared_ptr<Type> constType = t1->isConst() ? t1 : t2;
00459         shared_ptr<Type> other = t1->isConst() ? t2 : t1;
00460 
00461         if(other->isEffectivelyConst()) {
00462           CHKERR(errFree,
00463                  Unify(errStream, trail, errLoc, 
00464                        constType->Base()->minMutConstless(), 
00465                        other->minMutConstless(), uflags));
00466           break;
00467         }
00468       }
00469     
00470       errFree = typeError(errStream, errLoc, t1, t2);
00471       break;
00472     }    
00473   case true:
00474     {
00475       switch(t1->typeTag) {
00476       case ty_unit:
00477       case ty_bool:
00478       case ty_char:
00479       case ty_string:
00480       case ty_int8:
00481       case ty_int16:
00482       case ty_int32:
00483       case ty_int64:
00484       case ty_uint8:
00485       case ty_uint16:
00486       case ty_uint32:
00487       case ty_uint64:
00488       case ty_word:
00489       case ty_float:
00490       case ty_double:
00491       case ty_quad:
00492         break;
00493 
00494       case ty_tvar:
00495         {                
00496           if (uflags & UFLG_UNIFY_STRICT_TVAR) {
00497             errFree = typeError(errStream, errLoc, t1, t2);
00498             break;
00499           }
00500 
00501           if ((t1->flags & TY_RIGID) && (t2->flags & TY_RIGID) &&
00502               ((uflags & UFLG_UN_IGN_RIGIDITY) == 0)) {
00503             errFree = typeError(errStream, errLoc, t1, t2);
00504             break;
00505           }
00506 
00507           // One of the types is not rigid, or we are ignoring rigidity.
00508           if (t1->flags & TY_RIGID)
00509             trail->subst(t2, t1);
00510           else
00511             trail->subst(t1, t2);
00512         
00513           break;
00514         }
00515 
00516       case ty_dummy:
00517         {
00518           break;
00519         }
00520     
00521 #ifdef KEEP_BF
00522       case ty_bitfield:
00523         {        
00524           CHKERR(errFree, Unify(errStream, trail, errLoc,
00525                                 t1->CompType(0), 
00526                                 t2->CompType(0), uflags));
00527         
00528           if (!errFree)
00529             break;
00530         
00531           if (t1->Isize == t2->Isize)
00532             break;
00533 
00534           errStream << errLoc << ": "
00535                     << "Incompatibility in integer types "
00536                     << t1->asString() << " and " << t2->asString() 
00537                     << "." << std::endl;
00538 
00539           errFree = false;
00540           break;
00541         } 
00542 #endif     
00543 
00544       case ty_tyfn:
00545       case ty_fn:
00546       case ty_method:
00547         {
00548           shared_ptr<Type> t1Args = t1->Args();
00549           shared_ptr<Type> t2Args = t2->Args();
00550           CHKERR(errFree, UnifyFnArgs(errStream, trail, errLoc, 
00551                                       t1, t2, t1Args, t2Args, uflags));
00552       
00553           CHKERR(errFree, 
00554                  Unify(errStream, trail, errLoc, t1->Ret(), 
00555                        t2->Ret(), uflags));
00556           break;
00557         }
00558 
00559       case ty_fnarg:
00560         {
00561           CHKERR(errFree, UnifyFnArgs(errStream, trail, errLoc, 
00562                                       t1, t2, t1, t2, uflags));
00563           break;
00564         }
00565 
00566       case ty_structv:
00567       case ty_structr:
00568       case ty_unionv:
00569       case ty_unionr:
00570       case ty_uconr:
00571       case ty_uconv:
00572       case ty_uvalr:
00573       case ty_uvalv:
00574         {
00575           CHKERR(errFree,
00576                  UnifyStructUnion(errStream, trail, errLoc, t1, t2, uflags));
00577           break;
00578         }
00579 
00580       case ty_letGather:
00581         {      
00582           if (t1->components.size() != t2->components.size()) {
00583             errFree = typeError(errStream, errLoc, t1, t2);
00584             break;
00585           }
00586 
00587           for (size_t i=0; i<t1->components.size(); i++) 
00588             CHKERR(errFree, 
00589                    Unify(errStream, trail, errLoc, t1->CompType(i), 
00590                          t2->CompType(i), uflags));
00591         
00592           break;
00593         }
00594       
00595       case ty_array:
00596         {
00597           CHKERR(errFree, 
00598                  Unify(errStream, trail, errLoc, t1->Base(), 
00599                        t2->Base(), uflags));
00600         
00601           // FIX: Need to link arrLen structures here, since 
00602           // the two length might be 0, indicating later resolvability.
00603           if (t1->arrLen->len == t2->arrLen->len)
00604             break;
00605       
00606           // Array lengths did not Unify
00607           if (t1->arrLen->len == 0) {
00608             t1->arrLen->len = t2->arrLen->len;
00609             break;
00610           }
00611           else if (t2->arrLen->len == 0) {
00612             t2->arrLen->len = t1->arrLen->len;
00613             break;
00614           }
00615           else {
00616             errStream << errLoc 
00617                       << ": Array lengths do not match. "
00618                       << t1->arrLen->len
00619                       << " vs " 
00620                       << t2->arrLen->len
00621                       << std::endl;
00622             errFree = false;
00623           }
00624       
00625           break;
00626         }
00627       
00628         // We are doing same-type unification here. Treat ty_wkvector
00629         // like vector for the moment, since we don't have any
00630         // knowledge of a length yet.
00631       case ty_vector:
00632         {
00633           CHKERR(errFree, 
00634                  Unify(errStream, trail, errLoc, t1->Base(), 
00635                        t2->Base(), uflags));
00636           break;
00637         }
00638     
00639       case ty_mbTop:
00640         {
00641           CHKERR(errFree,
00642                  Unify(errStream, trail, errLoc, 
00643                        t1->Core()->minimizeTopMutability(), 
00644                        t2->Core()->minimizeTopMutability(), 
00645                        uflags));
00646       
00647           if (!errFree)
00648             break;
00649       
00650           CHKERR(errFree, Unify(errStream, trail, errLoc, 
00651                                 t1->Var(), t2->Var(), uflags));
00652           break;
00653         }
00654     
00655       case ty_mbFull:
00656         {
00657           CHKERR(errFree,
00658                  Unify(errStream, trail, errLoc, 
00659                        t1->Core()->minMutConstless(), 
00660                        t2->Core()->minMutConstless(), 
00661                        uflags));
00662       
00663           if (!errFree)
00664             break;
00665       
00666           shared_ptr<Type> var1 = t1->Var()->getType();
00667           shared_ptr<Type> var2 = t2->Var()->getType();
00668       
00669           if(var1->isMutable() && var2->isMutable())
00670             CHKERR(errFree, Unify(errStream, trail, errLoc, 
00671                                   var1->Base(), var2->Base(), uflags));
00672           else
00673             CHKERR(errFree, Unify(errStream, trail, errLoc, 
00674                                   var1, var2, uflags));
00675       
00676           if(errFree && t1->Var()->isMutable())
00677             CHKERR(errFree, PropagateMutability(errStream, trail, 
00678                                                 errLoc, t1));
00679       
00680           break;
00681         }
00682 
00683       case ty_mutable:
00684         {
00685           CHKERR(errFree,
00686                  Unify(errStream, trail, errLoc, t1->Base(), 
00687                        t2->Base(), uflags));
00688 
00689           if(!errFree)
00690             break;
00691       
00692           CHKERR(errFree, PropagateMutability(errStream, trail, 
00693                                               errLoc, t1));
00694           break;
00695         }
00696 
00697       case ty_const:
00698         {
00699           CHKERR(errFree,
00700                  Unify(errStream, trail, errLoc, 
00701                        t1->Base()->minMutConstless(), 
00702                        t2->Base()->minMutConstless(), uflags));
00703           break;
00704         }
00705     
00706       case ty_ref:
00707       case ty_byref:
00708       case ty_array_ref:
00709         {
00710           CHKERR(errFree,
00711                  Unify(errStream, trail, errLoc, t1->Base(), 
00712                        t2->Base(), uflags));
00713           break;
00714         }
00715 
00716       case ty_exn:
00717         {
00718           // All exceptions belong to the same sum type.        
00719           break;
00720         }
00721 
00722       case ty_typeclass:
00723         {
00724           if (t1->defAst != t2->defAst) {
00725             errFree = typeError(errStream, errLoc, t1, t2);
00726             break;
00727           }
00728         
00729           if (t1->typeArgs.size() != t2->typeArgs.size()) {
00730             errFree = typeError(errStream, errLoc, t1, t2);
00731             break;
00732           }
00733         
00734           for (size_t i = 0; i < t1->typeArgs.size(); i++) {
00735           
00736             CHKERR(errFree, Unify(errStream, trail, errLoc, 
00737                                   t1->TypeArg(i), t2->TypeArg(i),
00738                                   uflags));
00739           }
00740         
00741           break;
00742         }
00743       
00744         // The following cases are filled in so that strictlyEquals()
00745         // function works correctly.
00746       case ty_pcst:
00747         {
00748           assert(t1->components.size() == t2->components.size());
00749           for (size_t i=0; i < t1->components.size(); i++) 
00750             CHKERR(errFree,
00751                    Unify(errStream, trail, errLoc, t1->CompType(i), 
00752                          t2->CompType(i), uflags));
00753           break;
00754         }
00755 
00756       case ty_field:
00757         {
00758           if(t1->litValue.s != t2->litValue.s)
00759             errFree = typeError(errStream, errLoc, t1, t2);
00760           break;
00761         }
00762       
00763       case ty_kvar:
00764       case ty_kfix:
00765         {
00766           // This check will never unify, since the following check has
00767           // already failed at the start of the unification algorithm.
00768           if (t1->uniqueID != t2->uniqueID)
00769             errFree = typeError(errStream, errLoc, t1, t2);
00770           break;
00771         }
00772       }
00773     }
00774   }
00775   
00776   DEBUG(UNF_RES) errStream << "\t Result: " 
00777                           << ft->asString(Options::debugTvP)
00778                           << " == " 
00779                           << st->asString(Options::debugTvP)
00780                           << "{" << (errFree?"OK":"ERR") << "}"
00781                           << std::endl;  
00782   
00783   return errFree;
00784 }
00785 
00786 bool
00787 acyclic(std::ostream& errStream,
00788         const LexLoc &errLoc,
00789         shared_ptr<Type> typ, 
00790         WorkList<shared_ptr<Type> >& worklist, // Types currently visiting
00791          DoneList<shared_ptr<Type> >& donelist, // Types Known to be OK 
00792         bool inref=false)
00793 {
00794   assert(typ);
00795 
00796   shared_ptr<Type> t = typ->getType();
00797   bool errFree = true;
00798 
00799   //std::cout << "Acyclic: Processing: " << t->asString(Options::debugTvP)
00800   //            << std::endl;
00801   
00802   if (donelist.contains(t))
00803     return true;
00804   
00805   if (worklist.contains(t)) {
00806     
00807     if (t->typeTag == ty_structr ||
00808        t->typeTag == ty_unionr || 
00809        t->typeTag == ty_uconr ||
00810        t->typeTag == ty_uvalr)
00811       return true;
00812     
00813     if (inref)
00814       return true;
00815     
00816     std::cerr << errLoc << ": " 
00817               << "Cyclic Type Definitions among the following " 
00818               << worklist.size() << " types:" << std::endl;
00819     
00820     // By now, we know that the current type is already 
00821     // in the worklist
00822     std::cerr << t->asString(GC_NULL, PO_NO_TRAVERSE) 
00823                   << std::endl;
00824     for (WorkList<shared_ptr<Type> >::iterator itr = worklist.begin();
00825         itr != worklist.end(); ++itr)
00826       std::cerr << (*itr)->asString(GC_NULL, PO_NO_TRAVERSE)
00827                 << std::endl;
00828     fatal();
00829     return false;
00830   }
00831         
00832   assert(!worklist.contains(t));
00833   worklist.insert(t);
00834 
00835   for (size_t i=0; i < t->components.size(); i++)
00836     CHKERR(errFree, acyclic(errStream, errLoc, t->CompType(i),
00837                             worklist, donelist,
00838                             (inref || t->typeTag == ty_ref)));
00839 
00840 //   for (size_t i=0; i < t->typeArgs.size(); i++) {
00841 //     CHKERR(errFree, acyclic(errStream, errLoc, t->TypeArg(i),  
00842 //                             worklist, donelist,
00843 //                             (inref || t->typeTag == ty_ref)));
00844 //   }
00845   
00846   worklist.erase(t);   
00847   if (errFree)
00848     donelist.insert(t);
00849   
00850   //std::cout << "--"
00851   //          << std::endl;
00852   
00853   return errFree;                
00854 }
00855 
00856 bool
00857 unify(std::ostream& errStream,
00858       shared_ptr<Trail> trail,
00859       const LexLoc &errLoc,
00860       shared_ptr<Type> ft, shared_ptr<Type> st, 
00861       UnifyFlags uflags) 
00862 {
00863   bool errFree = true;
00864 
00865   CHKERR(errFree, Unify(errStream, trail, errLoc, ft, st, uflags));
00866   
00867   WorkList<shared_ptr<Type> > worklist;
00868   DoneList<shared_ptr<Type> > donelist;
00869   CHKERR(errFree, acyclic(errStream, errLoc, ft, worklist, donelist));
00870   if(errFree)
00871     ft->normalize(trail);
00872   
00873   return errFree;
00874 }
00875 

Generated on Sat Feb 4 23:59:29 2012 for BitC Compiler by  doxygen 1.4.7