Clconv.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 <dirent.h>
00041 #include <fstream>
00042 #include <iostream>
00043 #include <sstream>
00044 #include <string>
00045 #include <libsherpa/UExcept.hxx>
00046 #include <libsherpa/CVector.hxx>
00047 #include <libsherpa/avl.hxx>
00048 #include <assert.h>
00049 #include "AST.hxx"
00050 #include "Type.hxx"
00051 #include "TvPrinter.hxx"
00052 #include "backend.hxx"
00053 #include "inter-pass.hxx"
00054 #include "Symtab.hxx"
00055 #include "Unify.hxx"
00056 #include "Special.hxx"
00057 
00058 using namespace sherpa;
00059 
00060 #define SHAPDEBUG if(0)
00061 
00062 // Set to true if you want to hoist all lambdas unconditionally
00063 #define HOISTALL false
00064 
00065 // Set to true if you want to build procedure objects for all lambdas
00066 // unconditionally.
00067 #define CLOSEALL false
00068 
00069 #define NULL_MODE  0x0u
00070 #define LOCAL_MODE 0x2u  // Parameters
00071 #define USE_MODE   0x3u
00072 #define TYPE_MODE  0x4u
00073  
00074 static void
00075 markRecBound(AST *ast)
00076 {
00077   for(size_t c=0; c < ast->children.size(); c++)
00078     markRecBound(ast->children[c]);
00079   if (ast->astType == at_ident)
00080     ast->Flags2 |= ID_IS_RECBOUND;
00081 }
00082 
00087 static void
00088 clearusedef(AST *ast)
00089 {
00090   ast->Flags2 &= ~(ID_IS_DEF|ID_IS_USE|ID_IS_CLOSED|ID_IS_CAPTURED|ID_NEEDS_HEAPIFY|ID_IS_RECBOUND);
00091 
00092   for(size_t c=0; c < ast->children.size(); c++)
00093     clearusedef(ast->children[c]);
00094 }
00095 
00100 static void
00101 findusedef(AST *topAst, AST *ast, const int mode,
00102            // list of vars that are bound within the lambda at the
00103            // current point:
00104            CVector<AST *> *boundVars,
00105            // list of vars that lambda uses, but are not in
00106            // boundVars. Globals are not entered into this.
00107            CVector<AST *> *freeVars)
00108 {
00109   switch(ast->astType) {
00110 
00111   case at_Null:
00112   case at_AnyGroup:
00113   case at_version:
00114   case agt_literal:
00115   case agt_tvar:
00116   case agt_var:
00117   case agt_definition:
00118   case agt_type:
00119   case agt_bindingPattern:
00120   case agt_expr:
00121   case agt_eform:
00122   case agt_type_definition:
00123   case agt_value_definition:
00124   case at_letbindings:
00125   case at_letbinding:
00126   case at_dobindings:
00127   case at_dobinding:
00128   case agt_CompilationUnit:
00129   case at_ifident:
00130   case at_localFrame:
00131   case at_frameBindings:
00132   case agt_tc_definition:
00133   case agt_if_definition:
00134   case agt_category:
00135   case agt_ow:
00136   case agt_qtype:
00137   case agt_fielditem:
00138   case at_refCat:
00139   case at_valCat:
00140   case at_opaqueCat:
00141   case at_tcdecls:
00142   case at_tyfn:
00143   case at_usesel:
00144   case at_use_case:
00145   case at_identList:
00146   case at_container:
00147   case at_defrepr:
00148   case at_reprbody:
00149   case agt_reprbodyitem:
00150   case at_reprcase:
00151   case at_reprcaselegR:
00152   case at_reprtag:
00153   case at_unit:
00154   case at_boolLiteral:
00155   case at_charLiteral:
00156   case at_intLiteral:
00157   case at_floatLiteral:
00158   case at_stringLiteral:
00159   case at_bitfield:
00160   case at_declunion:
00161   case at_declstruct:
00162   case at_declrepr:
00163   case at_use:
00164   case at_import:
00165   case at_provide:
00166   case at_declares:
00167   case at_declare:
00168   case at_tvlist:
00169   case at_unitPattern:
00170   case at_docString:
00171     break;
00172 
00173 
00174   case at_ident:
00175     {
00176       //     errStream << ast->loc.asString() 
00177       //               << "astType = at_ident; mode = " << mode 
00178       //               << std::endl;
00179 
00180       switch(mode) {
00181 
00182       case TYPE_MODE:
00183         break;
00184         
00185       case LOCAL_MODE:
00186         boundVars->append(ast);
00187         ast->Flags2 |= ID_IS_DEF;
00188         break;
00189       
00190       case USE_MODE:
00191         {
00192           if (ast->symbolDef == NULL)
00193             std::cerr << "Warning: No definition for "
00194                       << ast->fqn << std::endl;
00195 
00196 #if 0
00197           assert(ast->symbolDef != NULL);
00198 #endif
00199 
00200           ast->Flags2 |= ID_IS_USE;
00201 
00202           // could check ast->symbolDef->symType->isMutable()
00203 
00204           if(ast->symbolDef->isGlobal())
00205             break;
00206 
00207 #if 1
00208           if (ast->symbolDef->Flags2 & ID_IS_RECBOUND) {
00209             ast->Flags2 |= (ID_NEEDS_HEAPIFY|ID_IS_CLOSED);
00210             ast->symbolDef->Flags2 |= (ID_NEEDS_HEAPIFY|ID_IS_CAPTURED);
00211           }
00212 #endif
00213       
00214           if(boundVars->contains(ast->symbolDef))
00215             break;
00216 
00217           ast->Flags2 |= ID_IS_CLOSED;
00218           ast->symbolDef->Flags2 |= ID_IS_CAPTURED;
00219 
00220           if (ast->symbolDef->getType()->needsCaptureConversion()) {
00221             ast->Flags2 |= ID_NEEDS_HEAPIFY;
00222             ast->symbolDef->Flags2 |= ID_NEEDS_HEAPIFY;
00223           }
00224 
00225 
00226           SHAPDEBUG std::cerr << "Append " << ast->symbolDef->fqn
00227                               << " to freeVars" << std::endl;
00228 
00229           if (!freeVars->contains(ast->symbolDef))
00230             freeVars->append(ast->symbolDef);
00231           break;
00232         }      
00233       case NULL_MODE:
00234       default:
00235         break;
00236       }
00237       break;
00238     }
00239 
00240   case at_start:
00241     {
00242       for(size_t c=0; c < ast->children.size(); c++)
00243         findusedef(topAst, ast->children[c], NULL_MODE, boundVars, freeVars);
00244       break;
00245     }
00246 
00247   case at_deftypeclass:
00248     {
00249       findusedef(topAst, ast->children[3], TYPE_MODE, boundVars, freeVars);
00250       break;
00251     }
00252 
00253   case at_definstance:
00254     {
00255       findusedef(topAst, ast->children[0], TYPE_MODE, boundVars, freeVars);
00256       findusedef(topAst, ast->children[1], USE_MODE, boundVars, freeVars);
00257       findusedef(topAst, ast->children[2], TYPE_MODE, boundVars, freeVars);
00258       break;
00259     }
00260 
00261   case at_method_decl: 
00262     {
00263       findusedef(topAst, ast->children[1], USE_MODE, boundVars, freeVars);
00264       break;
00265     }
00266 
00267   case at_defunion:
00268   case at_defstruct:
00269     {
00270       findusedef(topAst, ast->children[4], TYPE_MODE, boundVars, freeVars);
00271       break;
00272     }
00273     
00274   case at_declValue:
00275     {      
00276       findusedef(topAst, ast->children[1], TYPE_MODE, boundVars, freeVars);
00277       break;
00278     }
00279     
00280   case at_fn: 
00281     {      
00282       findusedef(topAst, ast->children[0], TYPE_MODE, boundVars, freeVars);
00283       findusedef(topAst, ast->children[1], TYPE_MODE, boundVars, freeVars);
00284       break;
00285     }
00286 
00287   case at_define:
00288     {
00289       findusedef(topAst, ast->children[1], USE_MODE, boundVars, freeVars);
00290       break;
00291     }
00292 
00293   case at_identPattern:
00294     {
00295       findusedef(topAst, ast->children[0], mode, boundVars, freeVars);
00296       break;
00297     }
00298 
00299   case at_pairPattern:
00300     {
00301       findusedef(topAst, ast->children[0], mode, boundVars, freeVars);
00302       findusedef(topAst, ast->children[1], mode, boundVars, freeVars);
00303       break;
00304     }
00305     
00306   case at_tqexpr:
00307     {
00308       findusedef(topAst, ast->children[0], USE_MODE, boundVars, freeVars);
00309       findusedef(topAst, ast->children[1], TYPE_MODE, boundVars, freeVars);
00310       break;
00311     }
00312 
00313   case at_suspend:
00314     {
00315       findusedef(topAst, ast->children[1], USE_MODE, boundVars, freeVars);
00316       break;
00317     }
00318     
00319   case at_select:
00320     {
00321       findusedef(topAst, ast->children[0], USE_MODE, boundVars, freeVars);
00322       break;
00323     }
00324 
00325   case at_lambda:
00326     {
00327       if (ast == topAst) {
00328         findusedef(topAst, ast->children[0], LOCAL_MODE, 
00329                    boundVars, freeVars);
00330         findusedef(topAst, ast->children[1], USE_MODE, 
00331                    boundVars, freeVars);
00332       }
00333       else {
00334         CVector<AST *> freeVars;
00335         CVector<AST *> boundVars;
00336 
00337         findusedef(topAst, ast->children[0], LOCAL_MODE, 
00338                    &boundVars, &freeVars);
00339         findusedef(topAst, ast->children[1], USE_MODE, 
00340                    &boundVars, &freeVars);
00341       }
00342 
00343       break;
00344     }
00345     
00346   case at_interface:
00347   case at_module:
00348     {
00349       for(size_t c=0; c < ast->children.size(); c++)
00350         findusedef(topAst, ast->children[c], NULL_MODE, boundVars, freeVars);
00351       break;
00352     }
00353   case at_methods:
00354     {
00355       for(size_t c=0; c < ast->children.size(); c++)
00356         findusedef(topAst, ast->children[c], USE_MODE, boundVars, freeVars);
00357       break;
00358     }
00359 
00360   case at_method_decls:
00361   case at_tcapp:    
00362   case at_typeapp:
00363   case at_exceptionType:
00364   case at_arrayType:
00365   case at_vectorType:
00366   case at_refType:
00367   case at_valType:
00368   case at_primaryType:
00369   case at_pairType:
00370   case at_fnargVec:
00371   case at_mutableType:
00372   case at_qualType:
00373   case at_constraints:
00374   case at_constructors:
00375   case at_fields:
00376   case at_fill:
00377     {
00378       for(size_t c=0; c < ast->children.size(); c++)
00379         findusedef(topAst, ast->children[c], TYPE_MODE, boundVars, freeVars);
00380       break;
00381     }
00382 
00383   case at_constructor:
00384   case at_field:
00385   case at_defexception:
00386     {
00387       for(size_t c=1; c<ast->children.size();c++)
00388         findusedef(topAst, ast->children[c], TYPE_MODE, boundVars, freeVars);
00389       break;
00390     }
00391 
00392   case at_begin:
00393     {
00394       for(size_t c=0; c<ast->children.size();c++)
00395         findusedef(topAst, ast->children[c], USE_MODE, boundVars, freeVars);
00396       break;
00397     }
00398 
00399   case at_argVec:
00400     {
00401       for(size_t c=0; c<ast->children.size();c++)
00402         findusedef(topAst, ast->children[c], LOCAL_MODE, boundVars, freeVars);
00403       break;
00404     }
00405 
00406   case at_and:
00407   case at_or:
00408   case at_not:
00409   case at_cond:
00410   case at_cond_legs:
00411   case at_dup:
00412   case at_deref:
00413   case at_switchR:
00414   case at_sw_legs:
00415   case at_otherwise:
00416   case at_tryR:
00417   case at_throw:
00418   case at_array_length:
00419   case at_vector_length:
00420   case at_array_nth:
00421   case at_vector_nth:
00422   case at_vector:
00423   case at_array:
00424   case at_pair:
00425   case at_mkclosure:
00426   case at_makevector:    
00427   case at_apply:
00428     {
00429       for(size_t c=0; c<ast->children.size();c++)
00430         findusedef(topAst, ast->children[c], USE_MODE, boundVars, freeVars);
00431       break;
00432     }
00433     
00434   case at_ucon_apply:
00435   case at_struct_apply:
00436     {
00437       for(size_t c=1; c<ast->children.size();c++)
00438         findusedef(topAst, ast->children[c], USE_MODE, boundVars, freeVars);
00439       break;
00440     }
00441 
00442   case at_if:
00443     {
00444       for(size_t c=0; c<ast->children.size();c++)
00445         findusedef(topAst, ast->children[c], USE_MODE, boundVars, freeVars);
00446       break;
00447     }
00448 
00449   case at_cond_leg:
00450     {
00451       findusedef(topAst, ast->children[0], USE_MODE, boundVars, freeVars);
00452       findusedef(topAst, ast->children[1], USE_MODE, boundVars, freeVars);
00453       break;
00454     }
00455     
00456   case at_setbang:
00457     {
00458       for(size_t c=0; c<ast->children.size();c++)
00459         findusedef(topAst, ast->children[c], USE_MODE, boundVars, freeVars);
00460       break;
00461     }
00462     
00463   case at_sw_leg:
00464     {
00465       findusedef(topAst, ast->children[0], LOCAL_MODE, boundVars, freeVars);
00466       for(size_t c=1; c<ast->children.size();c++)
00467         findusedef(topAst, ast->children[c], USE_MODE, boundVars, freeVars);
00468       break;
00469     }
00470     
00471   case at_do:
00472     {
00473       AST *dbs = ast->children[0];      
00474       for (size_t c = 0; c < dbs->children.size(); c++) {
00475         AST *db = dbs->children[c];
00476         
00477         findusedef(topAst, db->children[1], USE_MODE, boundVars, freeVars);
00478         findusedef(topAst, db->children[0], LOCAL_MODE, boundVars, freeVars);
00479         findusedef(topAst, db->children[2], USE_MODE, boundVars, freeVars);
00480       }
00481       
00482       findusedef(topAst, ast->children[1], USE_MODE, boundVars, freeVars);
00483       findusedef(topAst, ast->children[2], USE_MODE, boundVars, freeVars);
00484       break;
00485     }
00486 
00487   case at_dotest:
00488     {
00489       findusedef(topAst, ast->children[0], USE_MODE, boundVars, freeVars);
00490       findusedef(topAst, ast->children[1], USE_MODE, boundVars, freeVars);
00491       break;
00492     }    
00493 
00494   case at_letStar:
00495   case at_let:
00496   case at_letrec:
00497     {
00498       AST *lbs = ast->children[0];
00499 
00500       // For each individual binding // match at_letbinding+
00501       for (size_t c = 0; c < lbs->children.size(); c++) {
00502         AST *lb = lbs->children[c];
00503 
00504         findusedef(topAst, lb->children[0], LOCAL_MODE, boundVars, freeVars);
00505         if (ast->astType == at_letrec)
00506           markRecBound(lb->children[0]);
00507         findusedef(topAst, lb->children[1], USE_MODE, boundVars, freeVars);
00508       }
00509       
00510       findusedef(topAst, ast->children[1], USE_MODE, boundVars, freeVars);
00511       break;
00512     }
00513   }
00514 }
00515 
00516 AST *
00517 cl_rewrite_captured_idents(AST *ast, AST *clenvName)
00518 {
00519   for (size_t c = 0; c < ast->children.size(); c++)
00520     ast->children[c] = 
00521       cl_rewrite_captured_idents(ast->children[c], clenvName);
00522 
00523   switch(ast->astType) {
00524   case at_ident:
00525     {
00526       if (ast->Flags2 & ID_IS_CLOSED) {
00527         AST *clUse = new AST(at_select, ast->loc);
00528         clUse->addChild(clenvName->getSCopy(clenvName->loc));
00529         clUse->addChild(ast);
00530 
00531         ast = clUse;
00532       }
00533 
00534       break;
00535     }
00536   default:
00537     break;
00538   }
00539 
00540   return ast;
00541 }
00542 
00543 // Walk an AST. If it contains a lambda form that is going to require
00544 // a closure record, fabricate the closure record and append it to outASTs
00545 AST *
00546 cl_convert_ast(AST *ast, CVector<AST *> *outAsts, bool shouldHoist)
00547 {
00548   bool hoistChildren = true;
00549 
00550   if (ast->astType == at_define) {
00551     // match agt_expr
00552     if(ast->children[0]->astType == at_identPattern &&
00553        (ast->children[1]->astType == at_lambda))
00554       hoistChildren = HOISTALL;
00555   }
00556 
00557   for (size_t c = 0; c < ast->children.size(); c++)
00558     ast->children[c] = 
00559       cl_convert_ast(ast->children[c], outAsts, hoistChildren);
00560 
00561   switch(ast->astType) {
00562   case at_lambda:
00563     {
00564       CVector<AST *> boundVars;
00565       CVector<AST *> freeVars;
00566 
00567       AST *clenvName = 0;
00568       TvPrinter tvP;
00569       CVector<std::string> *tvs = 0;
00570 
00571       SHAPDEBUG std::cerr << "Processing lambda. " << std::endl;
00572 
00573       // Need to re-run this here, because we may have hoisted inner
00574       // lambdas and/or introduced a closure conversion, which will
00575       // have introduced new identifiers.
00576       findusedef(ast, ast, NULL_MODE, &boundVars, &freeVars);
00577 
00578       // defstruct = ident tvlist category declares fields constraints;
00579       if (freeVars.size() || CLOSEALL) {
00580         SHAPDEBUG std::cerr << "Need to generate closure struct. " << std::endl;
00581         AST *defStruct = new AST(at_defstruct, ast->loc);
00582         
00583         // Note defstruct does not use an identPattern
00584         clenvName = AST::genSym(ast, "clenv");
00585         clenvName->identType = id_type;
00586         clenvName->Flags |= (ID_IS_GLOBAL | ID_IS_CTOR);
00587         defStruct->addChild(clenvName);
00588 
00589         // FIX: if the free variables have alpha types, need to add
00590         // the alpha variables here, and I don't know how to do
00591         // that. For the moment, simply add an at_Null record as a
00592         // placeholder:
00593         AST *tvlist = new AST(at_tvlist, ast->loc);
00594         defStruct->addChild(tvlist);
00595 
00596         // env records are ref types
00597         defStruct->addChild(new AST(at_refCat));
00598         // no declares
00599         defStruct->addChild(new AST(at_declares));
00600         // Parent AST for fields:
00601         AST *fields = new AST(at_fields, ast->loc);
00602         defStruct->addChild(fields);
00603 
00604         // Add empty constraints subtree
00605         defStruct->addChild(new AST(at_constraints, ast->loc));
00606 
00607         for (size_t fv = 0; fv < freeVars.size(); fv++) {
00608           assert(freeVars[fv]->astType == at_ident);
00609           AST *field = new AST(at_field, ast->loc);
00610           AST *ident = new AST(at_ident, ast->loc);
00611           ident->s = ident->fqn.ident = freeVars[fv]->s;
00612 
00613           field->addChild(ident);
00614           field->addChild(freeVars[fv]->symType->asAST(ast->loc, &tvP));
00615 
00616           fields->addChild(field);
00617         }
00618 
00619         // If the Type of arg contains a type variable,   
00620         // then add to the tvlist.
00621         tvs = tvP.getAllTvarStrings();
00622         for(size_t i=0; i<tvs->size(); i++) {
00623           AST *tv = new AST(at_ident, tvlist->loc);
00624           tv->Flags |= ID_IS_TVAR;
00625           tv->s = tv->fqn.ident = ((*tvs)[i]);
00626           tvlist->children.append(tv);
00627         }
00628 
00629         // Okay. We have built the type declaration for the closure
00630         // record. Append it to outAsts
00631         outAsts->append(defStruct);
00632       }
00633 
00634       // Need to hoist if (a) we are supposed to, or (b) we just
00635       // introduced a closure.
00636       if (shouldHoist || clenvName) {
00637         SHAPDEBUG std::cerr << "Need to hoist this lambda. " << std::endl;
00638 
00639         SHAPDEBUG ast->PrettyPrint(std::cerr);
00640 
00641         // AST define = bindingPattern expr;
00642         AST *newDef = new AST(at_define, ast->loc);
00643 
00644         AST *lamName = AST::genSym(ast, "lam");
00645         lamName->identType = id_value;
00646         lamName->Flags |= ID_IS_GLOBAL;
00647 
00648         AST *lamType = ast->symType->asAST(ast->loc);
00649 
00650         AST *lamPat = new AST(at_identPattern, ast->loc, lamName, lamType);
00651         newDef->addChild(lamPat);
00652         newDef->addChild(ast);
00653         newDef->addChild(new AST(at_constraints));
00654 
00655         // See if we can re-use the existing lambda or we need to add
00656         // the closure argument:
00657 
00658         AST *clArgName = 0;
00659 
00660         if (clenvName) {
00661           // Insert the extra closure argument and prepend the type to
00662           // the attached function type signature
00663 
00664           AST *argVec = ast->child(0);
00665           AST *body = ast->child(1);
00666           clArgName = new AST(at_ident, ast->loc);
00667           clArgName->s = clArgName->fqn.ident = "__clArg";
00668           AST *clPat = new AST(at_identPattern, ast->loc, clArgName);
00669 
00670           AST *clType;
00671 
00672           if(tvs->size()) {
00673             AST *typeApp = new AST(at_typeapp, ast->loc);
00674             typeApp->addChild(clenvName->Use());
00675 
00676             for(size_t i=0; i<tvs->size(); i++) {
00677               AST *tv = new AST(at_ident, ast->loc);
00678               tv->Flags |= ID_IS_TVAR;
00679               tv->s = tv->fqn.ident = ((*tvs)[i]);
00680               typeApp->addChild(tv);
00681             }
00682 
00683             clType = typeApp;
00684           }
00685           else
00686             clType = clenvName->Use();
00687 
00688           lamType->children[0]->children.insert(0, clType);
00689           clPat->addChild(clType->getDCopy());
00690           argVec->children.insert(0, clPat);
00691 
00692           ast->children[1] = cl_rewrite_captured_idents(body, clArgName);
00693         }
00694 
00695         // We have built the hoisted procedure. Emit that:
00696         outAsts->append(newDef);
00697 
00698         SHAPDEBUG ast->PrettyPrint(newDef);
00699 
00700         // If the lambda requires a closure, emit a make-closure, else
00701         // emit an identifier reference in place of the lambda:
00702 
00703         AST *lamUse = lamName->Use();
00704         lamUse->symbolDef = lamName;
00705 
00706         if (clenvName) {
00707           AST *mkEnv = new AST(at_apply, ast->loc);
00708           mkEnv->addChild(clenvName->Use());
00709 
00710           for (size_t fv = 0; fv < freeVars.size(); fv++)
00711             mkEnv->addChild(freeVars[fv]->Use());
00712 
00713           AST *mkClo = new AST(at_mkclosure, ast->loc, mkEnv, lamUse);
00714           ast = mkClo;
00715         }
00716         else {
00717           ast = lamUse; 
00718         }
00719 
00720         SHAPDEBUG ast->PrettyPrint(ast);
00721       }
00722 
00723       return ast;
00724     }
00725 
00726   default:
00727     return ast;
00728   }
00729 }
00730 
00731 void
00732 cl_convert(UocInfo *uoc)
00733 {
00734   CVector<AST *> outAsts;
00735 
00736   AST *modOrIf = uoc->ast->child(0);
00737 
00738   for (size_t c = 0;c < modOrIf->children.size(); c++) {
00739     AST *child = modOrIf->children[c];
00740 
00741     child = cl_convert_ast(child, &outAsts, true);
00742     outAsts.append(child);
00743   }
00744 
00745   modOrIf->children = outAsts;
00746 }
00747 
00748 // Collect all of the at_ident ASTs that are defined in this argument
00749 // binding pattern and are marked as captured.
00750 static void
00751 collectHeapifiedArgs(AST *ast, CVector<AST *> *capturedArgs)
00752 {
00753   if (ast->astType == at_ident && (ast->Flags2 & ID_NEEDS_HEAPIFY)) {
00754     assert (ast->Flags2 & ID_IS_CAPTURED);
00755 
00756     capturedArgs->append(ast);
00757   }
00758 
00759   for(size_t i=0; i < ast->children.size(); i++)
00760     collectHeapifiedArgs(ast->child(i), capturedArgs);
00761 }
00762 
00763 // Simple re-writing pass. Takes all of the identifiers that were 
00764 // identfied above as being closed over and re-writes them in such a
00765 // way as to push them into the heap. In the following examples, the
00766 // '*' after the bound identifier indicates that it is captured. The
00767 // rewrites that we need to do on the defining occurrences are:
00768 //
00769 //  (let[rec] ((a* e-init) ...) <body>)
00770 //  => (let[ref] ((a (dup e-init))) <body>)
00771 //
00772 //  (switch id* e <cases>) => (switch id (dup e) <cases>)
00773 //
00774 //  (lambda (a* ...) <body>)
00775 //   => (lambda (a ...)
00776 //         (let ((a (dup a)))
00777 //            <body>))
00778 //
00779 // And then in the use-occurrences we simply need (at this stage) to
00780 // wrap the use-occurrences with (__clmember id)
00781 //
00782 AST *
00783 cl_heapify(AST *ast)
00784 {
00785   switch(ast->astType) {
00786   case at_lambda:
00787     {
00788       // Proceed through the arguments. For each argument that is
00789       // captured, rewrite the body to be surrounded by a dup'ing LET
00790       // form.
00791       AST *args = ast->child(0);
00792       AST *body = ast->child(1);
00793 
00794       CVector<AST *> heapifiedArgs;
00795       // Captures the leaf idents:
00796       collectHeapifiedArgs(args, &heapifiedArgs);
00797       if (heapifiedArgs.size() == 0)
00798         break;
00799 
00800       AST *bindings = new AST(at_letbindings, body->loc);
00801 
00802       // Wrap the existing body in a LET binding:
00803       body = new AST(at_let, body->loc, bindings, body);
00804       body->addChild(new AST(at_constraints));
00805       ast->children[1] = body;
00806 
00807       // The RHS is not yet dup'd here. This will happen when this let
00808       // is processed in the at_letbinding handler.
00809       for (size_t i = 0; i < heapifiedArgs.size(); i++) {
00810         AST *arg = heapifiedArgs[i];
00811         AST *argExpr = new AST(at_ident, arg->loc);
00812         argExpr->s = argExpr->fqn.ident = arg->s;
00813 
00814         AST *argIdent = new AST(at_ident, arg->loc);
00815         argIdent->s = argIdent->fqn.ident = arg->s;
00816         AST *identPattern = new AST(at_identPattern, arg->loc, argIdent);
00817 
00818         // We have moved the point of capture into the let, which was
00819         // the point:
00820         arg->Flags2 &= ~(ID_IS_CAPTURED|ID_NEEDS_HEAPIFY);
00821         argIdent->Flags2 |= (ID_IS_CAPTURED|ID_NEEDS_HEAPIFY);
00822 
00823         AST *theBinding = new AST(at_letbinding, arg->loc, identPattern, argExpr);
00824         bindings->addChild(theBinding);
00825       }
00826 
00827       break;
00828     }
00829 
00830   case at_letbinding:
00831     {
00832       AST *bpattern = ast->child(0);
00833       AST *expr = ast->child(1);
00834 
00835       assert(bpattern->astType == at_identPattern);
00836       AST *ident = bpattern->child(0);
00837 
00838       SHAPDEBUG std::cerr << "Let binding for " << ident->s << std::endl;
00839 
00840       /* Must heapify EXPR unconditionally */
00841       expr = cl_heapify(expr);
00842 
00843       if (ident->Flags2 & ID_NEEDS_HEAPIFY) {
00844         // Process the RHS:
00845 
00846         SHAPDEBUG std::cerr << "  Needs dup " << ident->s << std::endl;
00847         
00848         assert (ident->Flags2 & ID_IS_CAPTURED);
00849         expr = new AST(at_dup, expr->loc, expr);
00850  
00851         // if the binding pattern was qualified by a type qualification,
00852         // wrap that in a REF:
00853         if (bpattern->children.size() == 2)
00854           bpattern->children[1] = 
00855             new AST(at_refType, bpattern->loc, bpattern->children[1]);
00856       }
00857 
00858       ast->children[1] = expr;
00859 
00860       return ast;
00861     }
00862 
00863   case at_ident:
00864     {
00865       // If this is a use occurrence of a heapified symbol, rewrite it
00866       // into a DEREF reference.
00867 
00868       SHAPDEBUG std::cerr << "Processing " << ast->s << std::endl;
00869       SHAPDEBUG if (ast->Flags2 & ID_NEEDS_HEAPIFY)
00870         std::cerr << "  needs heapify" << std::endl;
00871       SHAPDEBUG if (ast->Flags2 & ID_IS_CLOSED)
00872         std::cerr << "  closed" << std::endl;
00873 
00874       if (ast->Flags2 & ID_NEEDS_HEAPIFY) {
00875         SHAPDEBUG std::cerr << "Needs deref " << ast->s << std::endl;
00876         ast = new AST(at_deref, ast->loc, ast);
00877 
00878         // Intentionally skip any further recursion, since we don't
00879         // want to do this redundantly.
00880         return ast;
00881       }
00882     }
00883     
00884   default:
00885     break;
00886   }
00887 
00888   for (size_t c = 0; c < ast->children.size(); c++)
00889     ast->children[c] = cl_heapify(ast->children[c]);
00890 
00891   return ast;
00892 }
00893 
00894 #ifdef LATE_CLCONV
00895 bool
00896 UocInfo::be_clconv(std::ostream& errStream,
00897                    bool init, unsigned long flags)
00898 { 
00899   bool errFree = true;
00900 
00901   CVector<AST *> freeVars;
00902   CVector<AST *> boundVars;
00903   
00904   AST *&ast = UocInfo::linkedUoc.ast;
00905 
00906   SHAPDEBUG std::cerr << "findusedef 1" << std::endl;
00907 
00908   findusedef(ast, ast, NULL_MODE, &boundVars, &freeVars);
00909 
00910   SHAPDEBUG UocInfo::linkedUoc.PrettyPrint(errStream, true);
00911 
00912   SHAPDEBUG std::cerr << "cl_heapify" << std::endl;
00913   ast = cl_heapify(ast);
00914 
00915   SHAPDEBUG UocInfo::linkedUoc.PrettyPrint(errStream, true);
00916 
00917   SHAPDEBUG std::cerr << "RandT 1" << std::endl;
00918   // Re-run the type checker to propagate the changes:
00919   CHKERR(errFree, RandT(errStream, &UocInfo::linkedUoc, true, POLY_SYM_FLAGS, POLY_TYP_FLAGS));
00920   assert(errFree);
00921 
00922   SHAPDEBUG std::cerr << "findusedef 2" << std::endl;
00923 
00924   // This *shouldn't* be necessary, but it doesn't hurt anything.
00925   clearusedef(ast);
00926   findusedef(ast, ast, NULL_MODE, &boundVars, &freeVars);
00927 
00928   SHAPDEBUG UocInfo::linkedUoc.PrettyPrint(errStream);
00929 
00930   SHAPDEBUG std::cerr << "cl_convert" << std::endl;
00931   cl_convert(&UocInfo::linkedUoc);
00932 
00933   SHAPDEBUG UocInfo::linkedUoc.PrettyPrint(errStream);
00934 
00935   SHAPDEBUG std::cerr << "RandT 2" << std::endl;
00936   // Re-run the type checker to propagate the changes:
00937   CHKERR(errFree, RandT(errStream, &UocInfo::linkedUoc, true, POLY_SYM_FLAGS, POLY_TYP_FLAGS));
00938   assert(errFree);
00939 
00940   return true;
00941 }
00942 #else
00943 bool
00944 UocInfo::fe_clconv(std::ostream& errStream,
00945                    bool init, unsigned long flags)
00946 { 
00947   bool errFree = true;
00948 
00949   CVector<AST *> freeVars;
00950   CVector<AST *> boundVars;
00951   
00952   SHAPDEBUG std::cerr << "findusedef 1" << std::endl;
00953 
00954   findusedef(ast, ast, NULL_MODE, &boundVars, &freeVars);
00955 
00956   SHAPDEBUG if (isSourceUoc)
00957     PrettyPrint(errStream);
00958 
00959   SHAPDEBUG std::cerr << "cl_heapify" << std::endl;
00960   ast = cl_heapify(ast);
00961 
00962   SHAPDEBUG if (isSourceUoc)
00963     PrettyPrint(errStream);
00964 
00965   SHAPDEBUG std::cerr << "RandT 1" << std::endl;
00966   // Re-run the type checker to propagate the changes:
00967   CHKERR(errFree, RandT(errStream, this, true, PP_SYM_FLAGS, PP_TYP_FLAGS));
00968   assert(errFree);
00969 
00970   SHAPDEBUG std::cerr << "findusedef 2" << std::endl;
00971 
00972   // This *shouldn't* be necessary, but it doesn't hurt anything.
00973   clearusedef(ast);
00974   findusedef(ast, ast, NULL_MODE, &boundVars, &freeVars);
00975 
00976   SHAPDEBUG if (isSourceUoc)
00977     PrettyPrint(errStream, true);
00978 
00979   SHAPDEBUG std::cerr << "cl_convert" << std::endl;
00980 
00981   cl_convert(this);
00982 
00983   SHAPDEBUG if (isSourceUoc)
00984     PrettyPrint(errStream, true);
00985 
00986   SHAPDEBUG std::cerr << "RandT 2" << std::endl;
00987   // Re-run the type checker to propagate the changes:
00988   CHKERR(errFree, RandT(errStream, this, true, PP_SYM_FLAGS, PP_TYP_FLAGS));
00989   assert(errFree);
00990 
00991   return true;
00992 }
00993 #endif

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