Typeclass.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 "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 
00059 using namespace boost;
00060 using namespace sherpa;
00061 using namespace std;
00062 
00063 bool 
00064 Instance::equals(shared_ptr<Instance> ins, 
00065                  shared_ptr<const InstEnvironment > instEnv) const
00066 {
00067   shared_ptr<TypeScheme> mySigma = ts->ts_instance();
00068   shared_ptr<TypeScheme> hisSigma = ins->ts->ts_instance();
00069 
00070   //std::cerr << mySigma->asString() << " vs " 
00071   //            << hisSigma->asString() 
00072   //            << std::endl;
00073 
00074   bool unifies = true;
00075   
00076   CHKERR(unifies, mySigma->tau->unifyWith(hisSigma->tau)); 
00077   
00078   if (!unifies)
00079     return false;
00080     
00081   assert(mySigma->tcc);
00082   assert(hisSigma->tcc);
00083   
00084   // This will also add self constraints.
00085   for (TypeSet::iterator itr = hisSigma->tcc->begin(); 
00086        itr != hisSigma->tcc->end(); ++itr) {
00087     shared_ptr<Typeclass> hisPred = (*itr);
00088     mySigma->tcc->addPred(hisPred);
00089   }
00090   
00091   std::stringstream ss;
00092   CHKERR(unifies, mySigma->solvePredicates(ss, ast->loc, 
00093                                            instEnv, Trail::make())); 
00094   
00095   if (!unifies)
00096     return false;
00097   
00098   if (mySigma->tcc->empty())
00099     return true;
00100   else
00101     return false;
00102 }
00103 
00104 // Check Instance overlapping:
00105 // Currently, all instances must be absolutely non-overlapping --
00106 // that is, non-unifiable.
00107 //
00108 // The operlapping check is different from equality check
00109 // For example, consider a class ABC wherein, we have instances
00110 //
00111 // (definstance (forall ((IntLit 'a)) (ABC 'a))  ... )
00112 // (definstance (forall ((FloatLit 'a)) (ABC 'a)) ...)
00113 //
00114 // The two instances are not equal, both have type (ABC 'a), and
00115 // therefore are overlapping. 
00116 //
00117 // If we declare these instances as non-overlapping, in the constraint
00118 // solver, if we have a constraint (ABC int32) The solver can 
00119 // 1) First come across the (((FloatLit 'a)) (ABC 'a)) instance
00120 // 2) Deem 'a unifiable with int32, assuming non-overlap
00121 // 3) Add pre-condition (FloatLit int32) which is unsatisfiable.
00122 //
00123 // The solver unifies with the first unifiable instance. It is not a
00124 // backtracking solver which tries other instances if the overall
00125 // solving fails for an instance. 
00126 
00127 bool 
00128 Instance::overlaps(boost::shared_ptr<Instance> ins) const
00129 {
00130   return ts->tau->equals(ins->ts->tau); 
00131 }
00132 
00133 
00134 bool 
00135 Instance::satisfies(shared_ptr<Typeclass> pred,                     
00136                     shared_ptr<const InstEnvironment >
00137                     instEnv) const
00138 {
00139   bool unifies = true;
00140   shared_ptr<TypeScheme> sigma = ts->ts_instance();
00141 
00142   CHKERR(unifies, sigma->tau->unifyWith(pred));   
00143   
00144   if (!unifies)
00145     return false;
00146     
00147   if (!sigma->tcc)
00148     return true;
00149 
00150   std::stringstream ss;
00151   LexLoc internalLocation;
00152   CHKERR(unifies, sigma->solvePredicates(ss, internalLocation, 
00153                                          instEnv, Trail::make()));
00154   
00155   if (!unifies)
00156     return false;
00157   
00158   if (sigma->tcc->empty())
00159     return true;
00160   else
00161     return false;
00162 }
00163 
00164 bool 
00165 Typeclass::addFnDep(shared_ptr<Type> dep) 
00166 {
00167   if (getType() != shared_from_this())
00168     return getType()->addFnDep(dep); // getType() OK
00169   
00170   if (typeTag != ty_typeclass)
00171     assert(false);
00172 
00173   if (dep->typeTag != ty_tyfn)
00174     assert(false);
00175   
00176   for (TypeSet::iterator itr = fnDeps.begin(); 
00177       itr != fnDeps.end(); ++itr) {
00178     if ((*itr)->strictlyEquals(dep, false, true))
00179       return false;
00180   }
00181 
00182   //   std::cout << "Adding fnDep " << dep->asString(NULL) 
00183   //               << " to " << this->asString(NULL) << "."
00184   //               << std::endl;
00185   fnDeps.insert(dep);
00186   return true;
00187 }
00188 
00189 void
00190 TCConstraints::collectAllFnDeps(TypeSet& fnDeps)
00191 {
00192   for (iterator itr = begin(); itr != end(); ++itr) {
00193     shared_ptr<Typeclass> pr = (*itr)->getType();    
00194 
00195     for (TypeSet::iterator itr_j=pr->fnDeps.begin();
00196         itr_j != pr->fnDeps.end(); ++itr_j) {
00197       shared_ptr<Type> fnDep = (*itr_j)->getType();
00198       assert(fnDep->typeTag == ty_tyfn);
00199       fnDeps.insert(fnDep);
00200     }
00201   }  
00202 }
00203 
00204 // Very important: if using pointer comparison, always add
00205 // getType()s to closure and compare with getType()s only.
00206 // I am relying on the fact that no unification happens
00207 // at this stage. Otherwise, a equals() or strictlyEquals()
00208 // must be used.
00209 
00210 void 
00211 TCConstraints::close(TypeSet& closure,
00212                      const TypeSet& fnDeps)
00213 {
00214   size_t newSize = 0; 
00215   size_t oldSize = 0;
00216   
00217   do {
00218     oldSize = newSize;    
00219     for (TypeSet::iterator itr = fnDeps.begin();
00220         itr != fnDeps.end(); ++itr) {
00221       shared_ptr<Type> fnDep = (*itr)->getType();
00222       shared_ptr<Type> fnDepArgs = fnDep->Args()->getType();
00223       shared_ptr<Type> fnDepRet = fnDep->Ret()->getType();      
00224       TypeSet argTvs;
00225       TypeSet retTvs;
00226       fnDepArgs->collectAllftvs(argTvs);      
00227       bool foundAll = true;
00228       for (TypeSet::iterator itr_j = argTvs.begin();
00229           itr_j != argTvs.end(); ++itr_j) {
00230         shared_ptr<Type> argTv = (*itr_j);
00231         if (closure.find(argTv) == closure.end()) {
00232           foundAll = false;
00233           break;
00234         }
00235       }
00236 
00237       if (foundAll) {        
00238         fnDepRet->collectAllftvs(retTvs);        
00239         for (TypeSet::iterator itr_j = retTvs.begin();
00240             itr_j != retTvs.end(); ++itr_j) {
00241           shared_ptr<Type> retTv = (*itr_j);
00242           if (closure.find(retTv) == closure.end())
00243             closure.insert(retTv);
00244         }
00245       }        
00246     }
00247     newSize = closure.size();
00248   } while (newSize > oldSize);
00249 }

Generated on Thu May 17 23:59:16 2012 for BitC Compiler by  doxygen 1.4.7