Instantiate.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 <stdint.h>
00039 #include <stdlib.h>
00040 #include <dirent.h>
00041 #include <errno.h>
00042 #include <fstream>
00043 #include <iostream>
00044 #include <string>
00045 #include <sstream>
00046 #include <map>
00047 
00048 #include "Options.hxx"
00049 #include "UocInfo.hxx"
00050 #include "AST.hxx"
00051 #include "Type.hxx"
00052 #include "inter-pass.hxx"
00053 #include "Instantiate.hxx"
00054 
00055 using namespace std;
00056 using namespace boost;
00057 using namespace sherpa;
00058 
00059 #if DEBUG_CND(INST)
00060 #define STRICTLYEQUALS(x) strictlyEqualsA(x, DEBUG_VERBOSE)
00061 #else
00062 #define STRICTLYEQUALS(x) strictlyEqualsA(x)
00063 #endif
00064 
00065 typedef map<shared_ptr<AST>, shared_ptr<AST> > AstMap;
00066 
00067 /*******************************************************************
00068                         ENVIRONMENT HANDLING
00069 *******************************************************************/
00070 
00071 /*
00072    Even though the unified-AST can be formed on demand, R&Ting the new
00073    definitions must be done in a fuly built environment --
00074    the mega-environment.
00075 
00076    We need the mega-environment because there is -- in general --
00077    no single environment where we can perform this R&T. For example,
00078    consider:
00079 
00080    (interface IF1
00081    (proclaim UID:(fn ('a) 'a))
00082    )
00083 
00084    (module SM1
00085    (provide if1 IF1)
00086    (defunion (un 'a) (Ctr c:'a))
00087    (define (UID x) (Ctr x) x)
00088    )
00089 
00090    (module SM2
00091    (defstruct St st:bool)
00092    (define p (UID (St))
00093    )
00094 
00095    => Now, if we want to instantiate p:
00096 
00097    1) We start with SM2's environment, need to instantiate p. So, we copy
00098    the definition of p as:
00099    (define p#St (UID (St))), and type it in SM2's environment,
00100    everything is OK.
00101 
00102    2) Now, we need to recurse over this definition, we encounter UID,
00103    get its definition, see that it is a proclaimation, and get its
00104    real definition. Then, we make a copy of this definition:
00105 
00106    (define UID#fn_St_St:(fn (St) St) (lambda (x) (Ctr x) x))
00107 
00108    Now, we must type it. Which environment should we type it in?
00109 
00110    Not in SM1 because we don't know `St' there, and not in SM2 because
00111    we don't  know `un' there. Not in the big-AST environment as there is
00112    nothing relevant there.
00113 
00114    There is no single environment which has enough information to type
00115    this new definition.
00116 
00117    Moreover, this fully built environment must also contain the output
00118    definitions produced by the polyinstantiator because
00119    further instantiations may need this definition. When we are
00120    recursing over the instantiated form, looking for further
00121    specialization, some types or functions will be specialized over
00122    the types that are newly instantiated. For example:
00123    (defstruct st1 a:int32 b:(list bool))
00124 
00125    (defstruct (st2 'a 'b) a:'a b:'b)
00126    (define (main.main argVec:(vector string))
00127    (cons
00128    (st2 (st2 #t (cons 0:int32 nil))
00129    (st1 0:int32 (cons #t nil)))
00130    nil)
00131    0:int32)
00132 
00133    In order to solve both of these problems, we build the *output* UOC
00134    (also called target-uoc or unified-Uoc) in
00135    the following form:
00136 
00137    Unified-UOC
00138    -----------
00139    |         |    ------------------  parent   ---------------
00140    | env   --|--->| unified-env    |==========>|  mega-env   |
00141    |         |    ------------------           ---------------
00142    | gamma --|--->|unified-gamma   |==========>|  mega-gamma |
00143    |         |    ------------------           ---------------
00144    |instEnv--|--->|unified-instEnv |==========>|  mega-gamma |
00145    |         |    ------------------           ---------------
00146    -----------
00147 */
00148 
00149 /*
00150   The main environment(s) which the Unified-UOC thinks it has, is the
00151   UOC where the output of the polyinstantiator resides. By prior
00152   arrangement (see CreateUnifiedUOC) we will build wrappers around the
00153   main environments, which will hold the mega-environments. In this
00154   way, when the resolver/type-checker looks at the environment, it can
00155   find ALL definitions (from all input and output).
00156 
00157   Since the instantiator's output is mutually exclusive from the
00158   input, there will be no collisions. Also, the wrappers MUST NEVER be
00159   discarded if we want to support incremental instantiation /
00160   interpretation. For this reason, all further passes must call R&T
00161   with reinit-flag turned on.
00162 
00163   In the future comments, will will refer to the megaENVs and
00164   unifiedUOC in separate terms sometimes, but it should be understood
00165   that they are both reachable from the unifiedUOC and that any such
00166   separation is only a matter of emphasis. */
00167 
00168 
00169 /* We have previously established that we need to build a
00170    mega-Env from all UOCs. How do we want to build it? Of
00171    course, for the first time, we  must build it by iterating over all
00172    the environments of all interfaces  and source modules and build a new
00173    environment based on their FQNs. However, we do not want to do it
00174    every time we enter the instantiator.  Since here is that the
00175    interface-list and the source-module list are append-only -- they are
00176    append-only in the case of an interactive interpreter; in the case of
00177    static compiler, these lists are frozen -- we can note the previously
00178    last processed indices into these lists, and  only processes additions
00179    each time.
00180 
00181    In the case of a compiler, interfaces and source module environments are
00182    immutable once the entire module is processed. Therefore, the index into
00183    the module list will suffice. However, in the case of an interactive
00184    interpreter, there is exactly one unit of compilation that is ever
00185    expanding, and the instantiator must cope with this. There are two ways
00186    in which we can think about the interactive loop.
00187 
00188    i) Some units of compilation are "dynamic" and the instantiator must
00189    process them every-time (as an optimization, we can remember their last
00190    processed environment index, and process only the new ones).
00191 
00192    ii) The interactive loop is not one unit of compilation, but it is an
00193    arrangement of nested interfaces, each of which is by itself frozen.
00194    That is, _every_ new definition has its own interface, and will import
00195    the interface introduced in the previous step, and use all the forms
00196    in it.
00197 
00198    Option (i) is probably better from an implementation standpoint.
00199 
00200    In the current implementation, we have two falgs on every UOC:
00201    UOC_IS_MUTABLE: Definitions in this UOC must be examined at every
00202    step.
00203    UOC_SEEN_BY_INST: UOC has been processed already.
00204 
00205    We only need to reprocess the UOC if we have never seen it before, or
00206    it is mutable. */
00207 
00208 
00209 static void
00210 importSymBindings(shared_ptr<ASTEnvironment > fromEnv,
00211                   shared_ptr<ASTEnvironment > toEnv)
00212 {
00213   for (ASTEnvironment::iterator itr = fromEnv->begin();
00214       itr != fromEnv->end(); ++ itr) {
00215     shared_ptr<Binding<AST> > bdng = itr->second;
00216 
00217     if ((bdng->flags & BF_PRIVATE) == 0) {
00218       std::string nm = bdng->val->fqn.asString();
00219       toEnv->addBinding(nm, bdng->val);
00220       toEnv->setFlags(nm, BF_REBIND | BF_COMPLETE);
00221 
00222       DEBUG(INST_ENV)
00223         cerr << "Added to env: "
00224              << bdng->val->fqn.asString()
00225              << endl;
00226     }
00227   }
00228 }
00229 
00230 static void
00231 importTSBindings(shared_ptr<TSEnvironment > fromEnv,
00232                  shared_ptr<TSEnvironment > toEnv)
00233 {
00234   for (TSEnvironment::iterator itr = fromEnv->begin();
00235       itr != fromEnv->end(); ++ itr) {
00236     shared_ptr<Binding<TypeScheme> > bdng = itr->second;
00237 
00238     if ((bdng->flags & BF_PRIVATE) == 0) {
00239       std::string nm = bdng->val->ast->fqn.asString();
00240       toEnv->addBinding(nm, bdng->val);
00241       toEnv->setFlags(nm, BF_REBIND | BF_COMPLETE);
00242 
00243       DEBUG(INST_ENV)
00244         cerr << "Added to Gamma: "
00245              << bdng->val->ast->fqn.asString()
00246              << " with type "
00247              << bdng->val->asString()
00248              << endl;
00249     }
00250   }
00251 }
00252 
00253 static void
00254 importInstBindings(shared_ptr<InstEnvironment > fromEnv,
00255                    shared_ptr<InstEnvironment > toEnv)
00256 {
00257   for (InstEnvironment::iterator itr = fromEnv->begin();
00258       itr != fromEnv->end(); ++ itr) {
00259     shared_ptr<Binding<InstanceSet> > bdng =
00260       itr->second;
00261 
00262     if (bdng->flags & BF_PRIVATE)
00263       continue;
00264 
00265     shared_ptr<InstanceSet> fromInsts = bdng->val;
00266     if (fromInsts->size() == 0)
00267       continue;
00268 
00269     // We need the FQN of the typeclass. Choose an arbitrary member of
00270     // the instance set, reach into that instance's definition's AST,
00271     // the get the AST of the Typeclass being defined and then its
00272     // FQN.
00273     InstanceSet::iterator itr = fromInsts->begin();
00274 
00275     shared_ptr<AST> instAST = (*itr)->ast;
00276     shared_ptr<AST> tcAST = instAST->child(0)->child(0)->symbolDef;
00277     string tcFQN = tcAST->fqn.asString();
00278 
00279     shared_ptr<InstanceSet> toInsts = toEnv->getBinding(tcFQN);
00280     if (toInsts) {
00281       cerr << "Available non-private instance for "
00282            << tcFQN << ": ";
00283       for (InstanceSet::iterator itr_j = toInsts->begin();
00284            itr_j != toInsts->end(); ++itr_j)
00285         cerr << (*itr_j)->asString() << "     ";
00286       cerr << endl;
00287       assert(false);
00288     }
00289 
00290     DEBUG(INST_ENV)
00291       cerr << "Adding Instance for " << tcFQN << endl;
00292     toEnv->addBinding(tcFQN, fromInsts);
00293   }
00294 }
00295 
00296 void
00297 UpdateMegaEnvs(shared_ptr<UocInfo> uoc)
00298 {
00299   // The input uoc is the unifiedUOC, So, get the megaENVs
00300   // from the current uoc by fetching the parents of the
00301   // current envs.
00302   shared_ptr<ASTEnvironment > megaEnv = uoc->env->parent;
00303   shared_ptr<TSEnvironment > megaGamma = uoc->gamma->parent;
00304   shared_ptr<InstEnvironment > megaInstEnv =
00305     uoc->instEnv->parent;
00306 
00307   DEBUG(INST_ENV)
00308     cerr << "#envs = " << megaEnv->size()
00309          << endl
00310          << "#tss = " << megaGamma->size()
00311          << endl
00312          << "#Instances = " << megaInstEnv->size()
00313          << endl;
00314 
00315   for (UocMap::iterator itr = UocInfo::ifList.begin();
00316       itr != UocInfo::ifList.end(); ++itr) {
00317     shared_ptr<UocInfo> puoci = itr->second;
00318     if ((puoci->flags & UOC_IS_MUTABLE) ||
00319        ((puoci->flags & UOC_SEEN_BY_INST) == 0)) {
00320       DEBUG(INST_ENV)
00321         cerr << "Importing Symbols from Interface: "
00322              << puoci->uocName << "."
00323              << endl;
00324 
00325       importSymBindings(puoci->env, megaEnv);
00326       importTSBindings(puoci->gamma, megaGamma);
00327       importInstBindings(puoci->instEnv, megaInstEnv);
00328       puoci->flags |= UOC_SEEN_BY_INST;
00329     }
00330   }
00331 
00332   for (UocMap::iterator itr = UocInfo::srcList.begin();
00333       itr != UocInfo::srcList.end(); ++itr) {
00334     shared_ptr<UocInfo> puoci = itr->second;
00335     if ((puoci->flags & UOC_IS_MUTABLE) ||
00336        ((puoci->flags & UOC_SEEN_BY_INST) == 0)) {
00337       DEBUG(INST_ENV)
00338         cerr << "Importing Symbols from Module: "
00339              << puoci->uocName << "."
00340              << endl;
00341 
00342       importSymBindings(puoci->env, megaEnv);
00343       importTSBindings(puoci->gamma, megaGamma);
00344       importInstBindings(puoci->instEnv, megaInstEnv);
00345       puoci->flags |= UOC_SEEN_BY_INST;
00346     }
00347   }
00348 }
00349 
00350 
00351 /*******************************************************************
00352                         NAME HANDLING
00353 *******************************************************************/
00354 
00355 shared_ptr<AST>
00356 UocInfo::lookupByFqn(const FQName& fqn, shared_ptr<UocInfo> &targetUoc)
00357 {
00358   targetUoc = GC_NULL;
00359 
00360 
00361   // Search all Interfaces and source modules serially for the AST
00362   // that is the definition of the FQN requested. If a definition is
00363   // found, we always try to return the definition. This is not just a
00364   // convenience, it is necessary for the instantiator. This is
00365   // because, we introduce the type qualifications for all
00366   // instantiated bindings, and if the definition and the declaration
00367   // differ in top level mutability at fn-arg-ret, if we start from
00368   // the type of the declaration, we might end up in a type
00369   // qualification that can never be satisfied.
00370 
00371   // Search the specified interface first:
00372   {
00373     UocMap::iterator itr = UocInfo::ifList.find(fqn.iface);
00374 
00375     if (itr != UocInfo::ifList.end()) {
00376       shared_ptr<UocInfo> uoc = itr->second;
00377 
00378       targetUoc = uoc;
00379       shared_ptr<AST> def = uoc->env->getBinding(fqn.ident);
00380 
00381       if (def) {
00382         assert(def->fqn == fqn);
00383 
00384         // If this is a declaration, then try to get the definition if
00385         // one exists, and return that.
00386         if (def->defn)
00387           def = def->defn;
00388         
00389         return def->defForm;
00390       }
00391     }
00392   }
00393 
00394   // Next all source modules
00395   for (UocMap::iterator itr = UocInfo::srcList.begin();
00396       itr != UocInfo::srcList.end(); ++itr) {
00397     shared_ptr<UocInfo> uoc = itr->second;
00398 
00399     if (uoc->uocName != fqn.iface)
00400       continue;
00401 
00402     targetUoc = uoc;
00403     shared_ptr<AST> def = uoc->env->getBinding(fqn.ident);
00404     if (def) {
00405       assert(def->fqn == fqn);
00406 
00407       if (def->defn)
00408         def = def->defn;
00409 
00410       return def->defForm;
00411     }
00412   }
00413 
00414   return GC_NULL;
00415 }
00416 
00417 // Get the Instantiated name for the polyinstantiated AST in the
00418 // new UOC. Ordinarily,
00419 // newName = _ + FQN.size() + FQN + # + typ->mangledString()
00420 //
00421 // However, Union constructors and vales are given type
00422 // based on the full union
00423 //
00424 // We must play a little trick on the mangled string, because we
00425 // always instantiate value-composite types to maximally mutable type.
00426 // IT IS NOT ENOUGH only to add a type-qualifier on the LHS with the
00427 // right mutability of the type, because the RHS being copy-compatible
00428 // will get instantiated to a different type ...
00429 
00430 static string
00431 getInstName(shared_ptr<const AST> def, shared_ptr<Type> typ)
00432 {
00433   stringstream ss;
00434   shared_ptr<Type> uAdjTyp = typ;
00435 
00436   if (typ->isUcon() || typ->isUval())
00437     uAdjTyp = typ->getUnionType();
00438 
00439   string fqnString = def->fqn.asString();
00440   ss << "_" << fqnString.size() << fqnString;
00441   ss << "#" << uAdjTyp->mangledString();
00442 
00443   DEBUG(INST)
00444     cerr << "New Name: " << ss.str()
00445          << " for " << def->s << " with type "
00446          << typ->asString()
00447          << endl;
00448 
00449   return ss.str();
00450 }
00451 
00452 // Namakaranam -- the ritual of giving a name
00453 #define NAMKARAN(ast, name) do {                \
00454     ast->s = name;                                \
00455     ast->flags |= IDENT_MANGLED;                \
00456   } while (0);
00457 
00458 // Rename an AST with its instantiated name
00459 void
00460 InstMangle(shared_ptr<AST> def)
00461 {
00462   NAMKARAN(def, getInstName(def, def->symType));
00463 }
00464 
00465 // In the case let-bindings, names (fqns) are not unique
00466 // So, in order to maintain a worklist, we form a
00467 // unique name based on the uniqueID of the AST, and
00468 // the mangled_string of the obtained by getInstName()
00469 static string
00470 uniqName(const string name, const shared_ptr<AST> def)
00471 {
00472   stringstream ss;
00473   ss << name;
00474   ss << def->ID;
00475   return ss.str();
00476 }
00477 
00478 // Fix the usage of any global definition to instead refer to its FQN
00479 // because that is what is in megaENVs
00480 static void
00481 name2fqn(shared_ptr<AST> ast)
00482 {
00483   switch(ast->astType) {
00484   case at_ident:
00485     {
00486       if (ast->flags & IDENT_MANGLED)
00487         break;
00488 
00489       if (!ast->symbolDef)
00490         break;
00491 
00492       if (!ast->symbolDef->isGlobal())
00493         break;
00494 
00495       ast->s = ast->symbolDef->fqn.asString();
00496       break;
00497     }
00498 
00499   case at_field:
00500   case at_methdecl:
00501     {
00502       name2fqn(ast->child(1));
00503       break;
00504     }
00505 
00506   case at_fqCtr:
00507   case at_sel_ctr:
00508   case at_select:
00509     {
00510       name2fqn(ast->child(0));
00511 
00512       // There is *NO* name2fqn of the field in the case of
00513       // at_sel_crt or at_fqCtr
00514       // This is because, because the original AST contains
00515       // unqualified names within type-records.
00516       // We only added fqns to the mega environment, with pointers to
00517       // the old unchanged ASTs.
00518       break;
00519     }
00520 
00521   case at_declares:
00522     {
00523       break;
00524     }
00525 
00526   case at_module:
00527     {
00528       assert(false);
00529       break;
00530     }
00531 
00532     // Special handling for switch unnecessary, if symbolDef is null
00533     // recursion stops.
00534   default:
00535     {
00536       for (size_t c = 0; c < ast->children.size(); c++)
00537         name2fqn(ast->child(c));
00538       break;
00539     }
00540   }
00541 }
00542 
00543 /*******************************************************************
00544                   MORE HELPER FUNCTIONS AND MACROS
00545 *******************************************************************/
00546 
00547 #define UNIFIED_ENVS GC_NULL
00548 
00549 // Warning: The following macros need local errStream
00550 #define RANDT_DROP(expr, mess, env) do {                \
00551     assert(RandTexpr(errStream, expr,                   \
00552                      POLY_SYM_FLAGS, POLY_TYP_FLAGS,    \
00553                      mess, false, env));                \
00554   } while (0);
00555 
00556 #define RANDT_COMMIT(expr, mess, env) do {              \
00557     assert(RandTexpr(errStream, expr,                   \
00558                      POLY_SYM_FLAGS, POLY_TYP_FLAGS,    \
00559                      mess, true, env));                 \
00560   } while (0);
00561 
00562 
00563 // Many a time, we will have to explicitely write (or re-write)
00564 // a type-qualification. This is a helper function to do that.
00565 // It gets type in AST form, and prepares it in the current context.
00566 static shared_ptr<AST>
00567 typeAsAst(shared_ptr<Type> t, const LexLoc& loc)
00568 {
00569   shared_ptr<AST> tAst = t->asAST(loc);
00570   name2fqn(tAst);
00571   return tAst;
00572 }
00573 
00574 // No constraints should survive after Polyinstantiation
00575 
00576 static void
00577 clearConstraints(shared_ptr<AST> ast)
00578 {
00579   switch(ast->astType) {
00580   case at_define:
00581   case at_recdef:
00582   case at_proclaim:
00583     assert(ast->child(2)->astType == at_constraints);
00584     ast->child(2)->children.clear();
00585     break;
00586 
00587   case at_declstruct:
00588   case at_declunion:
00589     assert(ast->child(5)->astType == at_constraints);
00590     ast->child(5)->children.clear();
00591     break;
00592 
00593   case at_defstruct:
00594   case at_defunion:
00595     assert(ast->child(5)->astType == at_constraints);
00596     ast->child(5)->children.clear();
00597     break;
00598 
00599   case at_defexception:
00600     break;
00601 
00602   case at_let:
00603   case at_letrec:
00604     assert(ast->child(2)->astType == at_constraints);
00605     ast->child(2)->children.clear();
00606     break;
00607 
00608   default:
00609     assert(false);
00610     break;
00611   }
00612 }
00613 
00614 // Substitute old name for new name; however, this substitution tries
00615 // to be a little more smart. If we see a typeapp whose first child
00616 // (the base type) is substituted, we replace the typeapp with the
00617 // type-name only. For example:
00618 //   (list 'a) -> list#int32.
00619 
00620 // This is a necessary step, and not a convenience that would
00621 // otherwise be handled by recinstantiate. The problem is that not all
00622 // typeapps in a definition can be removed, but the typeapps to the
00623 // currently specialized type _must_ be removed before it can be R&Ted
00624 // in the original environment.
00625 
00626 static shared_ptr<AST>
00627 substitute(shared_ptr<AST> ast, shared_ptr<AST> from, shared_ptr<AST> to)
00628 {
00629   switch(ast->astType) {
00630   case at_ident:
00631     {
00632       if (ast->symbolDef == from) {
00633         //assert((ast->flags & IDENT_MANGLED) == 0);
00634         if (ast->flags & IDENT_MANGLED) {
00635           std::cerr << "AST " << ast->s << " is mangled while "
00636                     << "substituting " << from->s 
00637                     << " <- " << to->s
00638                     << std::endl;
00639           
00640         }
00641         
00642         NAMKARAN(ast, to->s);
00643         ast->symbolDef = to;
00644       }
00645       return ast;
00646     }
00647 
00648   case at_typeapp:
00649     {
00650       if (ast->child(0)->symbolDef == from)
00651         return substitute(ast->child(0), from, to);
00652 
00653       for (size_t c = 0; c < ast->children.size(); c++)
00654         ast->child(c) = substitute(ast->child(c), from, to);
00655 
00656       return ast;
00657     }
00658 
00659   default:
00660     {
00661       for (size_t c = 0; c < ast->children.size(); c++)
00662         ast->child(c) = substitute(ast->child(c), from, to);
00663 
00664       return ast;
00665     }
00666   }
00667 }
00668 
00669 // Replace type variable usage with concrete types in the
00670 // instantiation
00671 static shared_ptr<AST>
00672 tvarSub(shared_ptr<AST> ast, shared_ptr<AST> tv, shared_ptr<Type> typ)
00673 {
00674   switch(ast->astType) {
00675   case at_ident:
00676     if (ast->symbolDef == tv)
00677       return typeAsAst(typ, ast->loc);
00678     else
00679       return ast;
00680 
00681   default:
00682     for (size_t c = 0; c < ast->children.size(); c++)
00683       ast->child(c) = tvarSub(ast->child(c), tv, typ);
00684     return ast;
00685 
00686   }
00687 }
00688 
00689 // ``Instantiate'' type variables scoped at
00690 //   the current letbinging to new type variables.
00691 static shared_ptr<AST>
00692 tvarInst(shared_ptr<AST> ast, shared_ptr<AST> scope, AstMap &newBinds)
00693 {
00694   switch(ast->astType) {
00695   case at_ident:
00696     {
00697       // We are only concerned with type variables
00698       // that are scoped at ``scope''
00699       if (!ast->isIdentType(id_tvar))
00700         return ast;
00701 
00702       shared_ptr<AST> def = ast->symbolDef;
00703 
00704       if (def->tvarLB != scope)
00705         return ast;
00706 
00707       AstMap::iterator itr = newBinds.find(def);
00708       if (itr != newBinds.end())
00709         return itr->second->Use();
00710 
00711       shared_ptr<Type> newTV = Type::make(ty_tvar);
00712       shared_ptr<AST> newTvAst = newTV->asAST(ast->loc,
00713                                    TvPrinter::make(false));
00714       newTvAst->symbolDef = newTvAst;
00715       newTvAst->flags |= TVAR_POLY_SPECIAL;
00716 
00717       newBinds[def] = newTvAst;
00718       return newTvAst;
00719     }
00720 
00721 
00722   case at_uswitch:
00723   case at_try:
00724     {
00725       for (size_t c = 0; c < ast->children.size(); c++)
00726         if (c != IGNORE(ast))
00727           ast->child(c) = tvarInst(ast->child(c), scope, newBinds);
00728       return ast;
00729     }
00730 
00731   default:
00732     {
00733       for (size_t c = 0; c < ast->children.size(); c++)
00734         ast->child(c) = tvarInst(ast->child(c), scope, newBinds);
00735       return ast;
00736     }
00737   }
00738 }
00739 
00740 // Coerce a non-concrete type to a more concrete type
00741 static void
00742 coerce(ostream &errStream, shared_ptr<Type> t, 
00743        bool maybeOnly=false)
00744 {
00745   DEBUG(INST)
00746     errStream << "COERCING "
00747               << t->asString(Options::debugTvP)
00748               << " to ";
00749   t->adjMaybe(Trail::make(), false, false, true);
00750   if(!maybeOnly)
00751     t->SetTvarsToUnit();
00752   DEBUG(INST)
00753     errStream << t->asString(Options::debugTvP)
00754               << endl;
00755 }
00756 
00757 
00758 // Build a new proclaimation for the new instantiation.
00759 // In the case of a value declaration, use typ to produce the type to
00760 // declare. In the case of struct/union declaration, build an empty
00761 // declaration where tvlist is empty. No constraints are ever emitted
00762 static shared_ptr<AST>
00763 buildNewDeclaration(shared_ptr<AST> def, shared_ptr<Type> typ)
00764 {
00765   shared_ptr<AST> ident = def->getID()->getDeepCopy();
00766 
00767   if (ident->externalName.size())
00768     ident->flags |= DEF_IS_EXTERNAL;
00769 
00770   // We must only proclaim globals
00771   assert(ident->isGlobal());
00772 
00773   NAMKARAN(ident, getInstName(ident, typ));
00774   shared_ptr<AST> decl = GC_NULL;
00775 
00776   switch(def->astType) {
00777   case at_define:
00778   case at_recdef:
00779   case at_proclaim:
00780   case at_defexception:
00781     decl = AST::make(at_proclaim, def->loc, ident,
00782                      typeAsAst(typ, ident->loc),
00783                      AST::make(at_constraints, def->loc));
00784     break;
00785 
00786   case at_declstruct:
00787     decl = AST::make(at_declstruct, def->loc, ident,
00788                      AST::make(at_tvlist, ident->loc),
00789                      AST::make(at_declares),
00790                      AST::make(at_fields),
00791                      AST::make(at_constraints, def->loc));
00792     break;
00793 
00794   case at_declunion:
00795     decl = AST::make(at_declunion, def->loc, ident,
00796                      AST::make(at_tvlist, ident->loc),
00797                      AST::make(at_declares),
00798                      AST::make(at_constructors),
00799                      AST::make(at_constraints, def->loc));
00800     break;
00801 
00802   default:
00803     assert(false);
00804     break;
00805   }
00806 
00807   DEBUG(INST)
00808     cerr << "Built new Declaration "
00809          << " for " << def->s << " with type "
00810          << typ->asString() << " as " << endl
00811          << decl->asString()
00812          << endl;
00813   return decl;
00814 }
00815 
00816 static shared_ptr<AST>
00817 getIDFromInstantiation(shared_ptr<AST> oldDefID, shared_ptr<AST> newDef)
00818 {
00819   shared_ptr<AST> oldDef = oldDefID->defForm;
00820 
00821   // If we are looking for a constructor, find it and return
00822   if ((oldDef->astType == at_defunion) && oldDefID->isUnionLeg()) {
00823     shared_ptr<AST> oldCtrs = oldDef->child(4);
00824     shared_ptr<AST> newCtrs = newDef->child(4);
00825     shared_ptr<AST> newCtr = GC_NULL;
00826     for (size_t c=0; c < oldCtrs->children.size(); c++)
00827       if (oldCtrs->child(c)->child(0) == oldDefID)
00828         newCtr = newCtrs->child(c)->child(0);
00829 
00830     assert(newCtr);
00831     return newCtr->Use();
00832   }
00833 
00834 
00835   // Normal case. We don't worry about methods any more
00836   return newDef->getID()->Use();        
00837 }
00838 
00839 // Qualify non-generalizing variable definitions with their type.
00840 static void
00841 propagate_type_annotations(shared_ptr<AST> ast)
00842 {
00843   switch(ast->astType) {
00844   case at_argVec:
00845     {
00846       for (size_t c=0; c < ast->children.size(); c++) {
00847         shared_ptr<AST> argPat = ast->child(c);
00848         shared_ptr<AST> arg = argPat->child(0);
00849         
00850         shared_ptr<AST> typeAST = typeAsAst(arg->symType,
00851                                             argPat->loc);
00852         
00853         if(ast->symType->CompFlags(c) & COMP_BYREF)
00854           typeAST = AST::make(at_byRefType, typeAST->loc, typeAST);
00855         
00856         if(argPat->children.size() == 2)
00857           argPat->child(1) = typeAST;
00858         else
00859           argPat->addChild(typeAST);
00860       }
00861       break;
00862     }
00863     
00864   case at_let:
00865   case at_letrec:
00866     break;
00867 
00868   default:
00869     for (size_t c=0; c < ast->children.size(); c++)
00870       propagate_type_annotations(ast->child(c));
00871     break;
00872   }
00873 }
00874 
00875 // Take in an identifier and return the symbol environment in which
00876 // that identifier is defined
00877 
00878 static shared_ptr<AST>
00879 getOuterLet(shared_ptr<AST> ast)
00880 {
00881   shared_ptr<AST> outerLet = GC_NULL;
00882   switch(ast->astType) {
00883   case at_ident:
00884     assert(!ast->symbolDef);
00885     assert(!ast->isGlobal());
00886     outerLet = ast->defForm->defForm->defForm;
00887     //     id    lb       lbs      let
00888     break;
00889 
00890   case at_letbinding:
00891     outerLet = ast->defForm->defForm;
00892     //    lb     lbs      let
00893     break;
00894 
00895   case at_letbindings:
00896     outerLet = ast->defForm;
00897     //    lbs    let
00898     break;
00899 
00900   default:
00901     assert(false);
00902     break;
00903   }
00904 
00905   assert(outerLet->astType == at_let ||
00906          outerLet->astType == at_letrec);
00907 
00908   return outerLet;
00909 }
00910 
00911 static shared_ptr<AST>
00912 getInnerLet(shared_ptr<AST> ast)
00913 {
00914   shared_ptr<AST> outerLet = getOuterLet(ast);
00915   shared_ptr<AST> innerLet = outerLet->child(1);
00916   assert(innerLet->astType == at_let ||
00917          innerLet->astType == at_letrec);
00918   return innerLet;
00919 }
00920 
00921 
00922 /*******************************************************************
00923                     The CORE POLYINSTANTIATOR
00924 *******************************************************************/
00925 
00926 /* Algorithm for new Polyinstantiator:
00927  *
00928  * 1) See if the desired identifier has been instantiated for the desired
00929  * type by searching the Unified-UOC environment. If found, just
00930  * return.
00931  *
00932  * 2) Examine the worklist whether we are in the process of instantiating
00933  * the current definition, if so emit a proclaimation, and exit.
00934  *
00935  * 3) Copy the incoming AST -- always copy the definition (rather than the
00936  * declaration) if one exists.
00937  *
00938  * 4) Mangle the name of the identifier being defined depending on the
00939  * desired type, and also change any recursive usages of the same name
00940  * within the current definition.
00941  *
00942  * ex: (define id#fn_bool_bool:(fn (bool) bool) (lambda (x) x))
00943  *
00944  * 5) Clamp the type of this AST to the desired type by introducing a
00945  * qualifier.
00946  *
00947  * ex, to instantiate id to (fn (bool) bool), we write:
00948  * (define id:(fn (bool) bool) (lambda (x) x))
00949  *
00950  * 6) Change the usage of any global identifiers to their FQNs since the
00951  * mega-Env contains the FQNs of all definitions.
00952  *
00953  * 7) R&T the new definition in the unified-UOC so that the types in
00954  * the body of the definition get clamped aiding further
00955  * instantiation. After successful R&T, throw away any changes to the
00956  * environment, as this definition is still in a "quasi" state.
00957  *
00958  * 8) Add the mangled name (id#fn_bool_bool) onto the worklist.
00959  *
00960  * 9) Recursively instantiate the body
00961  *
00962  * 10) After the current form has been completely instantiated, add it
00963  * to the target big-AST. Again R&T in the unified-UOC environment.
00964  *
00965  * 11) Remove the current definition from the worklist, exit.
00966  */
00967 
00969 //         Dealing with Type-classes and Constructors              //
00971 
00972 static shared_ptr<AST>
00973 getDefToInstantiate(ostream &errStream, shared_ptr<UocInfo> unifiedUOC,
00974                     shared_ptr<AST> def, shared_ptr<Type> typ)
00975 {
00976   // In the case of union constructors, we need to instantiate the
00977   // entire union type, the defForm field of all constructors point to
00978   // the entire defunion
00979 
00980   if (def->isUnionLeg())
00981     return def->defForm;
00982 
00983   // If this is a typeclass method, find an appropriate instance, get
00984   // the correct *identifier* representing (assumes instance-hoist)
00985   // the function to be used for this method-instance, and return
00986   // its defFrom (entire definition)
00987   //
00988   // But, the instance of a method could be satisfied by another
00989   // method (of the same or different type class). So, this process
00990   // must be repeated until we get an actual function.
00991 
00992   while (def->isTcMethod()) {
00993     // First look at the typeclass, get a copy of its type.
00994     shared_ptr<AST> typClass = def->defForm;
00995     shared_ptr<AST> tcID = typClass->child(0);
00996     shared_ptr<Typeclass> pred = tcID->scheme->type_instance();
00997 
00998     DEBUG(TC_INST)
00999       cerr << "Instantiating method " << def->s << " from TC " 
01000            << typClass->asString() << std::endl 
01001            << " over type " << typ->asString() << std::endl;
01002 
01003     // Then find out which method we are concerned about.
01004     size_t nthMethod = 0;
01005     bool found = false;
01006     for (size_t i = 0; i < pred->components.size(); i++) {
01007       shared_ptr<Type> ithMethod = pred->components[i]->typ->getType();
01008       if (ithMethod->defAst == def) {
01009         nthMethod = i;
01010         found = true;
01011         break;
01012       }
01013     }
01014     assert(found);
01015 
01016     // Unify the method's type with the necessary type (type at
01017     // current use).
01018     assert(pred->components[nthMethod]->typ->unifyWith(typ));
01019 
01020     // Now pred contains the properly specialized type. This should
01021     // have enough information to uniquely identify the instance we
01022     // must now instantiate. So, search for the (most) appripriate
01023     // instance among all the instances we have for the
01024     // current typeclass.
01025 
01026     shared_ptr<InstanceSet> insts =
01027       unifiedUOC->instEnv->getBinding(tcID->fqn.asString());
01028 
01029     InstanceSet::iterator matchingInstance;
01030 
01031     for (matchingInstance = insts->begin();
01032         matchingInstance != insts->end(); ++matchingInstance) {
01033       shared_ptr<Instance> currInst = (*matchingInstance);
01034       if (currInst->satisfies(pred, unifiedUOC->instEnv))
01035         break;
01036     }
01037 
01038     found = (matchingInstance != insts->end());
01039     assert(found);
01040 
01041     shared_ptr<AST> instAST = (*matchingInstance)->ast;
01042     shared_ptr<AST> theMethod = instAST->getInstanceMethod(def->s);
01043 
01044     // If an immediate lambda was present, then InstLamHoist hoisted
01045     // it and left us with an ID wrapped by a THE.
01046     assert (theMethod->astType == at_ident || theMethod->astType == at_typeAnnotation);
01047     if (theMethod->astType == at_typeAnnotation)
01048       theMethod = theMethod->child(0);
01049 
01050     // Finally, we have the instance we want to instantiate,
01051     // Set def to its defining occurence, and loop.
01052     def = theMethod->symbolDef;
01053   }
01054 
01055   // The natural case, just return my containing defining form
01056   // This returns:
01057   //   Top-level definition for globals
01058   //   The corresponding let-binding for locals
01059   return def->defForm;
01060 }
01061 
01063 //             Recursive Instantiation-propagator                  //
01065 
01066 
01067 // This function is the recursive walker to fix
01068 // the body of instantiated forms. This function must
01069 // *only* operate on the copied forms, and never the original
01070 
01071 shared_ptr<AST>
01072 UocInfo::recInstantiate(ostream &errStream,
01073                         shared_ptr<AST> ast,
01074                         bool &errFree,
01075                         WorkList<string>& worklist)
01076 {
01077   DEBUG(INST)
01078     cerr << "RecInstantiate: "
01079          << "[" << ast->atKwd() << "]"
01080          << ast->asString() << ": "
01081          << ((ast->symType) ?
01082              ast->symType->asString(Options::debugTvP) :
01083              "??")
01084          << endl;
01085 
01086   switch(ast->astType) {
01087   case at_ident:
01088     {
01089       // If Instantiate has already fixed this identifier, do nothing
01090       if (ast->flags & IDENT_MANGLED)
01091         break;
01092 
01093       // We should never be dealing with tvars because:
01094       // i) In the case of type definitions, all type-arguemnts are
01095       //    cleared
01096       // ii) In the case of type-qualifications in the case of value
01097       //    definitions, rec-instantiate is never called on the
01098       //    type-part. We alyays emit the type-AST by hand.
01099       assert(!ast->isIdentType(id_tvar));
01100 
01101       // We should only be handling use-occurences.
01102       // Defining occurences are handled by their respective container
01103       // ASTs -- local definitions here, and global definitions in
01104       // doInstantiate() function.
01105       shared_ptr<AST> def = ast->symbolDef;
01106       assert(def);
01107 
01108       // If this is a local defined at a non-let variable, whose name
01109       // I just fixed, fix the name of the use case, and do nothing.
01110       if (def->flags & LOCAL_NOGEN_VAR) {
01111         assert(def->flags & IDENT_MANGLED);
01112         NAMKARAN(ast, def->s);
01113         break;
01114       }
01115 
01116       // If the type is not concrete, fix it. The observation is that
01117       // all self uses of a recursive definition have already been
01118       // marked by Instantiate, and this use must be a use outside the
01119       // definition if IDENT_MANGLED is not set. So, there is no loss
01120       // of generality in fixing the use case.
01121       // In case of maybe Types, we can
01122       //    a) Just consider the core() part
01123       //    b) Pick any variant of the core(), in particular the
01124       //       minimally mutable one.
01125       //
01126       // FIX: Need to check that the type is not constrained, so that I
01127       //      can use unit as the placeholder value.
01128       // FIX: Sometime, change unit to some placeholder non-generalizable
01129       //      thing so that the user can be shown a tvar, rather than the
01130       //      unit
01131 
01132       if (!ast->symType->isConcrete())
01133         coerce(errStream, ast->symType);
01134 
01135       // Now that the identifier is a concrete instantiation,
01136       // (poly)instantiate it, and replace the use case with the
01137       // use of the (possibly) new AST.
01138       ast = doInstantiate(errStream, def, ast->symType,
01139                           errFree, worklist);
01140       break;
01141     }
01142 
01143   case at_typeapp:
01144     {
01145       for (size_t c = 0; c < ast->children.size(); c++)
01146         ast->child(c) = recInstantiate(errStream,
01147                                        ast->child(c),
01148                                        errFree, worklist);
01149 
01150       // There should be no typeapps in the polyinstantiated AST.
01151       ast = ast->child(0);
01152       break;
01153     }
01154 
01155   case at_methdecl:
01156     // FIX: instantiating at_methdecl may not be correct here.
01157   case at_labeledBlock:
01158   case at_return_from:
01159   case at_field:
01160     {
01161       ast->child(1) = recInstantiate(errStream,
01162                                      ast->child(1),
01163                                      errFree, worklist);
01164       break;
01165     }
01166 
01167   case at_select:
01168     {
01169       ast->child(0) = recInstantiate(errStream,
01170                                      ast->child(0),
01171                                      errFree, worklist);
01172       break;
01173     }
01174 
01175   case at_fqCtr:
01176   case at_sel_ctr:
01177     {
01178       ast->child(0) = recInstantiate(errStream,
01179                                      ast->child(0),
01180                                      errFree, worklist);
01181       ast->child(1) = recInstantiate(errStream,
01182                                      ast->child(1),
01183                                      errFree, worklist);
01184       break;
01185     }
01186 
01187   case at_inner_ref:
01188     {
01189       ast->child(0) = recInstantiate(errStream,
01190                                      ast->child(0),
01191                                      errFree, worklist);
01192 
01193       if (ast->flags & INNER_REF_NDX)
01194         ast->child(1) = recInstantiate(errStream,
01195                                        ast->child(1),
01196                                        errFree, worklist);
01197       break;
01198     }
01199 
01200   case at_declare:
01201     {
01202       if (ast->children.size() > 1)
01203         ast->child(1) = recInstantiate(errStream,
01204                                        ast->child(1),
01205                                        errFree, worklist);
01206       break;
01207     }
01208 
01209   case at_arrayType:
01210     {
01211       // Don't process the integer literal, the RHS is an integer
01212       // literal, it must not be type qualified.
01213       ast->child(0) = recInstantiate(errStream,
01214                                      ast->child(0),
01215                                      errFree, worklist);
01216       break;
01217     }
01218 
01219   case at_bitfieldType:
01220   case at_fill:
01221     {
01222       break;
01223     }
01224 
01225   case at_identPattern:
01226     {
01227       ast->child(0) = recInstantiate(errStream,
01228                                      ast->child(0),
01229                                      errFree, worklist);
01230 
01231       // Explicitely re-write EVERY type-qualification by hand.
01232       // Otherwise tvar-scoping will play havoc due to copy --
01233       // especially at let/letrec
01234       //
01235       // Need to be careful here about byref types: The byref
01236       // type goes on the function type, not on the identifier's type
01237       // Therefore, need to preserve by-ref AST qualifications as-is.
01238 
01239       if (ast->children.size() > 1) {
01240         shared_ptr<AST> typeAST = typeAsAst(ast->child(0)->symType,
01241                                             ast->child(1)->loc);
01242         if (ast->child(1)->astType == at_byRefType)
01243           ast->child(1) = AST::make(at_byRefType,
01244                                     typeAST->loc, typeAST);
01245         else
01246           ast->child(1) = typeAST;
01247 
01248         RANDT_DROP(ast->child(1), "[[IP R&T]]", UNIFIED_ENVS);        
01249         
01250         ast->child(1) = recInstantiate(errStream,
01251                                        ast->child(1),
01252                                        errFree, worklist);
01253       }
01254       break;
01255     }
01256 
01257   case at_typeAnnotation:
01258     {
01259       ast->child(0) = recInstantiate(errStream,
01260                                      ast->child(0),
01261                                      errFree, worklist);
01262 
01263       if (ast->child(0)->astType == at_typeAnnotation) {        
01264         // We already generated a qualified expression
01265         // See IntLit / FloatLit case
01266         assert(ast->child(0)->child(0)->astType == at_intLiteral ||
01267                ast->child(0)->child(0)->astType == at_floatLiteral);
01268         
01269         ast = ast->child(0);
01270         break;
01271       }
01272 
01273       ast->child(1) = typeAsAst(ast->child(0)->symType,
01274                                 ast->child(1)->loc);
01275 
01276       RANDT_DROP(ast->child(1), "[[TQ R&T]]", UNIFIED_ENVS);
01277 
01278       ast->child(1) = recInstantiate(errStream,
01279                                      ast->child(1),
01280                                      errFree, worklist);
01281       break;
01282     }
01283     
01284   case at_sizeof:
01285   case at_bitsizeof:
01286     {
01287       shared_ptr<AST> typAst = ast->child(0);
01288       if (!typAst->symType->isConcrete()) 
01289         coerce(errStream, typAst->symType);
01290 
01291       ast->child(0) = typeAsAst(typAst->symType, typAst->loc);
01292       ast->child(0) = recInstantiate(errStream, ast->child(0),
01293                                      errFree, worklist);
01294       break;
01295     }
01296 
01297   case at_floatLiteral:
01298   case at_intLiteral:
01299     {
01300       // Integer literals must have their types explicitely clamped
01301       // with a qualifier, we no longer deal with type classes after
01302       // this pass
01303       if (!ast->symType->isConcrete()) 
01304         coerce(errStream, ast->symType, true);
01305       
01306       assert(ast->symType->isConcrete());
01307 
01308       ast = AST::make(at_typeAnnotation, ast->loc, ast,
01309                       typeAsAst(ast->symType, ast->loc));
01310       RANDT_DROP(ast, "[[IntFloat R&T]]", UNIFIED_ENVS);
01311       break;        
01312     }
01313 
01314   case at_letStar:
01315     {
01316       assert(false);
01317       break;
01318     }
01319 
01320   case at_let:
01321   case at_letrec:
01322     {
01323       // Create a wrapper let expression, where the Instantiator will
01324       // fill in definitions. This let initially has empty bindings.
01325       // (an invalid AST), but we will shortly fix this.
01326 
01327       // (let[rec] (bindings) body constraints) is transformed into
01328       // (let[rec] (bindings) (let[rec] () body) constraints)
01329       // We will *not* carry over the constraints, these constraints
01330       // are automatiocally dropped when we finally declare the inner
01331       // let expression as "the" AST, and drop the outer wrapper.
01332 
01333       shared_ptr<AST> originalLbs = ast->child(0);
01334       shared_ptr<AST> originalExpr = ast->child(1);
01335 
01336       shared_ptr<AST> newLet = AST::make(ast->astType, ast->loc,
01337                             AST::make(at_letbindings,
01338                                     originalLbs->loc),
01339                             originalExpr,
01340                             AST::make(at_constraints,
01341                                     ast->child(2)->loc));
01342 
01343       shared_ptr<AST> newLbs = newLet->child(0);
01344       shared_ptr<AST> newExpr = newLet->child(1);
01345 
01346       // Actually rewrite the current expression
01347       ast->child(1) = newLet;
01348 
01349       // We re-built the let-expression, So, remark all defForms.
01350       findDefForms(ast, GC_NULL, ast->defForm);
01351 
01352       DEBUG(INST)
01353         errStream << "recInstantiate: WrappedLet =  "
01354                   << endl
01355                   << ast->asString()
01356                   << endl;
01357 
01358       newLet->child(1) = recInstantiate(errStream, newExpr,
01359                                         errFree, worklist);
01360       newExpr = newLet->child(1);
01361 
01362       // We need to carry-forward any non-polymorphic expression for
01363       // the sake of their (possible) side-effects.
01364       // We must not carry-forward everything because we must remove
01365       // all polymorphism and qualifications/constraints here.
01366       // Since no non-value can be polymorphic, this check will ensure
01367       // that we do not drop any state change.
01368       for (size_t i=0; i < originalLbs->children.size(); i++) {
01369         shared_ptr<AST> lb = originalLbs->child(i);
01370         shared_ptr<AST> ident = lb->child(0)->child(0);
01371         if (ident->symType->isConcrete()) {
01372           // Instantiate this definition, it will automatically get
01373           // added to the inner let, so we just drop the use
01374           // case identifier returned by doInstantiate().
01375           doInstantiate(errStream, ident, ident->symType,
01376                         errFree, worklist);
01377         }
01378       }
01379 
01380       // Declare the inner let-expression as "the" let-expression.
01381       // In case after instantiation, it so happens that no
01382       // let-bindings are carried forward, just drop the
01383       // let-expression, and return the let-body.
01384       if (newLbs->children.size() > 0)
01385         ast = newLet;
01386       else
01387         ast = newExpr;
01388       break;
01389     }
01390 
01391   case at_letbindings:
01392   case at_letbinding:
01393     {
01394       assert(false);
01395       break;
01396     }
01397 
01398 
01399     // We have already handled defining occurences of let-bound
01400     // identifiers. Now, we need to deal with other forms of local
01401     // definitions like:
01402     // - Lambda binding parameters (not generalized)
01403     // - Identifiers being defined at switch, case, do, (not
01404     //   generalized)
01405     //
01406     // These are as concrete as that fixed by the outer
01407     // containing form. There is no way use orrurences can have a
01408     // diferent type than the original, Fix their name and do
01409     // nothing.
01410     //
01411     // However, this must be done on a per-case basis because, if we
01412     // rename the defining occurence, we must **immediately** rename
01413     // all the use-cases before an R&T is done. Since parts of a
01414     // single global definition are R&Ted potentially many times due
01415     // to R&Ts of let-bindings, we must always keep the namespace
01416     // clean.
01417     //
01418     // In theory, it may be OK to not do this because we leave
01419     // environments intact many-a-time, even though we mangle
01420     // ASTs. But this method seems cleaner, and its advantages are
01421     // better redability of dumps, and ability to track all defining
01422     // occurence changes.
01423     //
01424     // Once we do this update, it is important also to update the key
01425     // in the corresponding environments because we are not R&Ting
01426     // here. It creates other problems as we are still in the process
01427     // of recursive-changes over the definition.
01428 
01429   case at_lambda:
01430     {
01431       shared_ptr<AST> args = ast->child(0);
01432       shared_ptr<AST> body = ast->child(1);
01433 
01434       for (size_t c=0; c < args->children.size(); c++) {
01435         shared_ptr<AST> argPat = args->child(c);
01436         shared_ptr<AST> arg = argPat->child(0);
01437         string oldName = arg->s;
01438 
01439         arg->flags |= LOCAL_NOGEN_VAR;
01440         NAMKARAN(arg, getInstName(arg, arg->symType));
01441         ast->envs.updateKey(oldName, arg->s);
01442         
01443         substitute(body, arg, arg); 
01444         
01445         shared_ptr<AST> typeAST = typeAsAst(arg->symType,
01446                                             argPat->loc);
01447         // No need to RANDT the new type AST generated here, it will
01448         // be handled in the identPattern case in the following
01449         // recInstantiate calls. 
01450         
01451         if(args->symType->CompFlags(c) & COMP_BYREF)
01452           typeAST = AST::make(at_byRefType, typeAST->loc, typeAST);
01453         
01454         if(argPat->children.size() == 2)
01455           argPat->child(1) = typeAST;
01456         else
01457           argPat->addChild(typeAST);
01458         
01459       }
01460       
01461       ast->child(0) = recInstantiate(errStream, args,
01462                                      errFree, worklist);
01463       ast->child(1) = recInstantiate(errStream, body,
01464                                      errFree, worklist);
01465       break;
01466     }
01467 
01468   case at_loopbinding:
01469     {
01470       // init and update
01471       for (size_t c = 1; c < ast->children.size(); c++)
01472         ast->child(c) = recInstantiate(errStream,
01473                                        ast->child(c),
01474                                        errFree, worklist);
01475       break;
01476     }
01477 
01478   case at_loop:
01479     {
01480       shared_ptr<AST> loopBds = ast->child(0);
01481       shared_ptr<AST> loopTest = ast->child(1);
01482       shared_ptr<AST> loopExprs = ast->child(2);
01483 
01484       for (size_t c = 0; c < loopBds->children.size(); c++) {
01485         shared_ptr<AST> loopBd = loopBds->child(c);
01486         shared_ptr<AST> local = loopBd->child(0)->child(0);
01487 
01488         string oldName = local->s;
01489         local->flags |= LOCAL_NOGEN_VAR;
01490         NAMKARAN(local, getInstName(local, local->symType));
01491         ast->envs.updateKey(oldName, local->s);
01492 
01493         for (size_t d = 0; d < loopBds->children.size(); d++) {
01494           shared_ptr<AST> update = loopBds->child(d)->child(2);
01495           substitute(update, local, local);
01496         }
01497         substitute(loopTest, local, local);
01498         substitute(loopExprs, local, local);
01499       }
01500 
01501       for (size_t c = 0; c < ast->children.size(); c++)
01502         ast->child(c) = recInstantiate(errStream,
01503                                        ast->child(c),
01504                                        errFree, worklist);
01505 
01506       break;
01507     }
01508 
01509   case at_usw_leg:
01510   case at_otherwise:
01511     {
01512       shared_ptr<AST> local = ast->child(0);
01513       shared_ptr<AST> expr = ast->child(1);
01514       string oldName = local->s;
01515       local->flags |= LOCAL_NOGEN_VAR;
01516       NAMKARAN(local, getInstName(local, local->symType));
01517       ast->envs.updateKey(oldName, local->s);
01518       substitute(expr, local, local); 
01519 
01520       // expr and all constructors
01521       for (size_t c = 1; c < ast->children.size(); c++)
01522         ast->child(c) = recInstantiate(errStream,
01523                                        ast->child(c),
01524                                        errFree, worklist);
01525       break;
01526     }
01527 
01528   case at_uswitch:
01529   case at_try:
01530     {
01531       for (size_t c = 0; c < ast->children.size(); c++)
01532         if (c != IGNORE(ast))
01533           ast->child(c) = recInstantiate(errStream,
01534                                          ast->child(c),
01535                                          errFree, worklist);
01536       break;
01537     }
01538 
01539   default:
01540     {
01541       // Obviously,
01542       for (size_t c = 0; c < ast->children.size(); c++)
01543         ast->child(c) = recInstantiate(errStream,
01544                                        ast->child(c),
01545                                        errFree, worklist);
01546       break;
01547     }
01548   }
01549 
01550   DEBUG(INST)
01551     cerr << "##" << "[" << ast->atKwd() << "]"
01552          << " RecInstantiated to: " << ast->asString()
01553          << " with type "
01554          << ((ast->symType != NULL)?ast->symType->asString(Options::debugTvP):"??") << endl;
01555 
01556   return ast;
01557 }
01558 
01559 
01561 //                        THE Instantiator                         //
01563 
01564 // Specialize the input AST /def/ according to the supplied concrete
01565 // type /typ/ and emit the resulting, renamed AST to outUOC.
01566 shared_ptr<AST>
01567 UocInfo::doInstantiate(ostream &errStream,
01568                        shared_ptr<AST> ast,
01569                        shared_ptr<Type> typ,
01570                        bool &errFree,
01571                        WorkList<string>& worklist)
01572 {
01573   // INPUT: /ast/ is the *defining* occurence of an identifier whise
01574   //        definition must be instantiated to the type /typ/
01575   //
01576   // OUTPUT: *Use* occurence of the instantiated identifier.
01577   //
01578   // SIDE-EFFECTS: The instantiated definition (defForm) is added
01579   //               to the output AST
01580   assert(ast->astType == at_ident);
01581   assert(!ast->symbolDef);
01582 
01583   // getDefToInstantiate returns the correct
01584   // definition to instantiate. ex: In the case of
01585   // constructors, entire union must be instantiated. Special
01586   // handling is necessary for methods, etc.
01587   shared_ptr<AST> def = getDefToInstantiate(errStream, shared_from_this(), ast, typ);
01588 
01589   assert((def->astType != at_deftypeclass) ||
01590          (def->astType == at_definstance));
01591 
01592   DEBUG(INST)
01593     cerr << "To Instantiate: " << def->asString()
01594          << " for type " << typ->asString() << endl;
01595 
01596   // Chase down any unification:
01597   //         keep mutability, maybes don't matter
01598   typ = typ->getTheType(true, false);
01599 
01600   // In the case of value-type-definitions, increase the
01601   // mutability-permissibility of all type-arguments to the maximum
01602   // possible extent. However, we must shed the outermost mutable
01603   // wrapper that will be produced by mazimizeMutability.
01604   //
01605   // Consideration: Should we mazimize mutability in the case of value
01606   // definitions also?
01607   // **NO** IF AT ALL POSSIBLE. This will increase closure coversion
01608   // as everything is mutable, and is only useful if a polymnorphic
01609   // definition is used polymorphically wrt mutability beyond shallow
01610   // mutability (since we catch thich case in the type-system).
01611   if (def->astType == at_defstruct || def->astType == at_defunion) {
01612     typ = typ->getDCopy()->maximizeMutability();
01613     typ = typ->getBareType();
01614 
01615     DEBUG(INST)
01616       cerr << "Type after maximizeMutability = "
01617            << typ->asString() << endl;
01618   }
01619 
01620   // We always specialize to some concrete type
01621   assert(typ->isConcrete());
01622 
01623   // We can only specialize defining forms
01624   shared_ptr<AST> defIdent = def->getID();
01625   assert(defIdent);
01626 
01627   // Make sure we don't mangle any identifier twice. We should never
01628   // be called for the use of an identifier we have already processed
01629   assert((defIdent->flags & IDENT_MANGLED) == 0);
01630 
01631   // Are we instantiating a local, or a global?
01632   // There is ont thing we must remember about the difference between
01633   // instantiating a local and instantiating a global.
01634   //
01635   // GLOBAL: The input definition is the original AST. Therefore, we
01636   // must never touch it directly. Also, the environment attached on
01637   // this AST is the original environment (not a part of the
01638   // unifiedUOC).
01639   //
01640   // LOCAL: The input AST is a let-binding, which is a part of a copy
01641   // of another global AST which has already been instantiated. This
01642   // AST has already been (quasily) R&Ted in the unifiedUOC (see the
01643   // working of this function).
01644   bool globalInst = true;
01645   if (!defIdent->isGlobal())
01646     globalInst = false;
01647 
01648 
01649   // If we are trying to instantiate a declaration,
01650   // try instantiating the definition if one exists.
01651   //
01652   // This must be performed as the first step because the definitions
01653   // and declarations can differ in mutability at the fn-arg-ret
01654   // positions, and hence mangled string() will produce different
01655   // names. This is actually bad because there might be other things
01656   // that rely on the mangledString(), and we must revisit
01657   // fn-compatibility and then generate mangledString()s based on the
01658   // outside type of a function
01659 
01660   if (defIdent->defn) {
01661     assert(globalInst);
01662     defIdent = defIdent->defn;
01663     def = defIdent->defForm;
01664     DEBUG(INST)
01665       cerr << "Definition found, will instantiate: "
01666            << def->asString() << endl;
01667   }
01668 
01669   // Now, we know all we can, about ident and def wrt the
01670   // whole program. If def is still a declation, there is
01671   // *globally* no definition available for it.
01672 
01673   // Get the new name to which this definition will be
01674   // instantiated.
01675   string newName = getInstName(defIdent, typ);
01676   // Get a globally unique working-name to deal with the
01677   // worklist. This name is based on the uniqueID of the AST def, and
01678   // is globally unique even wrt local definitions.
01679   string wkName = uniqName(newName, def);
01680 
01681   // See if we have already instantiated this AST for this type
01682   // before. If so, that AST must be in my environment,
01683   // just return it.
01684   //
01685   // GLOBALS: Search in the UnifiedUOC (my) environment.
01686   //          DO NOT search in the AST's environment, that is the
01687   //          original environment.
01688   //
01689   // LOCALS:  Search the let-bindings in the inner let to see if we
01690   //          already have an instantiation.
01691   //          Don't search the environment saved as part of the
01692   //          corresponding let AST's environment. The let-binding is
01693   //          R&Ted independent of the let-wrapper. There is no
01694   //          environment there.
01695 
01696   shared_ptr<AST> alreadyInstantiated = GC_NULL;
01697   if (globalInst)
01698     alreadyInstantiated = env->getBinding(newName);
01699   else {
01700     shared_ptr<AST> innerLet = getInnerLet(defIdent);
01701     shared_ptr<AST> innerLbs = innerLet->child(0);
01702     for (size_t c=0; c < innerLbs->children.size(); c++) {
01703       shared_ptr<AST> id = innerLbs->child(c)->getID();
01704       if (id->s == newName)
01705         alreadyInstantiated = id;
01706     }
01707   }
01708 
01709   DEBUG(INST)
01710     if (!alreadyInstantiated) {
01711       errStream << "No existing instantiation found for "
01712                 << newName;
01713       if (!globalInst)
01714         errStream << " in Local Env of "
01715                   << endl
01716                   << getInnerLet(defIdent)->asString();
01717 
01718       errStream << endl;
01719     }
01720 
01721   // If an instantiation is already found, return a use ast of the
01722   // corresponding identifier.
01723   if (alreadyInstantiated)
01724     return getIDFromInstantiation(ast, alreadyInstantiated->defForm);
01725 
01726   // If I am within the worklist, emit a declaration at this
01727   // point. This is necessary to ensure that mutually recursive
01728   // instantiations do not loop for ever
01729 
01730   if (worklist.contains(wkName)) {
01731 
01732     // In the case of local definitions (within a letrec), we cannot
01733     // emit a declaratin. Instead, make up an identifer AST with the
01734     // correct name and return it to the caller. This will all work
01735     // out when the corresponding let-binding will get instantiated
01736     // some day.
01737     if (!globalInst) {
01738       shared_ptr<AST> res = ast->getDeepCopy();
01739       res->symbolDef = GC_NULL;
01740       NAMKARAN(res, newName);
01741 
01742       DEBUG(INST)
01743         errStream << "LOCAL definition "
01744                   << wkName << " is present in the workist, "
01745                   << " returning " << newName
01746                   << endl;
01747       return res;
01748     }
01749 
01750     // If we are instantiating a union because of a constructor, we
01751     // cannot be still in the process of defining it, because the
01752     // type-definition must be complete before constructors can be
01753     // used. So, make sure we are OK.
01754     assert(!ast->isUnionLeg());
01755 
01756     // Get the proclaimation / declType
01757     shared_ptr<AST> newDecl = buildNewDeclaration(def, typ);
01758 
01759     // Marking done wrt my UOC.
01760     findDefForms(newDecl);
01761 
01762     // This new Declaration can never contain the name being
01763     // defined. So, no immediate fixup necessary.
01764     // Safe to R&T in MEGA environment.
01765     RANDT_DROP(newDecl, "[[InstDecl: R&T-1]]", UNIFIED_ENVS);
01766 
01767     // In the case of a proclaimation, I need to recurse over
01768     // the type-part and instantiate any types if necessary.
01769     // It is safe to recurse as there are no self references.
01770     // No constraints are ever emitted.
01771     if (newDecl->astType == at_proclaim)
01772       newDecl->child(1) = recInstantiate(errStream,
01773                                          newDecl->child(1),
01774                                          errFree, worklist);
01775 
01776     // Now that the declaration is fixed up -- if necessary --
01777     // R&T it (in my enviromment) and commit the AST.
01778     RANDT_COMMIT(newDecl, "[[InstDecl: R&T-2]]", UNIFIED_ENVS);
01779 
01780     // Actually add the declaration AST
01781     addTopLevelForm(newDecl);
01782 
01783     // Done with the declaration, somebody, please emit the definition
01784     // later.
01785     return newDecl->getID()->Use();
01786   }
01787 
01788   // If we reach  here, we have never seen this definition before, so,
01789   // need to really instantiate it. So, add this definition to the
01790   // worklist and mark that we are on it.
01791   worklist.insert(wkName);
01792 
01793 
01794   // Make a copy of the definition, make a true-copy, we need the
01795   // symbolDefs to still point to the old ones so that substitute
01796   // works correctly.
01797   shared_ptr<AST> copy = def->getTrueCopy();
01798 
01799 #if 0
01800   if(copy->astType == at_define || copy->astType == at_recdef) {
01801     shared_ptr<AST> ip = copy->child(0);
01802     assert(ip->astType == at_identPattern);
01803     shared_ptr<AST> typAST = typeAsAst(typ, copy->loc);
01804 
01805     if (ip->children.size() > 1)
01806       ip->child(1) = typAST;        
01807     else
01808       ip->children.push_back(typAST);        
01809     
01810   }
01811 #endif
01812 
01813   shared_ptr<AST> copyIdent = copy->getID();
01814   NAMKARAN(copyIdent, newName);
01815 
01816   // Then, within the current definition, replace all references to the
01817   // definition, with references to the copy.
01818   // This step **MUST** be done before clamping the AST with the type
01819   // annotation.
01820   copy = substitute(copy, defIdent, copyIdent);
01821 
01822   // and adjust the defForms and constraints in the new AST.
01823   if (globalInst) {
01824     findDefForms(copy); // Marking done wrt my UOC.
01825     clearConstraints(copy);
01826   }
01827   else {
01828     // In the case of local-instantiation, it is safe to
01829     // traverse defForm upwards
01830     shared_ptr<AST> copyTopExpr = ((globalInst) ? copy :
01831                         copy->defForm->defForm->defForm);
01832     //lb    lbs      let      define
01833 
01834     findDefForms(copy, copy->defForm, copyTopExpr);
01835     // constraints are dealt with in recInstantiate itself.
01836   }
01837 
01838   // Clamp the type of this definition based on typ. This must be done
01839   // on a per ASTtype basis
01840   // In the case of local instantiation, we actually will add the
01841   // letbinding to the AST here, before we RandT for the first time.
01842   switch(copy->astType) {
01843   case at_define:
01844   case at_recdef:
01845   case at_letbinding:
01846     {
01847       // For a definition, fix the type by emitting a concrete type
01848       // qualification in its identPattern. If the user has written
01849       // one, overwrite it. The type obtained from the type record is
01850       // at least as precise what the user wrote
01851 
01852       shared_ptr<AST> ip = copy->child(0);
01853       assert(ip->astType == at_identPattern);
01854       shared_ptr<AST> typAST = typeAsAst(typ, copy->loc);
01855       if (ip->children.size() > 1)
01856         ip->child(1) = typAST;        
01857       else
01858         ip->children.push_back(typAST);        
01859 
01860       if (!globalInst) {
01861         // In the case of local definitions, we add the copied
01862         // letbinding into the *inner* let-form (see recInstantiate
01863         // at_let/at_letrec case).
01864         // ex:(define top
01865         //      (let ((id (lambda (x) x)))
01866         //        (let ((id#fn_bool_bool (lambda (x) x))) ...)))
01867         assert(copy->astType == at_letbinding);
01868         shared_ptr<AST> innerLet = getInnerLet(copy);
01869         shared_ptr<AST> innerLbs = innerLet->child(0);
01870         innerLbs->children.push_back(copy);
01871 
01872         // We also need to fixup any references to
01873         // type-variables scoped at the current let-binding.
01874         // For example:
01875         // (let ((l (lambda (x:'a) #f)))
01876         //       (l #t)))
01877         // Here, we must not generate
01878         //   (let ((l#fn_4bool_4bool (lambda (x:'a) #f)))
01879         // as the inner let-binding because it will clamp the
01880         // generalizable type variable 'a.
01881         // This will result in a RIGID type variable unification
01882         // error. Therefore, we need to rename all variables that are
01883         // scoped at this let-bindings.
01884 
01885         AstMap newBinds;
01886         tvarInst(copy, getOuterLet(copy)->child(0), newBinds);
01887       }
01888 
01889       break;
01890     }
01891 
01892   case at_proclaim:
01893     {
01894       // Rewrite the type provided by the user, to the type desired.
01895       copy->child(1) = typeAsAst(typ, copy->child(1)->loc);
01896       break;
01897     }
01898 
01899   case at_defexception:
01900     {
01901       break;
01902     }
01903 
01904   case at_declstruct:
01905   case at_declunion:
01906     {
01907       // Even less work here, remove any type variables, and we are
01908       // done (possibly polymorphic -> concrete).
01909       copy->child(1)->children.clear();
01910       break;
01911     }
01912 
01913   case at_defstruct:
01914     {
01915       // First the new definition is concrete, remove
01916       // type-variables.
01917       copy->child(1)->children.clear();
01918 
01919       // We happily replaced the use of old name with new name and
01920       // removed type-variables. But there may be typeapps in the
01921       // fields, and old tvars must now refer to concrete types. So,
01922       // fix that before recursing over the fields.
01923 
01924       shared_ptr<AST> defTvList = def->child(1);
01925       assert(typ->typeArgs.size() == defTvList->children.size());
01926       shared_ptr<AST> copyFields = copy->child(4);
01927       for (size_t i=0; i < defTvList->children.size(); i++) {
01928         shared_ptr<AST> defTv = defTvList->child(i);
01929         shared_ptr<Type> arg = typ->TypeArg(i);
01930         for (size_t j=0; j < copyFields->children.size(); j++) {
01931           shared_ptr<AST> copyField = copyFields->child(j);
01932           if (copyField->astType == at_fill)
01933             continue;
01934           copyField->child(1) =  tvarSub(copyField->child(1),
01935                                          defTv, arg);
01936         }
01937       }
01938       break;
01939     }
01940 
01941   case at_defunion:
01942     {
01943       copy->child(1)->children.clear();
01944 
01945       shared_ptr<AST> defTvList = def->child(1);
01946       assert(typ->typeArgs.size() == defTvList->children.size());
01947 
01948       shared_ptr<AST> copyCtrs = copy->child(4);
01949       for (size_t j=0; j < copyCtrs->children.size(); j++) {        
01950         shared_ptr<AST> copyCtr = copyCtrs->child(j);
01951         
01952         // Unions are a little more complicated. We must:
01953         // i)  Fix the name of the constructor with the new name
01954         //     according to the new union we created
01955         // ii) Fix tvars of the fields of the constructor
01956         shared_ptr<AST> copyCtrID = copyCtr->child(0);
01957         NAMKARAN(copyCtrID, getInstName(copyCtrID, typ));
01958 
01959         for (size_t i=0; i < defTvList->children.size(); i++) {
01960           shared_ptr<AST> defTv = defTvList->child(i);
01961           shared_ptr<Type> arg = typ->TypeArg(i);
01962 
01963           for (size_t k=1; k < copyCtr->children.size(); k++) {
01964             shared_ptr<AST> copyField = copyCtr->child(k);
01965             if (copyField->astType == at_fill)
01966               continue;
01967         
01968             copyField->child(1) =  tvarSub(copyField->child(1),
01969                                            defTv, arg);
01970           }
01971         }
01972       }
01973       break;
01974     }
01975 
01976    default:
01977     assert(false);
01978     break;
01979   }
01980 
01981   // Now, replace use of any global identifiers with their FQNs
01982   // because the mega-ENV only recognizes definitions by their FQNs.
01983   // This step **MUST** be done after clamping the AST with the type
01984   // annotation.
01985   name2fqn(copy);
01986 
01987   // At this point, the entire definition must be a valid AST. So, we
01988   // will type the new definition. However, since this definition is
01989   // still in "quasi" state, call R&T with a note that changes should
01990   // be thrown away. The only purpose of this R&T is that the types of
01991   // rest of the expression is unchanged, and we can recurse over the
01992   // expression body an instantiate any dependencies properly
01993 
01994   DEBUG(INST)
01995     cerr << "Copy after name fixup: " << copy->asString() << endl;
01996 
01997   shared_ptr<EnvSet> envset = (globalInst ? UNIFIED_ENVS
01998                                :
01999                                (EnvSet::make(getOuterLet(copy)->envs)));
02000 
02001   RANDT_DROP(copy, "[[Inst: R&T-1: ]]", envset);
02002   
02003   // The type inference system can potentially perform some AST re-writes 
02004   // For example, in the case of method calls. These re-writes will
02005   // interfere with instantiator's own re-writes since they proceed in
02006   // parallel. Therefore, we must ensure that all inference re-writes
02007   // are completed by the time instantiator re-writes begin. Since all
02008   // types are comcrete at this stage, this serialization of re-writes
02009   // is possible. However, for this to happen correctly, we must
02010   // propagate annotations on to non-generalizing defining forms and
02011   // R&T again. Otherwise, not all re-writes would have happened yet.
02012   propagate_type_annotations(copy);
02013   RANDT_DROP(copy, "[[Inst: R&T-2: ]]", envset);
02014   
02015   DEBUG(INST)
02016     cerr << "Copy after name fixup, R&T: " << copy->asString() << endl;
02017   
02018   // Now that the expression is typed, recurse over the body and
02019   // process dependencies
02020 
02021   switch(copy->astType) {
02022   case at_define:
02023   case at_recdef:
02024   case at_letbinding:
02025     {
02026       // Instantiate any types in the qualification we just emitted
02027       shared_ptr<AST> ip = copy->child(0);
02028       ip->child(1) = recInstantiate(errStream,
02029                                     ip->child(1),
02030                                     errFree, worklist);
02031 
02032 
02033       // Attend to any instantiations necessary in the body of this
02034       // definition
02035       copy->child(1) = recInstantiate(errStream,
02036                                       copy->child(1),
02037                                       errFree, worklist);
02038       
02039       break;
02040     }
02041 
02042   case at_proclaim:
02043     {
02044       // Nothing much to do, just recurse over the type specifier
02045       copy->child(1) = recInstantiate(errStream,
02046                                       copy->child(1),
02047                                       errFree, worklist);
02048       break;
02049     }
02050 
02051   case at_declstruct:
02052   case at_declunion:
02053     {
02054       // Even less work here
02055       break;
02056     }
02057 
02058   case at_defunion:
02059   case at_defstruct:
02060   case at_defexception:
02061     {
02062       shared_ptr<AST> copyFieldsCtr = copy->child(4);
02063       copy->child(4) = recInstantiate(errStream,
02064                                       copyFieldsCtr,
02065                                       errFree, worklist);
02066       break;
02067     }
02068 
02069   default:
02070     assert(false);
02071     break;
02072   }
02073 
02074   if (globalInst) {
02075     // Now we have the newly instantiated AST to be added to our
02076     // environment. Before that, perform some cleanup in order to
02077     // eliminate any references to the old module.
02078     copy->getID()->decl = GC_NULL;
02079     copy->getID()->defn = GC_NULL;
02080 
02081     // FINALLY, add the new form to my UOC in the case
02082     addTopLevelForm(copy);
02083 
02084     // R&T in my UOC to make sure everything is OK. This will also add
02085     // the copy to the environment so that further calls can just use
02086     // this one.
02087     DEBUG(INST)
02088       cerr << "Copy after all fixup: " << copy->asString() << endl;
02089     RANDT_COMMIT(copy, "[[Inst: R&T-COMMIT]]", UNIFIED_ENVS);
02090   }
02091   // No ned for RandT in the case of local definitions
02092   // (let-bindings).
02093 
02094   // Now that we are (almost) done, remove current entry from the
02095   // worklist so that we are really done
02096   worklist.erase(wkName);  
02097   DEBUG(INST)
02098     cerr << "Instantiated: " << def->asString()
02099          << " for type " << typ->asString() << endl
02100          << " to " << copy->asString();
02101 
02102   // Now that we have instantiated the definition completely, we must
02103   // return a *use case* of the identifier for which we instantiated.
02104   // getIDFromInstantiation() does just that, with special attention
02105   // to the constructor case, where we have to return the constructor
02106   // ident's use instead
02107   return getIDFromInstantiation(ast, copy);
02108 }
02109 
02110 /* Things to remember:
02111    1) If we see a proclaimation that has a definition,
02112    we will only emit the definition. Here, we are relying on the
02113    fact that any externalNames hve already been propagated to the
02114    definitions (by the resolver), and that getDCopy() preserves
02115    externalNames.
02116 
02117    2) Suppose one defined a union type as:
02118 
02119    (defstruct (st 'a) a:'b)
02120    (defunion (unin 'a) nil)
02121 
02122    and if we see the definition
02123    (define (main argv:(vector string)))
02124    nil:(unin (st int32)) 0:int32)
02125 
02126    nil and this unin must be specialized for (st int32).
02127 
02128    But, after this substitution, the new unin ast will look like:
02129    (defunion _4unin#UR_SR_3st_5int32 _3nil#UR_SR_3st_5int32)
02130 
02131    3) Here are some old notes when we were dealing with type-variables
02132    in value definitions in rec-Instantiate:
02133    The first time we see a type-variable in an expression, it
02134    arbitrarily choosen as the defining occurence. But, it must
02135    also be considered as a use occurence.
02136    if (ast == def)
02137    assert(def->isIdentType(id_tvar));
02138    Type variables could have been present at defining occuernces in
02139    this case.
02140 
02141    4) It is generaly a good idea only to R&T at specific points:
02142    entire top-level form, and a particular let-binding when no
02143    generalization is involved. */
02144 
02145 
02146 
02147 /*******************************************************************
02148                     TOP_LEVEL INTERFACE FUNCTIONS
02149 *******************************************************************/
02150 
02151 bool
02152 UocInfo::instantiateFQN(ostream &errStream, const FQName& epName)
02153 {
02154   bool errFree = true;
02155   shared_ptr<UocInfo> targetUoc = GC_NULL;
02156   shared_ptr<AST> def = UocInfo::lookupByFqn(epName, targetUoc);
02157 
02158   if (!def) {
02159     errStream << "bitcc: Entry point \"" << epName
02160               << "\" not found.\n";
02161     return false;
02162   }
02163   else if (!def->symType->isConcrete()) {
02164     errStream << "Non-concrete procedure \"" << epName
02165               << "\" defined at "
02166               << def->loc
02167               << " cannot be used as an entry point.\n";
02168     return false;
02169   }
02170 
02171   shared_ptr<AST> defIdent = def->getID();
02172 
02173   DEBUG(INST) {
02174     INOstream ino(cerr);
02175     ino << "Instantiating form " << endl;
02176     ino.more();
02177     ino << def->asString() << endl;
02178     ino.less();
02179     ino << endl;
02180   }
02181 
02182   WorkList<string> worklist;
02183   doInstantiate(errStream, defIdent,
02184                 defIdent->symType, errFree, worklist);
02185 
02186   if (epName == FQName("bitc.main", "main"))
02187     UocInfo::mainIsDefined = true;
02188 
02189   return errFree;
02190 }
02191 
02192 // One Shot instantiator
02193 bool
02194 UocInfo::instantiate(ostream &errStream, const FQName& epName)
02195 {
02196   bool errFree = true;
02197   UpdateMegaEnvs(shared_from_this());
02198 
02199   CHKERR(errFree, instantiateFQN(errStream, epName));
02200 
02201   DEBUG(INST)
02202     cerr << "Unified UOC after instantiation is "
02203          << uocAst->asString() << endl;
02204   CHKERR(errFree, RandT(errStream, true, POLY_SYM_FLAGS,
02205                         POLY_TYP_FLAGS, "[[Post Instantiation]]"));
02206 
02207   return errFree;
02208 }
02209 
02210 // Batch mode Instantiator -- same as the one shot mode,
02211 // except that it does not refresh the megaENVs after
02212 // after instantiationg rach definition
02213 
02214 bool
02215 UocInfo::instantiateBatch(ostream &errStream,
02216                           FQNameSet& epNames)
02217 {
02218   bool errFree = true;
02219   UpdateMegaEnvs(shared_from_this());
02220 
02230   CHKERR(errFree, 
02231          instantiateFQN(errStream, 
02232                         FQName("bitc.prelude","__index_lt")));
02233   CHKERR(errFree,
02234          instantiateFQN(errStream, 
02235                         FQName("bitc.prelude","IndexBoundsError")));
02236 
02237   for (FQNameSet::iterator itr = epNames.begin();
02238       itr != epNames.end(); ++itr)
02239     CHKERR(errFree, instantiateFQN(errStream, (*itr)));
02240 
02241   DEBUG(INST)
02242     cerr << "Unified UOC after instantiation is "
02243          << uocAst->asString() << endl;
02244   CHKERR(errFree, RandT(errStream, true, POLY_SYM_FLAGS,
02245                         POLY_TYP_FLAGS, "Post Instantiation: "));
02246 
02247   return errFree;
02248 }
02249 
02250 

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