Clconv.cxx

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright (C) 2008, Johns Hopkins University.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or
00007  * without modification, are permitted provided that the following
00008  * conditions are met:
00009  *
00010  *   - Redistributions of source code must contain the above
00011  *     copyright notice, this list of conditions, and the following
00012  *     disclaimer.
00013  *
00014  *   - Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions, and the following
00016  *     disclaimer in the documentation and/or other materials
00017  *     provided with the distribution.
00018  *
00019  *   - Neither the names of the copyright holders nor the names of any
00020  *     of any contributors may be used to endorse or promote products
00021  *     derived from this software without specific prior written
00022  *     permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  **************************************************************************/
00037 
00038 #include <assert.h>
00039 #include <stdint.h>
00040 #include <stdlib.h>
00041 #include <dirent.h>
00042 #include <fstream>
00043 #include <iostream>
00044 #include <sstream>
00045 #include <string>
00046 #include <set>
00047 
00048 #include <libsherpa/UExcept.hxx>
00049 
00050 #include "Options.hxx"
00051 #include "UocInfo.hxx"
00052 #include "AST.hxx"
00053 #include "Type.hxx"
00054 #include "TypeInfer.hxx"
00055 #include "inter-pass.hxx"
00056 
00057 using namespace std;
00058 using namespace boost;
00059 using namespace sherpa;
00060 
00061 typedef set<shared_ptr<AST> > AstSet;
00062 
00067 static void
00068 clearusedef(shared_ptr<AST> ast)
00069 {
00070   ast->flags &= ~(ID_IS_CLOSED|ID_IS_CAPTURED|ID_NEEDS_HEAPIFY);
00071 
00072   for (size_t c=0; c < ast->children.size(); c++)
00073     clearusedef(ast->child(c));
00074 }
00075 
00076 // See if The identifier `id' is used in the ast `ast'
00077 // id must be a defining form.
00078 static bool
00079 used(shared_ptr<AST> id, shared_ptr<AST> ast)
00080 {
00081   if (ast->astType == at_ident && ast->symbolDef == id) {
00082     assert(ast != id);
00083     assert(!id->symbolDef);
00084     return true;
00085   }
00086 
00087   for (size_t i=0; i < ast->children.size(); i++)
00088     if (used(id, ast->child(i)))
00089       return true;
00090 
00091   return false;
00092 }
00093 
00094 
00099 static bool
00100 findusedef(std::ostream &errStream,
00101            shared_ptr<AST> topAst, shared_ptr<AST> ast, const int mode,
00102            // list of vars that are bound within the lambda at the
00103            // current point:
00104            AstSet& boundVars,
00105            // list of vars that lambda uses, but are not in
00106            // boundVars. Globals are not entered into this.
00107            AstSet& freeVars)
00108 {
00109   bool errFree = true;
00110   switch(ast->astType) {
00111   case at_letGather:
00112     assert(false);
00113 
00114   case at_Null:
00115   case at_AnyGroup:
00116   case agt_literal:
00117   case agt_tvar:
00118   case agt_var:
00119   case agt_definition:
00120   case agt_type:
00121   case agt_expr:
00122   case agt_expr_or_define:
00123   case agt_eform:
00124   case agt_type_definition:
00125   case agt_value_definition:
00126   case agt_openclosed:
00127   case at_letbindings:
00128   case at_letbinding:
00129   case at_loopbindings:
00130   case at_loopbinding:
00131   case agt_CompilationUnit:
00132   case at_ifident:
00133   case at_localFrame:
00134   case at_frameBindings:
00135   case agt_tc_definition:
00136   case agt_if_definition:
00137   case agt_category:
00138   case agt_ow:
00139   case agt_qtype:
00140   case agt_fielditem:
00141   case at_unboxedCat:
00142   case at_boxedCat:
00143   case at_oc_closed:
00144   case at_oc_open:
00145   case at_opaqueCat:
00146   case at_tcdecls:
00147   case at_tyfn:
00148   case at_usesel:
00149   case at_identList:
00150   case at_container:
00151   case at_defrepr:
00152     //case at_reprbody:
00153     //case agt_reprbodyitem:
00154     //case at_reprcase:
00155     //case at_reprcaselegR:
00156     //case at_reprtag:
00157   case at_reprctrs:
00158   case at_reprctr:
00159   case at_reprrepr:
00160   case at_unit:
00161   case at_boolLiteral:
00162   case at_charLiteral:
00163   case at_intLiteral:
00164   case at_floatLiteral:
00165   case at_stringLiteral:
00166   case at_bitfieldType:
00167   case at_declunion:
00168   case at_declstruct:
00169   case at_declrepr:
00170   case at_importAs:
00171   case at_provide:
00172   case at_import:
00173   case at_ifsel:
00174   case at_declares:
00175   case at_declare:
00176   case at_tvlist:
00177   case at_docString:
00178   case agt_ucon:
00179   case agt_uselhs:
00180     break;
00181 
00182 
00183   case at_ident:
00184     {
00185       //     errStream << ast->loc.asString()
00186       //               << "astType = at_ident; mode = " << mode
00187       //                << std::endl;
00188 
00189       switch(mode) {
00190 
00191       case TYPE_MODE:
00192         break;
00193         
00194       case LOCAL_MODE:
00195         boundVars.insert(ast);
00196         break;
00197         
00198       case USE_MODE:
00199         {
00200           if (!ast->symbolDef)
00201             std::cerr << "Warning: No definition for "
00202                       << ast->fqn << std::endl;
00203 
00204           // could check ast->symbolDef->symType->isMutable()
00205         
00206           if (ast->symbolDef->isGlobal())
00207             break;
00208         
00209           if (boundVars.find(ast->symbolDef) != boundVars.end())
00210             break;
00211         
00212           if (Options::noAlloc) {
00213             errStream << ast->loc << ": "
00214                       << "Usage of identifier " << ast->s
00215                       << " mandates closure conversion -- "
00216                       << "disallowed in noAlloc mode"
00217                       << std::endl;
00218             errFree = false;
00219           }
00220 
00221           ast->flags |= ID_IS_CLOSED;
00222           ast->symbolDef->flags |= ID_IS_CAPTURED;
00223           
00224           if(ast->flags & ARG_BYREF) {
00225             errStream << ast->loc << ": Non-Capturable by-ref variable "
00226                       << ast->s
00227                       << " captured in a closure."
00228                       << std::endl;
00229             errFree = false;
00230           }
00231 
00232           if(ast->symType->isNonEscaping()) {
00233             errStream << ast->loc << ": Variable " << ast->s 
00234                       << " with Non-Capturable type "
00235                       << ast->symType->asBlockString()
00236                       << " captured in a closure."
00237                       << std::endl;
00238             return false;
00239           }
00240 
00241           if (ast->symbolDef->getType()->needsCaptureConversion()) {
00242             ast->flags |= ID_NEEDS_HEAPIFY;
00243             ast->symbolDef->flags |= ID_NEEDS_HEAPIFY;
00244           }
00245 
00246           DEBUG(CLCONV) std::cerr << "Append " << ast->symbolDef->fqn
00247                                  << " to freeVars" << std::endl;
00248         
00249           freeVars.insert(ast->symbolDef);
00250           break;
00251         }
00252       case NULL_MODE:
00253       default:
00254         break;
00255       }
00256       break;
00257     }
00258 
00259   case at_deftypeclass:
00260     {
00261       CHKERR(errFree, findusedef(errStream, topAst, ast->child(3),
00262                                  TYPE_MODE, boundVars, freeVars));
00263       break;
00264     }
00265 
00266   case at_definstance:
00267     {
00268       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00269                                  TYPE_MODE, boundVars, freeVars));
00270       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00271                                  USE_MODE, boundVars, freeVars));
00272       CHKERR(errFree, findusedef(errStream, topAst, ast->child(2),
00273                                  TYPE_MODE, boundVars, freeVars));
00274       break;
00275     }
00276 
00277   case at_method_decl:
00278     {
00279       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00280                                  USE_MODE, boundVars, freeVars));
00281       break;
00282     }
00283 
00284   case at_defunion:
00285   case at_defstruct:
00286     {
00287       CHKERR(errFree, findusedef(errStream, topAst, ast->child(4),
00288                                  TYPE_MODE, boundVars, freeVars));
00289       break;
00290     }
00291 
00292   case at_proclaim:
00293     {
00294       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00295                                  TYPE_MODE, boundVars, freeVars));
00296       break;
00297     }
00298 
00299   case at_fn:
00300   case at_methType:
00301     {
00302       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00303                                  TYPE_MODE, boundVars, freeVars));
00304       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00305                                  TYPE_MODE, boundVars, freeVars));
00306       break;
00307     }
00308 
00309   case at_define:
00310   case at_recdef:
00311     {
00312       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00313                                  USE_MODE, boundVars, freeVars));
00314       break;
00315     }
00316 
00317   case at_identPattern:
00318     {
00319       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00320                                  mode, boundVars, freeVars));
00321       break;
00322     }
00323 
00324   case at_typeAnnotation:
00325     {
00326       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00327                                  USE_MODE, boundVars, freeVars));
00328       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00329                                  TYPE_MODE, boundVars, freeVars));
00330       break;
00331     }
00332 
00333   case at_suspend:
00334     {
00335       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00336                                  USE_MODE, boundVars, freeVars));
00337       break;
00338     }
00339 
00340   case at_fqCtr:
00341     {
00342       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00343                                  TYPE_MODE, boundVars, freeVars));
00344       break;
00345     }
00346 
00347   case at_sizeof:
00348   case at_bitsizeof:
00349     {
00350       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00351                                  TYPE_MODE, boundVars, freeVars));
00352       break;
00353     }
00354     
00355   case at_select:
00356   case at_sel_ctr:
00357     {
00358       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00359                                  USE_MODE, boundVars, freeVars));
00360       break;
00361     }
00362 
00363   case at_lambda:
00364     {
00365       if (ast == topAst) {
00366         CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00367                                    LOCAL_MODE, boundVars, freeVars));
00368         CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00369                                    USE_MODE, boundVars, freeVars));
00370       }
00371       else {
00372         AstSet freeVars;
00373         AstSet boundVars;
00374 
00375         CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00376                                    LOCAL_MODE, boundVars, freeVars));
00377         CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00378                                    USE_MODE, boundVars, freeVars));
00379       }
00380 
00381       break;
00382     }
00383 
00384   case at_interface:
00385   case at_module:
00386     {
00387       for (size_t c=0; c < ast->children.size(); c++)
00388         CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00389                                    NULL_MODE, boundVars, freeVars));
00390       break;
00391     }
00392   case at_tcmethods: 
00393   case at_tcmethod_binding:
00394     {
00395       for (size_t c=0; c < ast->children.size(); c++)
00396         CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00397                                    USE_MODE, boundVars, freeVars));
00398       break;
00399     }
00400 
00401   case at_method_decls:
00402   case at_tcapp:
00403   case at_typeapp:
00404   case at_exceptionType:
00405   case at_dummyType:
00406   case at_arrayType:
00407   case at_vectorType:
00408   case at_boxedType:
00409   case at_byRefType:
00410   case at_arrayRefType:
00411   case at_unboxedType:
00412   case at_primaryType:
00413   case at_fnargVec:
00414   case at_mutableType:
00415   case at_constType:
00416   case at_qualType:
00417   case at_constraints:
00418   case at_constructors:
00419   case at_fields:
00420   case at_fill:
00421     {
00422       for (size_t c=0; c < ast->children.size(); c++)
00423         CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00424                                    TYPE_MODE, boundVars, freeVars));
00425       break;
00426     }
00427 
00428   case at_methdecl:
00430   case at_constructor:
00431   case at_field:
00432   case at_fieldType:
00433   case at_defexception:
00434     {
00435       for (size_t c=1; c<ast->children.size();c++)
00436         CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00437                                    TYPE_MODE, boundVars, freeVars));
00438       break;
00439     }
00440 
00441   case at_argVec:
00442     {
00443       for (size_t c=0; c<ast->children.size();c++)
00444         CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00445                                    LOCAL_MODE, boundVars, freeVars));
00446       break;
00447     }
00448 
00449   case at_setbang:
00450     {
00451       for (size_t c=0; c<ast->children.size();c++)
00452         CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00453                                    USE_MODE, boundVars, freeVars));
00454       break;
00455     }
00456 
00457   case at_begin:
00458   case at_allocREF:
00459   case at_setClosure:
00460   case at_copyREF:
00461   case at_mkClosure:
00462   case at_and:
00463   case at_or:
00464   case at_cond:
00465   case at_cond_legs:
00466   case at_condelse:
00467   case at_dup:
00468   case at_deref:
00469   case at_usw_legs:
00470   case at_throw:
00471 #ifdef HAVE_INDEXABLE_LENGTH_OPS
00472   case at_array_length:
00473   case at_array_ref_length:
00474   case at_vector_length:
00475 #endif
00476   case at_array_nth:
00477   case at_array_ref_nth:
00478   case at_vector_nth:
00479   case at_vector:
00480   case at_array:
00481   case at_MakeVector:
00482   case at_mkArrayRef:
00483   case at_apply:
00484     {
00485       for (size_t c=0; c<ast->children.size();c++)
00486         CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00487                                    USE_MODE, boundVars, freeVars));
00488       break;
00489     }
00490 
00491   case at_nth:
00492     // Shouldn't survive to this point
00493     assert(false);
00494     break;
00495 
00496   case at_labeledBlock:
00497   case at_return_from:
00498     {
00499       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00500                                  USE_MODE, boundVars, freeVars));
00501       break;
00502     }
00503 
00504   case at_uswitch:
00505   case at_try:
00506     {
00507       for (size_t c=0; c<ast->children.size();c++)
00508         if (c != IGNORE(ast))
00509           CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00510                                      USE_MODE, boundVars, freeVars));
00511       break;
00512     }
00513 
00514   case at_inner_ref:
00515     {
00516       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00517                                  USE_MODE, boundVars, freeVars));
00518 
00519       if (ast->flags & INNER_REF_NDX)
00520         CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00521                                    USE_MODE, boundVars, freeVars));
00522 
00523       break;
00524     }
00525 
00526   case at_ucon_apply:
00527   case at_struct_apply:
00528   case at_object_apply:
00529     {
00530       for (size_t c=1; c<ast->children.size();c++)
00531         CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00532                                    USE_MODE, boundVars, freeVars));
00533       break;
00534     }
00535 
00536   case at_if:
00537   case at_when:
00538   case at_unless:
00539     {
00540       for (size_t c=0; c<ast->children.size();c++)
00541         CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00542                                    USE_MODE, boundVars, freeVars));
00543       break;
00544     }
00545 
00546   case at_cond_leg:
00547     {
00548       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00549                                  USE_MODE, boundVars, freeVars));
00550       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00551                                  USE_MODE, boundVars, freeVars));
00552       break;
00553     }
00554 
00555   case at_otherwise:
00556   case at_usw_leg:
00557     {
00558       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00559                                  LOCAL_MODE, boundVars, freeVars));
00560       for (size_t c=1; c<ast->children.size();c++)
00561         CHKERR(errFree, findusedef(errStream, topAst, ast->child(c),
00562                                    USE_MODE, boundVars, freeVars));
00563       break;
00564     }
00565 
00566   case at_loop:
00567     {
00568       shared_ptr<AST> lbs = ast->child(0);
00569       // Initializers
00570       for (size_t c = 0; c < lbs->children.size(); c++) {
00571         shared_ptr<AST> lb = lbs->child(c);
00572         CHKERR(errFree, findusedef(errStream, topAst, lb->child(1),
00573                                    USE_MODE, boundVars, freeVars));
00574       }
00575 
00576       // Binding
00577       for (size_t c = 0; c < lbs->children.size(); c++) {
00578         shared_ptr<AST> lb = lbs->child(c);
00579         CHKERR(errFree, findusedef(errStream, topAst, lb->child(0),
00580                                    LOCAL_MODE, boundVars, freeVars));
00581       }
00582 
00583       //Step-wise update
00584       for (size_t c = 0; c < lbs->children.size(); c++) {
00585         shared_ptr<AST> lb = lbs->child(c);
00586         CHKERR(errFree, findusedef(errStream, topAst, ast->child(2),
00587                                    USE_MODE, boundVars, freeVars));
00588       }
00589 
00590       // Test
00591       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00592                                  USE_MODE, boundVars, freeVars));
00593       // Body
00594       CHKERR(errFree, findusedef(errStream, topAst, ast->child(2),
00595                                  USE_MODE, boundVars, freeVars));
00596       break;
00597     }
00598 
00599   case at_looptest:
00600     {
00601       CHKERR(errFree, findusedef(errStream, topAst, ast->child(0),
00602                                  USE_MODE, boundVars, freeVars));
00603       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00604                                  USE_MODE, boundVars, freeVars));
00605       break;
00606     }
00607 
00608   case at_letStar:
00609   case at_let:
00610   case at_letrec:
00611     {
00612       shared_ptr<AST> lbs = ast->child(0);
00613 
00614       // For each individual binding // match at_letbinding+
00615       for (size_t c = 0; c < lbs->children.size(); c++) {
00616         shared_ptr<AST> lb = lbs->child(c);
00617 
00618         CHKERR(errFree, findusedef(errStream, topAst, lb->child(1),
00619                                    USE_MODE, boundVars, freeVars));
00620         CHKERR(errFree, findusedef(errStream, topAst, lb->child(0),
00621                                    LOCAL_MODE, boundVars, freeVars));
00622       }
00623 
00624       CHKERR(errFree, findusedef(errStream, topAst, ast->child(1),
00625                                  USE_MODE, boundVars, freeVars));
00626       break;
00627     }
00628   }
00629 
00630   return errFree;
00631 }
00632 
00633 shared_ptr<AST>
00634 cl_rewrite_captured_idents(shared_ptr<AST> ast, shared_ptr<AST> clenvName)
00635 {
00636   for (size_t c = 0; c < ast->children.size(); c++)
00637     ast->child(c) =
00638       cl_rewrite_captured_idents(ast->child(c), clenvName);
00639 
00640   switch(ast->astType) {
00641   case at_ident:
00642     {
00643       if (ast->flags & ID_IS_CLOSED) {
00644         shared_ptr<AST> clUse = AST::make(at_select, ast->loc);
00645         clUse->addChild(clenvName->getDeepCopy());
00646         clUse->addChild(ast);
00647 
00648         ast = clUse;
00649       }
00650 
00651       break;
00652     }
00653   default:
00654     break;
00655   }
00656 
00657   return ast;
00658 }
00659 
00660 
00661 static shared_ptr<AST>
00662 getClenvUse(shared_ptr<AST> ast, shared_ptr<AST> clenvName,
00663             std::vector<std::string>& tvs)
00664 {
00665   shared_ptr<AST> clType;
00666   if (tvs.size()) {
00667     shared_ptr<AST> typeApp = AST::make(at_typeapp, ast->loc);
00668     typeApp->addChild(clenvName->Use());
00669 
00670     for (size_t i=0; i<tvs.size(); i++) {
00671       shared_ptr<AST> tv = AST::make(at_ident, ast->loc);
00672       tv->identType = id_tvar;
00673       tv->s = tv->fqn.ident = tvs[i];
00674       typeApp->addChild(tv);
00675     }
00676 
00677     clType = typeApp;
00678   }
00679   else
00680     clType = clenvName->Use();
00681 
00682   return clType;
00683 }
00684 
00685 
00686 #if 0
00687 static void
00688 rewriteMyCapture(shared_ptr<AST> ast, shared_ptr<AST> me, shared_ptr<AST> him)
00689 {
00690   if (ast->astType == at_set_closure) {
00691     shared_ptr<AST> envApp = ast->child(1);
00692     for (size_t c=1; c < envApp->children.size(); c++)
00693       if (envApp->child(c)->symbolDef == me)
00694         envApp->child(c) = him->Use();
00695     return;
00696   }
00697 
00698   for (size_t c=0; c < ast->children.size(); c++)
00699     rewriteMyCapture(ast->child(c), me, him);
00700 }
00701 #endif
00702 
00703 
00704 // Walk an AST. If it contains a lambda form that is going
00705 // to require a closure record, fabricate the closure record
00706 // and append it to outASTs
00707 static shared_ptr<AST>
00708 cl_convert_ast(shared_ptr<AST> ast,
00709                std::vector<shared_ptr<AST> >& outAsts,
00710                bool shouldHoist)
00711 {
00712   bool hoistChildren = true;
00713 
00714   /* Pre Processing */
00715   if (ast->astType == at_define || ast->astType == at_recdef) {
00716     hoistChildren = false;
00717 
00718     shared_ptr<AST> ident = ast->getID();
00719     if (!ident->decl) {
00720       shared_ptr<AST> proclaim = AST::make(at_proclaim, ast->loc,
00721                               ident->getDeepCopy(),
00722                               cl_convert_ast(ident->symType->asAST(ast->loc),
00723                                              outAsts, hoistChildren),
00724                               AST::make(at_constraints, ast->loc));
00725 
00726       if (ident->externalName.size())
00727         proclaim->child(0)->flags |= DEF_IS_EXTERNAL;
00728 
00729       ast->flags |= PROCLAIM_IS_INTERNAL;
00730       outAsts.push_back(proclaim);
00731     }
00732   }
00733 
00734   /* Process children (inside-out) */
00735   for (size_t c = 0; c < ast->children.size(); c++)
00736     ast->child(c) =
00737       cl_convert_ast(ast->child(c), outAsts, hoistChildren);
00738 
00739   /* Post Processing */
00740   switch(ast->astType) {
00741   case at_letrec:
00742     {
00743       shared_ptr<AST> lbs = ast->child(0);
00744       shared_ptr<AST> expr = ast->child(1);
00745 
00746       // A list of copyclosures to append in the end.
00747       shared_ptr<AST> ccs = AST::make(at_begin, expr->loc);
00748 
00749       for (size_t c=0; c < lbs->children.size(); c++) {
00750         shared_ptr<AST> lb = lbs->child(c);
00751         shared_ptr<AST> id = lb->child(0)->child(0);
00752         
00753         shared_ptr<AST> rhs = lb->child(1);
00754         
00755         // If this identifier may be used in *any* let-binding
00756         // within the current letrec, we must use the alloc-ref /
00757         // copy-ref scheme for closure conversion.
00758         if (used(id, lbs)) {
00759           assert(id->flags & ID_IS_CAPTURED);
00760           shared_ptr<AST> qual =
00761             id->symType->getBareType()->asAST(rhs->loc);
00762           qual = cl_convert_ast(qual, outAsts, hoistChildren);
00763           shared_ptr<AST> ac = AST::make(at_allocREF, rhs->loc, qual);
00764           shared_ptr<AST> cc = AST::make(at_copyREF, rhs->loc, id->Use(), rhs);
00765           ccs->children.push_back(cc);
00766           lb->child(1) = ac;
00767         }
00768       }
00769 
00770       ccs->addChild(expr);
00771 
00772       ast->child(1) = ccs;
00773       //ast->astType = at_let;
00774       break;
00775     }
00776 
00777   case at_lambda:
00778     {
00779       AstSet freeVars;
00780       AstSet boundVars;
00781 
00782       shared_ptr<AST> clenvName = GC_NULL;
00783       shared_ptr<TvPrinter> tvP = TvPrinter::make();
00784 
00785       DEBUG(CLCONV) std::cerr << "Processing lambda. " << std::endl;
00786 
00787       // Need to re-run this here, because we may have hoisted inner
00788       // lambdas and/or introduced a closure conversion, which will
00789       // have introduced new identifiers.
00790       findusedef(std::cerr, ast, ast, NULL_MODE, boundVars, freeVars);
00791 
00792       std::vector<std::string> tvs;
00793 
00794       // Closure object is only generated if we actually have some
00795       // free variables.
00796       bool needsClosure = !freeVars.empty();
00797       if (needsClosure) {
00798 
00799         DEBUG(CLCONV) std::cerr << "Need to generate closure struct. "
00800                                << std::endl;
00801 
00803         // defstruct = ident tvlist category declares fields constraints;
00804         shared_ptr<AST> defStruct = AST::make(at_defstruct, ast->loc);
00805 
00806         // Note defstruct does not use an identPattern
00807         clenvName = AST::genSym(ast, "clenv");
00808         clenvName->identType = id_struct;
00809         clenvName->flags |= (ID_IS_GLOBAL);
00810         defStruct->addChild(clenvName);
00811 
00812         // tvList: to be fixed-up later.
00813         shared_ptr<AST> tvlist = AST::make(at_tvlist, ast->loc);
00814         defStruct->addChild(tvlist);
00815         // env records are boxed types
00816         defStruct->addChild(AST::make(at_boxedCat));
00817         // no declares
00818         defStruct->addChild(AST::make(at_declares));
00819         // Parent AST for fields:
00820         shared_ptr<AST> fields = AST::make(at_fields, ast->loc);
00821         defStruct->addChild(fields);
00822         // Add empty constraints subtree
00823         defStruct->addChild(AST::make(at_constraints, ast->loc));
00824 
00825         for (AstSet::iterator fv = freeVars.begin();
00826             fv != freeVars.end(); ++fv) {
00827           assert((*fv)->astType == at_ident);
00828           shared_ptr<AST> field = AST::make(at_field, ast->loc);
00829           shared_ptr<AST> ident = AST::make(at_ident, ast->loc);
00830           ident->s = ident->fqn.ident = (*fv)->s;
00831         
00832           field->addChild(ident);
00833           shared_ptr<AST> fvType = (*fv)->symType->asAST(ast->loc, tvP);
00834           fvType = cl_convert_ast(fvType, outAsts, hoistChildren);
00835           field->addChild(fvType);
00836         
00837           fields->addChild(field);
00838         }
00839 
00840         // If the Type of arg contains a type variable,        
00841         // then add to the tvlist.
00842         // No type variables can appear if closure conversion happens
00843         // after polyinstantiation.
00844         tvs = tvP->getAllTvarStrings();
00845 
00846         for (size_t i=0; i < tvs.size(); i++) {
00847           shared_ptr<AST> tv = AST::make(at_ident, tvlist->loc);
00848           tv->identType = id_tvar;
00849           tv->s = tv->fqn.ident = tvs[i];
00850           tvlist->children.push_back(tv);
00851         }
00852 
00853         // Okay. We have built the type declaration for the closure
00854         // record. Append it to outAsts
00855         outAsts.push_back(defStruct);
00856       }
00857 
00859       if (shouldHoist) {
00860         DEBUG(CLCONV) std::cerr << "Need to hoist this lambda. "
00861                                << std::endl;
00862         DEBUG(CLCONV) ast->PrettyPrint(std::cerr);
00863         
00864         // AST define = bindingPattern expr;
00865         // This can be done as a recdef since we don't allow top-level
00866         // names to be shadowed.
00867         shared_ptr<AST> newDef = AST::make(at_recdef, ast->loc);
00868 
00869         shared_ptr<AST> lamName = AST::genSym(ast, "lam");
00870         lamName->identType = id_value;
00871         lamName->flags |= ID_IS_GLOBAL;
00872         
00873         shared_ptr<AST> lamType = ast->symType->asAST(ast->loc);
00874         // Once we removed closure types, this conversion
00875         // operation is redundant. Of historic interest,
00876         // placeholder reminder in case we switch back.
00877         lamType = cl_convert_ast(lamType, outAsts, hoistChildren);
00878         shared_ptr<AST> lamPat = AST::make(at_identPattern, ast->loc,
00879                                     lamName, lamType);        
00880         newDef->addChild(lamPat);
00881         newDef->addChild(ast);
00882         newDef->addChild(AST::make(at_constraints));
00883 
00884         if (needsClosure) {
00885           newDef->flags |= LAM_NEEDS_TRANS;
00886 
00887           // Insert the extra closure argument and prepend the type to
00888           // the attached function type signature
00889           shared_ptr<AST> argVec = ast->child(0);
00890           shared_ptr<AST> body = ast->child(1);
00891           shared_ptr<AST> clArgName = AST::make(at_ident, ast->loc);
00892           clArgName->s = clArgName->fqn.ident = "__clArg";
00893           shared_ptr<AST> clArgPat = AST::make(at_identPattern, ast->loc, clArgName);
00894           // Note: tvs was populated in the if (needsClosure) above
00895           // if (shouldHoist).
00896           shared_ptr<AST> clType = getClenvUse(ast, clenvName, tvs);
00897         
00898           lamType->child(0)->children.insert(lamType->child(0)->children.begin(),
00899                                              clType);
00900           clArgPat->addChild(clType->getDeepCopy());
00901           argVec->children.insert(argVec->children.begin(), clArgPat);
00902 
00903           ast->child(1) = cl_rewrite_captured_idents(body, clArgName);
00904         }
00905         
00906         // We have built the hoisted procedure. Emit that:
00907         outAsts.push_back(newDef);
00908 
00909         DEBUG(CLCONV) ast->PrettyPrint(newDef);
00910 
00911         // If the lambda requires a closure, emit a make-closure, else
00912         // emit an identifier reference in place of the lambda:
00913         shared_ptr<AST> lamUse = lamName->Use();
00914         if (freeVars.size()) {        
00915           shared_ptr<AST> mkEnv = AST::make(at_struct_apply, ast->loc);
00916           mkEnv->addChild(clenvName->Use());        
00917           for (AstSet::iterator fv = freeVars.begin();
00918                fv != freeVars.end(); ++fv)
00919             mkEnv->addChild((*fv)->Use());
00920         
00921           shared_ptr<AST> mkClo = AST::make(at_mkClosure, ast->loc, mkEnv, lamUse);
00922           ast = mkClo;
00923         }
00924         else {
00925           ast = lamUse;
00926         }
00927       }
00928       break;
00929     }
00930 
00931   default:
00932     {
00933       break;
00934     }
00935   }
00936 
00937   return ast;
00938 }
00939 
00940 void
00941 cl_convert(shared_ptr<UocInfo> uoc)
00942 {
00943   std::vector<shared_ptr<AST> > outAsts;
00944 
00945   shared_ptr<AST> modOrIf = uoc->uocAst;
00946 
00947   for (size_t c = 0;c < modOrIf->children.size(); c++) {
00948     shared_ptr<AST> child = modOrIf->child(c);
00949 
00950     child = cl_convert_ast(child, outAsts, true);
00951     outAsts.push_back(child);
00952   }
00953 
00954   modOrIf->children = outAsts;
00955 }
00956 
00957 // Simple re-writing pass. Takes all of the identifiers that were
00958 // identfied above as being closed over and re-writes them in such a
00959 // way as to push them into the heap. In the following examples, the
00960 // '*' after the bound identifier indicates that it is captured. The
00961 // rewrites that we need to do on the defining occurrences are:
00962 //
00963 //  (let[rec] ((a* e-init) ...) <body>)
00964 //  => (let[ref] ((a (dup e-init))) <body>)
00965 //
00966 //  (switch id* e <cases>) => (switch id (dup e) <cases>)
00967 //
00968 //  (lambda (a* ...) <body>)
00969 //   => (lambda (a ...)
00970 //         (let ((a (dup a)))
00971 //            <body>))
00972 //
00973 // And then in the use-occurrences we simply need (at this stage) to
00974 // wrap the use-occurrences with (__clmember id)
00975 //
00976 shared_ptr<AST>
00977 cl_heapify(shared_ptr<AST> ast)
00978 {
00979   switch(ast->astType) {
00980   case at_lambda:
00981     {
00982       // Proceed through the arguments. For each argument that is
00983       // captured, rewrite the body to be surrounded by a dup'ing LET
00984       // form.
00985       shared_ptr<AST> args = ast->child(0);
00986       shared_ptr<AST> body = ast->child(1);
00987 
00988       shared_ptr<AST> bindings = AST::make(at_letbindings, body->loc);
00989 
00990       // Wrap the existing body in a LET binding:
00991       body = AST::make(at_let, body->loc, bindings, body);
00992       body->addChild(AST::make(at_constraints));
00993 
00994       bool atleastOneHeapified = false;
00995 
00996       // The RHS is not yet dup'd here. This will happen when this let
00997       // is processed in the at_letbinding handler.
00998       for (size_t i = 0; i < args->children.size(); i++) {
00999         shared_ptr<AST> arg = args->child(i)->child(0);
01000         if ((arg->flags & ID_NEEDS_HEAPIFY) == 0)
01001           continue;
01002         
01003         atleastOneHeapified = true;
01004         // Exchange the arg to a new Identifier with the same name
01005         // Te reason for the exchange is that the use cases in the
01006         // body will be pointing to the *OLD* ident AST.
01007         shared_ptr<AST> newArg = AST::make(at_ident, arg->loc);
01008         newArg->s = newArg->fqn.ident = arg->s;
01009         args->child(i)->child(0) = newArg;
01010         
01011          // We have moved the point of capture into the let,
01012         // which was the point:
01013         shared_ptr<AST> letIdent = arg;
01014         shared_ptr<AST> letExpr = newArg->Use();
01015         shared_ptr<AST> identPattern = AST::make(at_identPattern, arg->loc, letIdent);
01016         
01017         shared_ptr<AST> theBinding = AST::make(at_letbinding, arg->loc,
01018                                   identPattern, letExpr);
01019         bindings->addChild(theBinding);
01020       }
01021 
01022       if (atleastOneHeapified)
01023         ast->child(1) = body;
01024 
01025       // Process the body.
01026       ast->child(1) = cl_heapify(ast->child(1));
01027       break;
01028     }
01029 
01030   case at_letbinding:
01031     {
01032       shared_ptr<AST> bpattern = ast->child(0);
01033       shared_ptr<AST> expr = ast->child(1);
01034 
01035       assert(bpattern->astType == at_identPattern);
01036       shared_ptr<AST> ident = bpattern->child(0);
01037 
01038       DEBUG(CLCONV) std::cerr << "Let binding for " << ident->s << std::endl;
01039 
01040       /* Must heapify EXPR unconditionally */
01041       expr = cl_heapify(expr);
01042 
01043       if (ident->flags & ID_NEEDS_HEAPIFY) {
01044         // Process the RHS:
01045 
01046         DEBUG(CLCONV) std::cerr << "  Needs dup " << ident->s << std::endl;
01047         
01048         assert (ident->flags & ID_IS_CAPTURED);
01049         expr = AST::make(at_dup, expr->loc, expr);
01050         // Previously: Clconv was marking Dup-ed variables specially
01051         // at this point expr->flags2 |= DUPED_BY_CLCONV;
01052 
01053         // if the binding pattern was qualified by a type qualification,
01054         // wrap that in a REF:
01055         if (bpattern->children.size() == 2)
01056           bpattern->child(1) =
01057             AST::make(at_boxedType, bpattern->loc, bpattern->child(1));
01058       }
01059 
01060       ast->child(1) = expr;
01061       break;
01062     }
01063 
01064   case at_ident:
01065     {
01066       // If this is a use occurrence of a heapified symbol, rewrite it
01067       // into a DEREF reference.
01068 
01069       DEBUG(CLCONV) std::cerr << "Processing " << ast->loc << ": "
01070                           << ast->s << std::endl;
01071       /* Swaroop: ID_NEEDS_HEAPIFY must always be checked on the
01072          symbolDef because all use cases may not be corerectly
01073          marked. For example see:
01074          (define PQR (let ((p #t))
01075               (set! p #f)
01076               (lambda () p)))
01077         
01078          Thhe first use case within the set! will not be heapified if
01079          this is not done.  */
01080 
01081       shared_ptr<AST> def = (ast->symbolDef) ? ast->symbolDef : ast;
01082 
01083       DEBUG(CLCONV) if (def->flags & ID_NEEDS_HEAPIFY)
01084         std::cerr << "  needs heapify" << std::endl;
01085       DEBUG(CLCONV) if (def->flags & ID_IS_CAPTURED)
01086         std::cerr << "  closed" << std::endl;
01087 
01088       if (def->flags & ID_NEEDS_HEAPIFY) {
01089         DEBUG(CLCONV) std::cerr << "Needs deref " << ast->s << std::endl;
01090         ast = AST::make(at_deref, ast->loc, ast);
01091       }
01092       break;
01093     }
01094 
01095   case at_uswitch:
01096   case at_try:
01097     {
01098       for (size_t c = 0; c < ast->children.size(); c++)
01099         if (c != IGNORE(ast))
01100           ast->child(c) = cl_heapify(ast->child(c));
01101       break;
01102     }
01103 
01104   default:
01105     {
01106       for (size_t c = 0; c < ast->children.size(); c++)
01107         ast->child(c) = cl_heapify(ast->child(c));
01108       break;
01109     }
01110   }
01111 
01112   return ast;
01113 }
01114 
01115 bool
01116 UocInfo::be_clconv(std::ostream& errStream,
01117                    bool init, unsigned long flags)
01118 {
01119   bool errFree = true;
01120 
01121   AstSet freeVars;
01122   AstSet boundVars;
01123 
01124   DEBUG(CLCONV) std::cerr << "findusedef 1" << std::endl;
01125 
01126   CHKERR(errFree, findusedef(errStream, uocAst, uocAst,
01127                              NULL_MODE, boundVars, freeVars));
01128 
01129   if (!errFree)
01130     return false;
01131 
01132   DEBUG(CLCONV) PrettyPrint(errStream, true);
01133 
01134   DEBUG(CLCONV) std::cerr << "cl_heapify" << std::endl;
01135   uocAst = cl_heapify(uocAst);
01136 
01137   DEBUG(CLCONV) PrettyPrint(errStream, true);
01138 
01139   DEBUG(CLCONV) std::cerr << "RandT 1" << std::endl;
01140   // Re-run the type checker to propagate the changes:
01141   CHKERR(errFree,
01142          RandT(errStream, true, REF_SYM_FLAGS, REF_TYP_FLAGS));
01143   assert(errFree);
01144 
01145   DEBUG(CLCONV) std::cerr << "findusedef 2" << std::endl;
01146 
01147   // This *shouldn't* be necessary, but it doesn't hurt anything.
01148   clearusedef(uocAst);
01149   findusedef(errStream, uocAst, uocAst, NULL_MODE,
01150              boundVars, freeVars);
01151 
01152   DEBUG(CLCONV) PrettyPrint(errStream);
01153 
01154   DEBUG(CLCONV) std::cerr << "cl_convert" << std::endl;
01155   cl_convert(shared_from_this());
01156 
01157   DEBUG(CLCONV) PrettyPrint(errStream);
01158 
01159   DEBUG(CLCONV) std::cerr << "RandT 2" << std::endl;
01160   // Re-run the type checker to propagate the changes:
01161   CHKERR(errFree,
01162          RandT(errStream, true, CL_SYM_FLAGS, CL_TYP_FLAGS));
01163 
01164   if (!errFree)
01165     std::cerr << uocAst->asString();
01166   assert(errFree);
01167 
01168   return true;
01169 }
01170 
01171 

Generated on Sat Feb 4 23:59:28 2012 for BitC Compiler by  doxygen 1.4.7