TypePoly.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 <string>
00045 #include <sstream>
00046 
00047 #include <libsherpa/UExcept.hxx>
00048 
00049 #include "Options.hxx"
00050 #include "UocInfo.hxx"
00051 #include "AST.hxx"
00052 #include "Type.hxx"
00053 #include "TypeInfer.hxx"
00054 #include "TypeScheme.hxx"
00055 #include "TypeMut.hxx"
00056 #include "Typeclass.hxx"
00057 #include "inter-pass.hxx"
00058 #include "Unify.hxx"
00059 
00060 using namespace boost;
00061 using namespace sherpa;
00062 using namespace std;
00063 
00064 bool isExpansive(std::ostream& errStream, 
00065                 shared_ptr<const TSEnvironment > gamma,
00066                 shared_ptr<const AST> ast);
00067 bool isExpansive(std::ostream& errStream, 
00068                  shared_ptr<const TSEnvironment > gamma,
00069                  shared_ptr<Type> typ);
00070 
00071 /**********************************************************
00072  **********************************************************
00073 
00074     FTV Handling: Support routines for Type generalization
00075                   and Specialization
00076 
00077  **********************************************************
00078  **********************************************************/
00079 
00080 
00081 bool
00082 Type::boundInType(shared_ptr<Type> tv)
00083 {
00084   shared_ptr<Type> t = getType();
00085   
00086   if (t == tv->getType())
00087     return true;
00088    
00089   if (t->mark & MARK_PREDICATE)
00090     return false;
00091   
00092   t->mark |= MARK_PREDICATE;
00093   bool bound = false;
00094   
00095   for (size_t i=0; (!bound) && (i < t->components.size()); i++) 
00096     bound = t->CompType(i)->boundInType(tv);
00097 
00098   // To consider cases like (define aNil nil)
00099   for (size_t i=0; (!bound) && (i < t->typeArgs.size()); i++) 
00100     bound = t->TypeArg(i)->boundInType(tv);
00101 
00102   // Deal with fnDeps if present
00103   for (TypeSet::iterator itr = t->fnDeps.begin();
00104       (!bound) && itr != t->fnDeps.end(); ++itr)
00105     bound = (*itr)->boundInType(tv);
00106   
00107   t->mark &= ~MARK_PREDICATE;
00108   return bound;
00109 }
00110 
00111 bool
00112 Type::boundInGamma(shared_ptr<const TSEnvironment > gamma)
00113 {
00114   shared_ptr<Type> tvar = getType();
00115   while (gamma) {
00116     for (TSEnvironment::const_iterator itr = gamma->begin();
00117         itr != gamma->end(); ++itr) {
00118       shared_ptr<TypeScheme> sigma = itr->second->val;
00119 
00120       for (TypeSet::iterator tv = sigma->ftvs.begin();
00121            tv != sigma->ftvs.end(); ++tv) {
00122         if ((*tv)->uniqueID == tvar->uniqueID)
00123           return true;
00124       }
00125       
00126       if (sigma->tau->boundInType(tvar))
00127         return true;
00128     }
00129     
00130     gamma = gamma->parent;
00131   }
00132   
00133   return false;
00134 }
00135 
00136 // Collect ALL ftvs regardless of gamma
00137 // This APPENDS TO the vector `tvs'. IT IS NOT NECESSARY THAT
00138 // `tvs' BE EMPTY TO START WITH. 
00139 void
00140 Type::collectAllftvs(TypeSet& tvs)
00141 {
00142   shared_ptr<Type> t = getType();
00143   
00144   if (t->mark & MARK_COLLECT_ALL_FTVS)
00145     return;
00146 
00147   t->mark |= MARK_COLLECT_ALL_FTVS;
00148   
00149   if (t->typeTag == ty_tvar) {
00150     tvs.insert(t);
00151   }      
00152   else {
00153     for (size_t i=0; i < t->components.size(); i++)
00154       t->CompType(i)->collectAllftvs(tvs);
00155 
00156     for (size_t i=0; i < t->typeArgs.size(); i++)
00157       t->TypeArg(i)->collectAllftvs(tvs);
00158 
00159     for (TypeSet::iterator itr = t->fnDeps.begin();
00160         itr != t->fnDeps.end(); ++itr)
00161       (*itr)->collectAllftvs(tvs);
00162   }
00163 
00164   t->mark &= ~MARK_COLLECT_ALL_FTVS;
00165 }
00166  
00167 // Collects ftvs wrt the basic type and TC predicates 
00168 void
00169 TypeScheme::collectAllFtvs()
00170 {
00171   tau->collectAllftvs(ftvs);  
00172   if (tcc) {
00173     for (TypeSet::iterator itr = tcc->begin();
00174         itr != tcc->end(); ++itr)
00175       (*itr)->collectAllftvs(ftvs);      
00176   }  
00177 }
00178 
00179 // Collect the Free Type Variables in a type
00180 // that are unbound in gamma
00181 void
00182 Type::collectftvsWrtGamma(TypeSet& tvs,
00183                           shared_ptr<const TSEnvironment > gamma)
00184 {   
00185   shared_ptr<Type> t = getType();
00186 
00187   if (t->mark & MARK_COLLECT_FTVS_WRT_GAMMA)
00188     return;
00189 
00190   t->mark |= MARK_COLLECT_FTVS_WRT_GAMMA;
00191 
00192   if (t->typeTag == ty_tvar) {
00193     assert(t->components.size() == 0);
00194     if (!t->boundInGamma(gamma))
00195       tvs.insert(t);
00196   }
00197   else {
00198     for (size_t i=0; i < t->components.size(); i++)      
00199       t->CompType(i)->collectftvsWrtGamma(tvs, gamma);
00200     
00201     for (size_t i=0; i < t->typeArgs.size(); i++)
00202       t->TypeArg(i)->collectftvsWrtGamma(tvs, gamma);
00203 
00204     for (TypeSet::iterator itr = t->fnDeps.begin();
00205         itr != t->fnDeps.end(); ++itr)
00206       (*itr)->collectftvsWrtGamma(tvs, gamma);
00207   }
00208 
00209   t->mark &= ~MARK_COLLECT_FTVS_WRT_GAMMA;
00210 }
00211  
00212 
00213 // Remove Free Type Variables that are indirectly influenced
00214 // by type variables that are bound in Gamma through
00215 // Functional Dependencies
00216 static void
00217 remftvsWrtFnDeps(TypeSet &ftvs,
00218                  TypeSet fnDeps,
00219                  shared_ptr<const TSEnvironment > gamma)
00220 {
00221   // closure wrt tvs in fnDeps influenced by Gamma.
00222   TypeSet closure;
00223 
00224   for (TypeSet::iterator itr = fnDeps.begin();
00225       itr != fnDeps.end(); ++itr) {
00226     shared_ptr<Type> fnDep = (*itr);
00227     TypeSet tvs;
00228     fnDep->collectAllftvs(tvs);
00229     for (TypeSet::iterator itr_j = tvs.begin();
00230         itr_j != tvs.end(); ++itr_j) {
00231       shared_ptr<Type> tv = (*itr_j);
00232       if (tv->boundInGamma(gamma))
00233         closure.insert(tv);
00234     }
00235   }
00236 
00237   TCConstraints::close(closure, fnDeps);
00238   
00239   TypeSet newFtvs;
00240   for (TypeSet::iterator itr = ftvs.begin(); itr != ftvs.end(); ++itr) {
00241     shared_ptr<Type> ftv = (*itr)->getType();
00242     if (closure.find(ftv) == closure.end())
00243       newFtvs.insert(ftv);
00244   }
00245 
00246   ftvs = newFtvs;
00247 }
00248 
00249 /**********************************************************
00250                      FTV Collection
00251  **********************************************************/
00252 // Collect the Free Type Variables in a type
00253 // that are unbound in gamma
00254 void
00255 TypeScheme::collectftvs(shared_ptr<const TSEnvironment > gamma)
00256 {
00257   tau->collectftvsWrtGamma(ftvs, gamma);  
00258   if (tcc) {    
00259     for (TypeSet::iterator itr = tcc->begin();
00260         itr != tcc->end(); ++itr) {
00261       shared_ptr<Typeclass> pred = (*itr);
00262       pred->collectftvsWrtGamma(ftvs, gamma);  
00263     }
00264  
00265     TypeSet allFnDeps;
00266     tcc->collectAllFnDeps(allFnDeps);
00267     remftvsWrtFnDeps(ftvs, allFnDeps, gamma);
00268   }
00269 }
00270 
00271 /**********************************************************
00272                   Type Scheme Imprevoment
00273  **********************************************************/
00274 
00275 // Remove Ftvs that will never be instantiable.
00276 bool
00277 TypeScheme::removeUnInstFtvs()
00278 {
00279   bool removed = false;
00280 
00281   for (TypeSet::iterator itr_c = ftvs.begin();
00282       itr_c != ftvs.end(); ++itr_c) {
00283     shared_ptr<Type> ftv = (*itr_c)->getType();
00284     if (tau->boundInType(ftv))
00285       ftv->flags |= TY_CLOS;
00286   }
00287 
00288   for (TypeSet::iterator itr = tcc->begin();
00289       itr != tcc->end(); ++itr) {
00290     shared_ptr<Constraint> ct = (*itr)->getType();
00291 
00292     bool mustAdd=false;
00293     for (TypeSet::iterator itr_c = ftvs.begin();
00294         itr_c != ftvs.end(); ++itr_c) {
00295       shared_ptr<Type> ftv = (*itr_c)->getType();
00296       if (ct->boundInType(ftv) && (ftv->flags & TY_CLOS)) {
00297         mustAdd = true;
00298         break;
00299       }
00300     }
00301 
00302     if (mustAdd) {
00303       for (TypeSet::iterator itr_c = ftvs.begin();
00304           itr_c != ftvs.end(); ++itr_c) {
00305         shared_ptr<Type> ftv = (*itr_c)->getType();
00306         
00307         if (ct->boundInType(ftv))
00308           ftv->flags |= TY_CLOS;
00309       }
00310     }
00311   }
00312 
00313   TypeSet newTvs;
00314   for (TypeSet::iterator itr_c = ftvs.begin();
00315       itr_c != ftvs.end(); ++itr_c) {
00316     shared_ptr<Type> ftv = (*itr_c)->getType();
00317     if (ftv->flags & TY_CLOS) {
00318       newTvs.insert(ftv);
00319       ftv->flags &= ~TY_CLOS;
00320     }
00321     else
00322       removed = true;
00323   }
00324   
00325   ftvs = newTvs;
00326   return removed;
00327 }
00328 
00329 // Remove *generalizable* Ftvs that appear only at copy-positions of
00330 // function types or Typeclass Predicates.
00331 bool
00332 TypeScheme::normalizeConstruction(shared_ptr<Trail> trail)
00333 {
00334   bool removed = false;
00335 
00336   for (TypeSet::iterator itr_c = ftvs.begin();
00337       itr_c != ftvs.end(); ++itr_c) {
00338     shared_ptr<Type> ftv = (*itr_c)->getType();
00339     ftv->flags |= TY_COERCE;
00340   }
00341   
00342   tau->markSignMbs(false);
00343   
00344   for (TypeSet::iterator itr = tcc->begin();
00345       itr != tcc->end(); ++itr) {
00346     shared_ptr<Constraint> ct = (*itr)->getType();
00347     ct->markSignMbs(true);
00348   }
00349 
00350   TypeSet newTvs;
00351   for (TypeSet::iterator itr_c = ftvs.begin();
00352       itr_c != ftvs.end(); ++itr_c) {
00353     shared_ptr<Type> ftv = (*itr_c)->getType();
00354     if ((ftv->flags & TY_COERCE) == 0)
00355       newTvs.insert(ftv);
00356     else
00357       removed = true;
00358   }
00359   ftvs = newTvs;
00360   
00361   // TY_COERCE flag is not cleared, but it does not matter, because
00362   // all of these types are substituted within the next adjMaybe call.
00363   tau->adjMaybe(trail, true, false, true);
00364   for (TypeSet::iterator itr = tcc->begin();
00365       itr != tcc->end(); ++itr) {
00366     shared_ptr<Constraint> ct = (*itr)->getType();
00367     ct->adjMaybe(trail, true, false, true);
00368   }
00369   
00370   return removed;
00371 }
00372 
00373 
00374 /**********************************************************
00375  **********************************************************
00376                 Type Generalization
00377 
00378  **********************************************************
00379  **********************************************************/
00380 
00381 
00382 /**********************************************************
00383                    THE Type Generalizer 
00384 
00385    The generalizer returns true if all free-type-variables could be
00386    completely generalized, false otherwise.
00387 
00388    Here is the Type generalization algorithm:
00389    Input is a type t and a set of constraints C, wrt to 
00390    the current let expression let(k) x = e in ...
00391 
00392    0) Normalize the type representation. For example, this eliminates
00393       unnecessary maybe types such as (mutable 'a)|bool and converts
00394       them to (mutable bool).
00395 
00396    1) Solve predicates: let (t', C') = SolvePredicates(C)
00397       The constraint set C' contains residual constraints. It cannot
00398       contain any constraints over concrete types.
00399       This step is not performed for instance generalizations.
00400 
00401    2) Add the polymorphic instantiation constraint *(k, t, t) to C
00402       if necessary.
00403       -- This step is not performed for instance generalizations.      
00404       -- The constraint is only added if !Mut(t) and !Immut(t)
00405 
00406    3) In case of top-level definitions, make a choice for all
00407       *-constraints: The type is made immutable upto the function
00408       boundary, and all 'ks are resolved to polymorphic.
00409       At this stage, re-solve all consrtainst.
00410 
00411    4) Check for value restriction: 
00412       exp = isExpansive(e) || isExpansive(t')
00413 
00414    5) If !exp, Determine the set of generalizable type variables:
00415       'a* = (FTVS(t') U FTVS(C')) \ FTVS(gamma)
00416       Otherwise, 'a* = {}
00417 
00418    6) Remove FTVs that are present purely only in constraints (no need
00419       for generalization)
00420          -- remove FTVs that only appear in a constraint that does not 
00421             contain an FTV that is transitively reachable from the 
00422             type t' (possibly through other constraints)
00423 
00424    7) Function type simplification: Remove *generalizable* FTVs that
00425       appear as maybe-type variables at copy-positions of function
00426       types, since these will be not result in any loss of
00427       generality. Coerce the type to its non-maybe form.
00428 
00429       If any variables were removed due to (6) or (7), 
00430       then re-solve all consrtainsts .
00431 
00432    8) If exp, and if generalizing at top-level, instantiate
00433       free variables to dummy types and issue warnings
00434 
00435    9) Migrate appropriate constraints to parent's TCC, if one exists
00436       let C'' = migrate(parent-sigma, C')
00437       --> Constraints purely over monomorphic type variables can be
00438           migrated to the containing scope.
00439 
00440    10) Check for ambiguity: This is a no-op.
00441 
00442     Finally,  The generalized type is forall 'a*, t' \ C''
00443 
00444  *********************************************************/
00445 
00446 enum GenSteps {
00447   gs_fixAll=0,
00448   gs_solve=1,
00449   gs_pcst=2,
00450   gs_fixTop=3,
00451   gs_valRes=4,
00452   gs_genFtvs=5,
00453   gs_ctrNorm=6,
00454   gs_fnNorm=7,
00455   gs_dummy=8,
00456   gs_migrate=9,
00457   gs_ambgCheck=10};
00458 
00459 // 0     1      2      3       4    5     6       7       8      9    10
00460 //fAll,  Solve, PCST,  fTop,  VRes, Gen, CtNorm, FnNorm, Dummy, Mig, Ambg
00461 
00462 static bool genSteps[6][11] = {
00464 // Case gen_instance[0]
00465 //fAll,  Solve, PCST,  fTop,  VRes, Gen, CtNorm, FnNorm, Dummy, Mig, Ambg
00466   {false, false, false, false, true, true, false, false,  false, true, true},
00467 // Case gen_top [1]
00468 //fAll,  Solve, PCST,  fTop,  VRes, Gen, CtNorm, FnNorm, Dummy, Mig, Ambg
00469   {false, true, true,  true, true, true, true,   true,   true, true, true},
00470 // Case gen_local [2]
00471 //fAll,  Solve, PCST,  fTop,  VRes, Gen, CtNorm, FnNorm, Dummy, Mig, Ambg
00472   {false, true, true,  false, true, true, true,  false,  false, true, true},
00473 
00475 // Case gen_instance[3]
00476 //fAll,  Solve, PCST,  fTop,  VRes, Gen, CtNorm, FnNorm, Dummy, Mig, Ambg
00477   {true, false, false, false, true, true, false, false,  false, true, true},
00478 // Case gen_top [4]
00479 //fAll,  Solve, PCST,  fTop,  VRes, Gen, CtNorm, FnNorm, Dummy, Mig, Ambg
00480   {true, true,  false, false, true, true, true,  true,   true,  true, true},
00481 // Case gen_local [5]
00482 //fAll,  Solve, PCST,  fTop,  VRes, Gen, CtNorm, FnNorm, Dummy, Mig, Ambg
00483   {true, true,  false, false, true, true, true,  false,  false, true, true},
00484 };
00485 
00486 #define GEN_STEP(m,s) if (genSteps[m][s])
00487 #define GEN_STEP2(m,s1,s2) if (genSteps[m][s1] || genSteps[m][s2])
00488 
00489 bool
00490 TypeScheme::generalize(std::ostream& errStream, 
00491                        const LexLoc &errLoc,
00492                        shared_ptr<const TSEnvironment > gamma,
00493                        shared_ptr<const InstEnvironment >
00494                        instEnv, 
00495                        shared_ptr<const AST> expr, 
00496                        shared_ptr<TCConstraints> parentTCC,
00497                        shared_ptr<Trail> trail,
00498                        GeneralizeMode mode)
00499 {
00500   bool errFree = true;  
00501   bool exprExpansive=false;
00502   bool typExpansive=false;
00503   bool expansive=false;
00504   bool rem1=false;
00505   bool rem2=false;
00506 
00507   DEBUG(GEN) errStream << "To Generalize " 
00508                       << asString(Options::debugTvP)
00509                       << " for expression "
00510                       << expr->asString() 
00511                       << std::endl;
00512   
00513   DEBUG(GEN_TL) if (mode == gen_top)
00514     mode = gen_local;
00515 
00516   tau->normalize();
00517   
00518   if (Options::heuristicInference) {
00519     switch(mode) {
00520     case gen_instance:
00521       mode = gen_Hinstance;
00522       break;
00523     case gen_top:
00524       mode = gen_Htop;
00525       break;
00526     case gen_local:
00527       mode = gen_Hlocal;
00528       break;
00529     default:
00530       assert(false);
00531       break;
00532     }
00533   }
00534   
00535   // Step 0: Heiristic Inference
00536   GEN_STEP(mode, gs_fixAll) {
00537     tau->adjMaybe(trail, false, true);
00538 
00539     DEBUG(GEN) errStream << "[0] Heuristic Adjustment " 
00540                         << asString(Options::debugTvP)
00541                         << std::endl;
00542   }
00543 
00544   // Step 1
00545   GEN_STEP(mode, gs_solve) {
00546     CHKERR(errFree, solvePredicates(errStream, errLoc, 
00547                                     instEnv, trail)); 
00548     
00549     DEBUG(GEN) errStream << "[1] Solve: " 
00550                         << asString(Options::debugTvP)
00551                         << std::endl;
00552   }
00553 
00554   // Step 2
00555   GEN_STEP(mode, gs_pcst) {
00556     if (!tau->isDeepMut() && !tau->isDeepImmut()) {
00557       shared_ptr<Type> pcst = Constraint::make(ty_pcst); 
00558       pcst->components.push_back(comp::make(Type::make(ty_kvar)));
00559       pcst->components.push_back(comp::make(tau)); // General Type
00560       pcst->components.push_back(comp::make(tau)); // Instantiation Type
00561       tcc->addPred(pcst);
00562       
00563       DEBUG(GEN) errStream << "[2] With Pcst: " 
00564                           << asString(Options::debugTvP)
00565                           << std::endl;
00566       
00567     }
00568   }
00569 
00570   // Step 3
00571   GEN_STEP(mode, gs_fixTop) {
00572     tau->adjMaybe(trail, false, true);
00573 
00574     bool cleared = false;
00575     for (TypeSet::iterator itr = tcc->begin();
00576         itr != tcc->end(); ++itr) {
00577       shared_ptr<Type> pred = (*itr);
00578       if (!pred->isPcst())
00579         continue;
00580 
00581       cleared = true;
00582       shared_ptr<Type> k = pred->CompType(0)->getType();
00583       shared_ptr<Type> gen = pred->CompType(1)->getType();
00584       shared_ptr<Type> ins = pred->CompType(2)->getType();
00585       
00586       assert(k != Type::Kmono);
00587       if (k->typeTag == ty_kvar) {
00588         trail->subst(k, Type::Kpoly);
00589         k = k->getType();
00590       }
00591       assert(k == Type::Kpoly);
00592       
00593       shared_ptr<Type> tgg = gen->minimizeDeepMutability();
00594       shared_ptr<Type> tii = ins->minimizeDeepMutability();
00595       assert(gen->unifyWith(tgg, false, trail, errStream));
00596       assert(ins->unifyWith(tii, false, trail, errStream));
00597     }
00598 
00599     if (cleared) {
00600       ConstraintSet oldPreds = tcc->pred;
00601       tcc->pred.clear();
00602       
00603       for (TypeSet::iterator itr = oldPreds.begin();
00604           itr != oldPreds.end(); ++itr) {
00605         shared_ptr<Type> pred = (*itr);
00606         if (!pred->isPcst())
00607           tcc->addPred(pred);
00608       }
00609       
00610       CHKERR(errFree, solvePredicates(errStream, errLoc, 
00611                                       instEnv, trail)); 
00612     }
00613 
00614     DEBUG(GEN) errStream << "[3] Top-Fix: " 
00615                         << asString(Options::debugTvP)
00616                         << std::endl;
00617   }
00618   
00619   // Step 4
00620   GEN_STEP(mode, gs_valRes) {
00621     exprExpansive = isExpansive(errStream, gamma, expr);
00622     typExpansive = isExpansive(errStream, gamma, tau);
00623     expansive = exprExpansive || typExpansive;
00624   }
00625 
00626   // Step 5
00627   GEN_STEP(mode, gs_genFtvs) {
00628     if (!expansive)
00629       collectftvs(gamma);
00630     
00631     DEBUG(GEN) errStream << "[5] Generalize: " 
00632                         << ((expansive) ? " {Expansive} " : " {Value} ")
00633                         << asString(Options::debugTvP)
00634                         << std::endl;    
00635   }
00636   
00637   // Step 6
00638   GEN_STEP(mode, gs_ctrNorm) {
00639     if (!expansive) {
00640       rem1 = removeUnInstFtvs();
00641     
00642       DEBUG(GEN) errStream << "[6] Remove Uninst-Ftvs: " 
00643                           << asString(Options::debugTvP)
00644                           << std::endl;
00645     }
00646   }
00647   
00648   // Step 7
00649   GEN_STEP(mode, gs_fnNorm) {
00650     if (!expansive) {
00651       rem2 = normalizeConstruction(trail);
00652       
00653       DEBUG(GEN) errStream << "[7] Construction Normalization: " 
00654                           << asString(Options::debugTvP)
00655                           << std::endl;
00656     }
00657   }
00658   
00659   GEN_STEP2(mode, gs_ctrNorm, gs_fnNorm) {
00660     if (rem1 || rem2)
00661       CHKERR(errFree, solvePredicates(errStream, errLoc, 
00662                                       instEnv, trail)); 
00663     
00664     DEBUG(GEN) errStream << "[7#] Re-Solve: " 
00665                         << asString(Options::debugTvP)
00666                         << std::endl;
00667   }
00668   
00669   // Step 8
00670   GEN_STEP(mode, gs_dummy) {
00671     if (expansive) {
00672       collectftvs(gamma);
00673 
00674       if (ftvs.size()) {
00675         TypeSet dummys = ftvs;
00676         ftvs.clear();
00677         
00678         for (TypeSet::iterator itr = dummys.begin();
00679             itr != dummys.end(); ++itr) {
00680           shared_ptr<Type> ftv = (*itr)->getType();
00681           ftv->link = Type::make(ty_dummy);
00682         }
00683         
00684         errStream << errLoc << ": WARNING: The type of"
00685                   << " this toplevel definition "
00686                   << expr->asString() << " "
00687                   << " cannot be fully generalized"
00688                   << " due to the value restriction."
00689                   << " The type obtained is: "
00690                   << tau->asString() << "."
00691                   << std::endl;    
00692       }
00693     }
00694   }
00695 
00696   // Step 9
00697   GEN_STEP(mode, gs_migrate) {
00698     migratePredicates(parentTCC);
00699     DEBUG(GEN) errStream << "[9] Migrated Constraints: " 
00700                         << asString(Options::debugTvP)
00701                         << std::endl;
00702   }
00703 
00704   // Step 10
00705   GEN_STEP(mode, gs_ambgCheck) {
00706     CHKERR(errFree, checkAmbiguity(errStream, errLoc));
00707     
00708     DEBUG(GEN) errStream << "FINAL: " 
00709                         << asString(Options::debugTvP)
00710                         << std::endl 
00711                         << std::endl;
00712   }
00713   
00714   return errFree;
00715 }
00716 
00717 
00718 /**********************************************************
00719                      Pattern Generalization
00720  **********************************************************/
00721 
00722 /* Helper routines to generalize a pattern */
00723 static void
00724 updateSigmas(shared_ptr<const AST> bp, const TypeSet& ftvs,
00725              shared_ptr<TCConstraints> tcc)
00726 {
00727   switch(bp->astType) {
00728   case at_identPattern:
00729     {
00730       shared_ptr<AST> ident = bp->child(0);
00731       shared_ptr<TypeScheme> sigma = ident->scheme;
00732       assert(ident->scheme);
00733       shared_ptr<Type> tau = sigma->tau;;
00734       
00735       for (TypeSet::iterator itr_i = ftvs.begin();
00736           itr_i != ftvs.end(); ++itr_i) {
00737         if (tau->boundInType(*itr_i)) {
00738           sigma->ftvs.insert(*itr_i);
00739           continue;
00740         }
00741         
00742         if (tcc)
00743           for (TypeSet::iterator itr = tcc->begin();
00744               itr != tcc->end(); ++itr) {
00745             shared_ptr<Constraint> pred = (*itr);
00746             if (pred->boundInType(*itr_i)) {
00747               sigma->ftvs.insert(*itr_i);
00748               break;
00749             }
00750           }
00751       }
00752       
00753       sigma->tcc = tcc;
00754       break;
00755     }
00756     
00757   case at_letGather:
00758     {
00759       for (size_t c = 0; c < bp->children.size(); c++)
00760         updateSigmas(bp->child(c), ftvs, tcc);
00761       break;
00762     }
00763 
00764   default:
00765     {
00766       assert(false);
00767       break;
00768     }
00769   }
00770 }
00771 
00772 bool
00773 generalizePat(std::ostream& errStream,
00774               const LexLoc &errLoc,
00775               shared_ptr<TSEnvironment > gamma,
00776               shared_ptr<const InstEnvironment > instEnv,
00777               shared_ptr<AST> bp, shared_ptr<AST> expr,
00778               shared_ptr<TCConstraints> tcc,
00779               shared_ptr<TCConstraints> parentTCC,
00780               shared_ptr<Trail> trail)
00781 {
00782   bool errFree = true;
00783 
00784   // Make a temporary typeScheme for the pattern.
00785   // Individual identifiers' TypeScheme will be updated after the 
00786   // pattern is generalized as a whole.
00787   shared_ptr<TypeScheme> sigma = TypeScheme::make(bp->symType, bp, tcc);
00788 
00789   CHKERR(errFree, 
00790          sigma->generalize(errStream, errLoc, 
00791                            gamma, instEnv, expr, parentTCC,
00792                            trail, gen_local));
00793   
00794   updateSigmas(bp, sigma->ftvs, tcc);
00795 
00796   // Puts the letgather type here.
00797   expr->symType = bp->symType = sigma->tau;
00798   expr->scheme = bp->scheme = sigma;
00799 
00800   return errFree;
00801 }
00802 
00803 /******************************************************************
00804                        Predicate Migration 
00805 
00806   Migrate appropriate constraints to parent's TCC, if one exists
00807    let C'' = migrate(parent-sigma, C')
00808       --> Constraints purely over monomorphic type variables can be
00809           migrated to the containing scope.
00810    
00811   This function returns true if at least one predicate was migrated to
00812   the containing scope, false otherwise. 
00813 
00814   Suppose the current type scheme s = forall 'a*.t\C
00815 
00816   For each predicate p in C,
00817 
00818   1) FTV(p) = 0 CANNOT HAPPEN. The prediate is concrete, and must be
00819      have been solved at this step.
00820 
00821   2) If FTVS(p) intersection 'a* = {}, then this predicate can be
00822      migrated. 
00823 *********************************************************************/
00824 
00825 
00826 bool
00827 TypeScheme::migratePredicates(shared_ptr<TCConstraints> parentTCC)
00828 {
00829   if (!parentTCC)
00830     return false;
00831   
00832   bool migrated = false;
00833   TypeSet newPred;
00834   
00835   for (TypeSet::iterator itr = tcc->begin();
00836       itr != tcc->end(); ++itr) {
00837     shared_ptr<Typeclass> pred = (*itr)->getType();
00838     TypeSet allFtvs;
00839     pred->collectAllftvs(allFtvs);
00840     
00841     assert(allFtvs.size());
00842     
00843     bool hasFtv = false;
00844     for (TypeSet::iterator itr_j = allFtvs.begin();
00845         itr_j != allFtvs.end(); ++itr_j) {
00846       shared_ptr<Type> ftv = (*itr_j)->getType();
00847       
00848       if (ftvs.find(ftv) != ftvs.end()) {
00849         hasFtv = true;
00850         break;
00851       }
00852     }
00853     
00854     if (hasFtv) {
00855       newPred.insert(pred);
00856     }
00857     else {
00858       parentTCC->addPred(pred);
00859       migrated = true;
00860     }
00861   }
00862     
00863   tcc->pred = newPred;
00864   return migrated;
00865 }
00866 
00867 /**************************************************************
00868                          Ambiguity Check
00869 
00870    Check if a type scheme s = forall 'a*. t\C is ambiguous.
00871    If there exists a 'a such that 
00872       'a in {'a*}, 
00873       'a in FTVS(C) and 
00874       'a not in FTVS(t')
00875     then s is ambiguous.
00876 
00877    For example: 
00878      read:  forall 'a. () -> 'a \ {Readable('a)}
00879      write: forall 'a. 'a -> () \ {Writable('a)}
00880 
00881    What about write(read ()) ?
00882   
00883      write(read ()): forall 'a. () \ Readable('a), Writable('a).
00884 
00885    This case is traditionally declared and error because there is no
00886    way to instantiate the 'a at the use location.
00887 
00888    It is not clear that "ambiguous" typing is an error. In fact, it
00889    does not break subject reduction, and execution can continue by
00890    picking any instantiation of the variable. In particular, it is (in
00891    a way) necessary in the case of polymorphic consrtaints.
00892 
00893    For example, consider:
00894    
00895     let(k1) id = \x.x 
00896     Ignoring the internal maybe types at function argument and return
00897     positions, we can write:
00898     
00899     id: forall 'a,'b. 'b|'a->'a  \ {*(k1, 'b|'a->'a, 'b|'a->'a)}
00900     
00901     This type is not ambiguous. Now, if we write:
00902 
00903     let(k2) id2 = \y.(id y),
00904 
00905     the type if id2 will be:
00906 
00907     id2: forall 'c,'d,'e. 'd|'c->'c  \ {*(k1, 'b|'a->'a, 'e|'c->'c),
00908                                         *(k2, 'd|'c->'c, 'd|'c->'c)}
00909 
00910     Here, the type of id2 will be declared ambiguous, which we cannot
00911     accept. 
00912     
00913    It seems that we can take a middle ground where ambiguity check is
00914    performed only for type-class constraints. However, in the presence
00915    of copy-compatibility, even this is insufficient. Consider the
00916    following case:
00917 
00918    (deftypeclass (Tc 'a)
00919       mt: (fn ('a) bool))
00920 
00921    (define (f x) (mt x))
00922    f: forall 'a,'b,'c,'d. (fn ('a|'b) 'c|bool) \ Tc('d|'b)
00923 
00924    Actually, the top-level mutability on the type-class does not
00925    matter (as long as the argument) is not used in a reference
00926    context, and can be ignored in the ambiguity check. However,
00927    it seems that the correct solution is to turn off the ambiguity
00928    check. There is now only a stub-code for the ambiguty check.
00929 *********************************************************************/
00930 
00931 bool 
00932 TypeScheme::checkAmbiguity(std::ostream &errStream, const LexLoc &errLoc)
00933 {
00934 #if 0
00935   bool errFree =true;
00936   for (size_t j=0; j < ftvs->size(); j++) {
00937     shared_ptr<Type> ftv = ftvs->elem(j);
00938     
00939     if (!tau->boundInType(ftv)) {
00940       // ftv must be bound in some predicate.
00941 
00942       for (size_t c=0; c < tcc->size(); c++) {
00943         shared_ptr<Typeclass> pred = tcc->Pred(c);
00944         if (pred->isPcst())
00945           continue;
00946         
00947         // The ftv is bound in a type-class predicate.
00948         if (pred->boundInType(ftv)) {
00949           errStream << errLoc << ": "
00950                     << "Type variable "
00951                     << ftv->asString(Options::debugTvP)
00952                     << " unbound in "
00953                     << tau->asString(Options::debugTvP)
00954                     << " wrt "
00955                     << asString(Options::debugTvP)
00956                     << std::endl;
00957           
00958           errFree = false;
00959           break;
00960         }
00961       }
00962     }
00963   }
00964 
00965   if (!errFree)
00966     errStream << errLoc << ": "
00967               << "Ambiguous type definition:"
00968               << asString()
00969               << std::endl;
00970   return errFree;
00971 #else
00972   return true;
00973 #endif
00974 }
00975 
00976 
00977 /**********************************************************
00978  **********************************************************
00979                Type Specialization
00980 
00981  **********************************************************
00982  **********************************************************/
00983 
00984 
00985 /**********************************************************
00986                   THE Type Specializer 
00987 ***********************************************************/
00988 
00989 shared_ptr<Type> 
00990 Type::TypeSpecializeReal(const std::vector<boost::shared_ptr<Type> >& ftvs,
00991                          std::vector<boost::shared_ptr<Type> >& nftvs)
00992 {
00993   shared_ptr<Type> t = getType();
00994   shared_ptr<Type> theType = Type::make(t);
00995   theType->flags &= ~TY_SP_MASK;
00996   theType->typeArgs.clear();
00997   theType->components.clear();
00998   shared_ptr<Type> retType = theType;
00999   
01000   DEBUG(INS) std::cout << "To Specialize " 
01001                       << this->asString()  
01002                       << std::endl;  
01003 
01004   if (t->sp)
01005     retType = t->sp;
01006   else {    
01007     t->sp = retType;
01008   
01009     switch(t->typeTag) {    
01010     case ty_kvar:
01011       {
01012         retType = t;
01013         break;
01014       }
01015     case ty_pcst:
01016       {
01017         // the let-kind and generic type are added as is.
01018         theType->components.push_back(comp::make(t->CompType(0)));
01019         theType->components.push_back(comp::make(t->CompType(1)));
01020         // The instance of the constraint is specialized.
01021         shared_ptr<Type> ins = t->CompType(2)->TypeSpecializeReal(ftvs, nftvs);
01022         theType->components.push_back(comp::make(ins));
01023         break;
01024       }
01025     case ty_tvar:
01026       {
01027         size_t i=0;
01028         for (i=0; i<ftvs.size(); i++) {
01029           shared_ptr<Type> ftv = ftvs[i]->getType();          
01030           if (ftv->typeTag == ty_tvar && t->uniqueID == ftv->uniqueID) {
01031             theType->link = nftvs[i]; 
01032             break;
01033           }
01034         }
01035         
01036         // If the variable was NOT in ftv list, then 
01037         // we should link it to the original, in order to honor
01038         // variable capture
01039         if (i == ftvs.size())
01040           theType->link = t;
01041               break;
01042       }
01043 
01044     default:
01045       {      
01046         /* Deal with Type-args */
01047         for (size_t i=0; i<t->typeArgs.size(); i++) {
01048           shared_ptr<Type> arg = t->TypeArg(i)->getType();
01049           shared_ptr<Type> newArg = arg->TypeSpecializeReal(ftvs, nftvs);
01050           
01051           theType->typeArgs.push_back(newArg);
01052         }
01053             
01054         /* Deal with Components */
01055         for (size_t i=0; i<t->components.size(); i++) {
01056           shared_ptr<comp> nComp = 
01057             comp::make(t->CompName(i),
01058                        t->CompType(i)->TypeSpecializeReal(ftvs, nftvs),
01059                        t->CompFlags(i));
01060           theType->components.push_back(nComp);
01061         }
01062 
01063         /* Deal with fnDeps if any */
01064         if (t->fnDeps.size()) {
01065           theType->fnDeps.clear();
01066 
01067           for (TypeSet::iterator itr = t->fnDeps.begin();
01068               itr != t->fnDeps.end(); ++itr) {
01069             shared_ptr<Type> fnDep = (*itr)->TypeSpecializeReal(ftvs, nftvs);
01070             theType->addFnDep(fnDep);
01071           }
01072         }
01073         
01074         break;
01075       }      
01076     }
01077   }
01078   
01079   DEBUG(INS) std::cout << "\t Specialized " 
01080                       << getType()->asString(GC_NULL)
01081                       << " to " 
01082                       << retType->getType()->asString(GC_NULL)
01083                       << std::endl;
01084   
01085   return retType;
01086 }
01087 
01088 // Clear the sp (specialization) field of type records recursively.
01089 void
01090 Type::clear_sp()
01091 {
01092   shared_ptr<Type> t = getType();
01093   if (!t->sp)
01094     return;
01095 
01096   t->sp = GC_NULL;
01097 
01098   for (size_t i=0; i<t->typeArgs.size(); i++)
01099     t->TypeArg(i)->clear_sp();
01100 
01101   for (size_t i=0; i<t->components.size(); i++)
01102     t->CompType(i)->clear_sp();
01103 
01104   for (TypeSet::iterator itr = t->fnDeps.begin();
01105       itr != t->fnDeps.end(); ++itr)
01106     (*itr)->clear_sp();
01107 }
01108 
01109 /**********************************************************
01110                   The Specizlizer interface 
01111 ***********************************************************/
01112 
01113 shared_ptr<Type> 
01114 Type::TypeSpecialize(const std::vector<boost::shared_ptr<Type> >& ftvs,
01115                      std::vector<boost::shared_ptr<Type> >& nftvs)
01116 {
01117   shared_ptr<Type> specializedType = TypeSpecializeReal(ftvs, nftvs);
01118   clear_sp();
01119   return specializedType;
01120 }
01121 
01122 

Generated on Fri Feb 10 07:59:20 2012 for BitC Compiler by  doxygen 1.4.7