TypeInferCommon.cxx

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright (C) 2006, 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 <stdint.h>
00039 #include <stdlib.h>
00040 #include <iostream>
00041 #include <string>
00042 #include <sstream>
00043 #include <libsherpa/UExcept.hxx>
00044 #include <libsherpa/CVector.hxx>
00045 #include "UocInfo.hxx"
00046 #include "Options.hxx"
00047 #include "AST.hxx"
00048 #include "Type.hxx"
00049 #include "TypeScheme.hxx"
00050 #include "TypeMut.hxx"
00051 #include "Typeclass.hxx"
00052 #include "inter-pass.hxx"
00053 #include "TypeInfer.hxx"
00054 #include "TypeInferCommon.hxx"
00055 
00056 using namespace sherpa;
00057 using namespace std;
00058 
00059 /**************************************************************/
00060 /*                     Some Helper Functions                  */
00061 /**************************************************************/
00062 
00063 //#define VERBOSE
00064 
00065 GCPtr<Type> 
00066 obtainFullUnionType(GCPtr<Type> t)
00067 {  
00068   //   std::cerr << "Input = " 
00069   //        << t->toString()
00070   //                << std::endl;
00071   
00072   t = t->getBareType();  
00073   assert(t->isUType());
00074   GCPtr<AST> unin = t->myContainer;  
00075   GCPtr<TypeScheme> uScheme = unin->scheme;
00076   GCPtr<Type> uType = uScheme->type_instance_copy();  
00077 
00078   assert(uType->typeArgs->size() == t->typeArgs->size());
00079 
00080   for(size_t c=0; c < uType->typeArgs->size(); c++)
00081     t->TypeArg(c)->unifyWith(uType->TypeArg(c));
00082   
00083   //   std::cerr << "Output = " 
00084   //        << uType->toString()
00085   //        << std::endl;
00086   
00087   return uType;
00088 }
00089 
00090 
00091 
00092 /**************************************************************/
00093 /*                    Environment handling                    */
00094 /**************************************************************/
00095 
00096 /* Use all bindings in the some other environment */
00097 void
00098 useIFGamma(const std::string& idName,
00099            GCPtr<Environment<TypeScheme> > fromEnv, 
00100            GCPtr<Environment<TypeScheme> > toEnv)
00101 {
00102   for (size_t i = 0; i < fromEnv->bindings->size(); i++) {
00103     GCPtr<Binding<TypeScheme> > bdng = fromEnv->bindings->elem(i);
00104 
00105     if (bdng->flags & BF_PRIVATE)
00106       continue;
00107 
00108     std::string s = bdng->nm;
00109     GCPtr<TypeScheme> ts = bdng->val;
00110 
00111     if (idName.size())
00112       s = idName + "." + s;
00113 
00114     toEnv->addBinding(s, ts);
00115     toEnv->setFlags(s, BF_PRIVATE|BF_COMPLETE);
00116   }  
00117 }
00118 
00119 /* Use all instances from some other environment. Unlike Type
00120    environmen, this one needs explicit checking to make sure there are
00121    no collisions */
00122 
00123 bool
00124 useIFInsts(std::ostream &errStream,
00125            LexLoc &errLoc,
00126            GCPtr<Environment< CVector<GCPtr<Instance> > > >fromEnv, 
00127            GCPtr<Environment< CVector<GCPtr<Instance> > > >toEnv,
00128            unsigned long uflags)
00129 {
00130   bool errFree = true;
00131   for (size_t i = 0; i < fromEnv->bindings->size(); i++) {
00132     GCPtr<Binding< CVector<GCPtr<Instance> > > >bdng =
00133       fromEnv->bindings->elem(i);
00134 
00135     if (bdng->flags & BF_PRIVATE)
00136       continue;
00137     
00138     std::string s = bdng->nm;
00139     GCPtr<CVector<GCPtr<Instance> > > fromInsts = bdng->val;
00140     GCPtr<CVector<GCPtr<Instance> > > toInsts = toEnv->getBinding(s); 
00141 
00142     if(!toInsts) {
00143       toInsts = new CVector<GCPtr<Instance> >;
00144       for (size_t j = 0; j < fromInsts->size(); j++)
00145         toInsts->append(fromInsts->elem(j));
00146       toEnv->addBinding(s, toInsts);
00147     }
00148     else {
00149       for (size_t j = 0; j < fromInsts->size(); j++) {
00150         size_t k;
00151         bool mustAppend = true;
00152         GCPtr<Instance> fromInst = fromInsts->elem(j);
00153 
00154         for (k = 0; k < toInsts->size(); k++) {
00155           GCPtr<Instance> toInst = toInsts->elem(k);
00156           
00157           if(toInst == fromInst) {
00158             // We are seeing the same AST as a matter of import from
00159             // different interfaces. For example: diamond import,
00160             // or, Interface X imports prelude, obviously, and
00161             // exports all interfaces in the prelude. I have also
00162             // already seen the prelude. So, this need not be
00163             // re-considered, but this is not an error.
00164             // It is safe to ignore this because we are thinking of
00165             // the *same* instance defined at the same *AST* and              
00166             // thus, there is no conflict.
00167             mustAppend = false;
00168             break;
00169           }
00170           
00171           if((uflags & ALL_INSTS_OK) == 0)
00172             if(toInst->equals(errStream, fromInst, toEnv)) {
00173               errStream << errLoc << ": "
00174                         << "Conflict in Instance declarations "
00175                         << " of type " 
00176                         << toInsts->elem(k)->asString()
00177                         << " defined at " 
00178                         << toInsts->elem(k)->ast->loc << " and " 
00179                         << fromInsts->elem(j)->ast->loc << "."
00180                         << std::endl;
00181               errFree = false;
00182               mustAppend = false;           
00183               break;                              
00184             }
00185         }
00186           
00187         if(mustAppend) 
00188           toInsts->append(fromInsts->elem(j));
00189       }
00190     }
00191   }
00192   
00193   return errFree;
00194 }
00195   
00196 /* Initialize my environment */
00197 bool
00198 initGamma(std::ostream& errStream, 
00199           GCPtr<Environment<TypeScheme> > gamma,
00200           GCPtr<Environment< CVector<GCPtr<Instance> > > > instEnv,
00201           const GCPtr<AST> ast, unsigned long uflags)
00202 {
00203   bool errFree = true;
00204   // Make sure I am not processing the prelude itself
00205   // cout << "Processing " << ast->child(1)->child(0)->s 
00206   //      << std::endl;
00207   if(ast->child(0)->astType == at_interface &&
00208      ast->child(0)->child(0)->s == "bitc.prelude") {
00209     // cout << "Processing Prelude " << std::endl;
00210     return true;
00211   }
00212   
00213   // "use" everything in the prelude
00214   GCPtr<Environment<TypeScheme> > preenv = 0;
00215   GCPtr<Environment< CVector<GCPtr<Instance> > > > preInsts = 0;
00216   
00217   size_t i;
00218 
00219   for(i=0; i < UocInfo::ifList->size(); i++) {
00220     if(UocInfo::ifList->elem(i)->uocName == "bitc.prelude") {
00221       preenv = UocInfo::ifList->elem(i)->gamma;
00222       preInsts = UocInfo::ifList->elem(i)->instEnv;
00223       break;
00224     }
00225   }
00226 
00227   if(i == UocInfo::ifList->size()) {
00228     errStream << ast->loc << ": "
00229               << "Internal Compiler Error. "
00230               << "Prelude has NOT been processed till " 
00231               << "type inference."
00232               << std::endl;
00233     return false;
00234   }
00235   
00236   if(!preenv || !preInsts) {
00237     errStream << ast->loc << ": "
00238               << "Internal Compiler Error. "
00239               << "Prelude's Gamma is NULL "
00240               << std::endl;
00241     return false;
00242   }
00243   
00244   useIFGamma(std::string(), preenv, gamma);
00245   LexLoc internalLocation;
00246   CHKERR(errFree, useIFInsts(errStream, internalLocation, 
00247                              preInsts, instEnv, uflags));
00248   return errFree;
00249 }
00250 
00251 

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