TopInit.cxx

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright (C) 2008, Johns Hopkins University.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or
00007  * without modification, are permitted provided that the following
00008  * conditions are met:
00009  *
00010  *   - Redistributions of source code must contain the above 
00011  *     copyright notice, this list of conditions, and the following
00012  *     disclaimer. 
00013  *
00014  *   - Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions, and the following
00016  *     disclaimer in the documentation and/or other materials 
00017  *     provided with the distribution.
00018  *
00019  *   - Neither the names of the copyright holders nor the names of any
00020  *     of any contributors may be used to endorse or promote products
00021  *     derived from this software without specific prior written
00022  *     permission. 
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  **************************************************************************/
00037 
00038 #include <assert.h>
00039 #include <stdint.h>
00040 #include <stdlib.h>
00041 #include <dirent.h>
00042 #include <fstream>
00043 #include <iostream>
00044 #include <string>
00045 
00046 #include "AST.hxx"
00047 #include "Environment.hxx"
00048 #include "inter-pass.hxx"
00049 
00050 using namespace boost;
00051 using namespace sherpa;
00052  
00053 /* 
00054    Notes:
00055    1) This pass assumes successful completion of Symbol Resolution. 
00056 
00057    2) This pass deals with Values definitions only.
00058       That is, it does not deal with 
00059         - Constructor Visibility
00060         - Type variable scoping
00061 
00062    3) For top-level definitions, the environment pointer refers to: 
00063         - The definition if available in scope
00064         - The declaration if no definition is available in scope.
00065 
00066       Therefore, if a source module defined an implementation for a
00067       declaration in an interface, 
00068         - Only the provider for that definition will have a pointer
00069           to the defintion
00070         - The interface and all other importers/providers will have a
00071             pointer to the declaration.
00072 
00073    4) We still need the ID_OBSERV_DEF flag (and cannot just rely on
00074       whether the env points to decl/def) because in the case of
00075       recursive definitions, the env of first definition points to
00076       definition even tough it is not observably completely defined. 
00077 
00078    5) We will mark the definitions ID_OBSERV_DEF only after full
00079       checking. It is OK to mark it in the AST.
00080       In the interface/provider case above, the definition will be
00081       marked ID_OBSERV_DEF in the provider source module, where it is
00082       a valid initializer. All others will refer to the declaration,
00083       which will never be marked ID_OBSERV_DEF.
00084 
00085    6) The only way mutually recursive defintions can be ID_OBSERV_DEF
00086       is by using other mutually recursive definitions within a
00087       lambda form.
00088 
00089    7) This pass need not assume the incompleteness check if run after
00090       type checker. 
00091         - Defintions like:
00092             (letrec ((a b)
00093                      (b a)) ... ) 
00094           will fail due to the observably defined check.
00095         - Definitions like
00096             (let rec ((a (lambda () b))
00097                       (b a)) ... )
00098           will fail to type check.
00099 */
00100 
00101 enum pop_type {
00102   pop_none,
00103   pop_sclar,
00104   pop_intFl,
00105   pop_int
00106 };
00107 
00108 #define CHOOSE(a, b) do { \
00109     if (ast->s == #a)          \
00110       return b;                  \
00111   }while (0)
00112 
00113 static pop_type
00114 primOp(shared_ptr<AST> ast)
00115 {
00116   if ((ast->astType != at_ident) || 
00117      (!ast->symbolDef->isGlobal()))
00118     return pop_none;
00119 
00120   CHOOSE(==, pop_sclar);
00121   CHOOSE(!=, pop_sclar);
00122   CHOOSE(<, pop_sclar);
00123   CHOOSE(>, pop_sclar);
00124   CHOOSE(<=, pop_sclar);
00125   CHOOSE(>=, pop_sclar);
00126   CHOOSE(+, pop_intFl);
00127   CHOOSE(-, pop_intFl);
00128   CHOOSE(*, pop_intFl);
00129   CHOOSE(/, pop_intFl);
00130   CHOOSE(%, pop_int);
00131   return pop_none;
00132 }
00133 
00134 //WARNING: **REQUIRES** errStream, errFree.
00135 #define TOPINIT(ast, flags)                                        \
00136   CHKERR(errFree, TopInit((errStream), (ast), (flags)));        
00137 
00138 
00139 bool
00140 TopInit(std::ostream& errStream, 
00141         shared_ptr<AST> ast, 
00142         unsigned long flags)
00143 {
00144   bool errFree = true;
00145 
00146   switch(ast->astType) {
00147   case at_boxedCat:
00148   case at_unboxedCat:
00149   case at_oc_closed:
00150   case at_oc_open:
00151   case at_opaqueCat:
00152   case agt_category:
00153   case at_AnyGroup:
00154   case agt_literal:
00155   case agt_tvar:
00156   case agt_var:
00157   case agt_definition:
00158   case agt_type:
00159   case agt_expr:
00160   case agt_expr_or_define:
00161   case agt_eform:
00162   case agt_type_definition:
00163     //case agt_reprbodyitem:
00164   case agt_value_definition:
00165   case agt_CompilationUnit:
00166   case agt_tc_definition:
00167   case agt_if_definition:
00168   case agt_ow:
00169   case agt_openclosed:
00170   case at_localFrame:
00171   case at_frameBindings:
00172   case at_identList:
00173   case at_container:
00174   case agt_qtype:
00175   case agt_fielditem:
00176   case agt_uselhs:
00177   case at_defrepr:
00178     //case at_reprbody:
00179     //case at_reprcase:
00180     //case at_reprcaselegR:
00181     //case at_reprtag:
00182   case at_reprctrs:
00183   case at_reprctr:
00184   case at_reprrepr:
00185   case at_docString:
00186   case at_letGather:
00187   case agt_ucon:
00188 
00189   case at_usesel:
00190   case at_allocREF:
00191   case at_mkClosure:
00192   case at_copyREF:
00193   case at_setClosure:
00194   case at_argVec:
00195     {
00196       assert(false);
00197       break;
00198     }
00199 
00200   case at_Null: 
00204 
00205     // switch contains at_Null of otherwise clause is absent. 
00206   case at_defunion:
00207   case at_defstruct:
00208   case at_declunion:
00209   case at_declstruct:
00210   case at_declrepr:
00211   case at_tvlist:
00212   case at_constructors:
00213   case at_constructor:
00214   case at_fields:
00215   case at_field:
00216   case at_methdecl:
00217   case at_fill:
00218   case at_proclaim:
00219   case at_defexception:
00220   case at_deftypeclass:
00221   case at_tcdecls:
00222   case at_tyfn:
00223   case at_tcapp:
00224   case at_method_decls:
00225   case at_method_decl:
00226   case at_definstance:
00227   case at_tcmethods:
00228   case at_tcmethod_binding:
00229   case at_ifident:
00230   case at_importAs:
00231   case at_provide:
00232   case at_import:
00233   case at_ifsel:
00234   case at_declares:
00235   case at_declare:
00236   case at_suspend:
00237   case at_bitfieldType:
00238   case at_boxedType:
00239   case at_unboxedType:
00240   case at_arrayRefType:
00241   case at_byRefType:
00242   case at_fn:
00243   case at_fnargVec:
00244   case at_primaryType:
00245   case at_fieldType:
00246   case at_arrayType:
00247   case at_vectorType:
00248   case at_exceptionType:
00249   case at_dummyType:
00250   case at_mutableType:
00251   case at_constType:
00252   case at_typeapp:
00253   case at_qualType:
00254   case at_methType:
00255   case at_constraints:
00256     break;
00257     
00258   case at_boolLiteral:
00259   case at_charLiteral:
00260   case at_intLiteral:
00261   case at_floatLiteral:
00262   case at_stringLiteral:
00263   case at_unit:
00264   case at_lambda:
00265   case at_sizeof:
00266   case at_bitsizeof:
00267     break;
00268 
00269   case at_ident:
00270     {
00271       // We must only deal with value definitions.
00272       assert(ast->isIdentType(id_value));
00273       
00274       if (ast->isTcMethod())
00275         break;
00276       
00277       shared_ptr<AST> def = ast->symbolDef;
00278       if (!def) {
00279         // Defining Occurence.
00280         // This loop MUST only enter the ident case ONLY for 
00281         //  definitions that are _observably defined_.
00282         assert(!ast->isDecl);
00283         ast->flags |= ID_OBSERV_DEF;
00284       }
00285       else {
00286         // Constructors like `nil'.
00287         if (def->isUnionLeg())
00288           break;
00289 
00290         if ((def->flags & ID_OBSERV_DEF) == 0) {
00291           errStream << ast->loc << ": "
00292                     << "Identifier " << ast->s
00293                     << " is not observably defined, "
00294                     << "but is used in an initializing expression"
00295                     << std::endl;
00296           errFree = false;
00297         }
00298       }
00299       break;
00300     }
00301     
00302   case at_interface:
00303     {
00304       // match agt_definition*
00305       for (size_t c = 1; c < ast->children.size(); c++)
00306         TOPINIT(ast->child(c), flags);
00307 
00308       break;
00309     }
00310 
00311   case at_module:
00312     {
00313       // match agt_definition*
00314       for (size_t c = 0; c < ast->children.size(); c++)
00315         TOPINIT(ast->child(c), flags);
00316       
00317       break;
00318     }
00319     
00320   case at_define:
00321   case at_recdef:
00322     {
00323       TOPINIT(ast->child(1), flags);      
00324 
00325       if (errFree)
00326         TOPINIT(ast->child(0), flags);
00327       
00328       break;
00329     }
00330 
00331   case at_fqCtr:
00332     break;
00333 
00334   case at_identPattern:
00335   case at_typeAnnotation:
00336   case at_select:
00337   case at_sel_ctr:
00338     {
00339       TOPINIT(ast->child(0), flags);
00340       break;
00341     }
00342 
00343   case at_array:
00344   case at_labeledBlock:
00345   case at_return_from:
00346   case at_vector:
00347   case at_MakeVector:
00348   case at_mkArrayRef:
00349   case at_begin:
00350 #ifdef HAVE_INDEXABLE_LENGTH_OPS
00351   case at_array_length:
00352   case at_array_ref_length:
00353   case at_vector_length:
00354 #endif
00355   case at_array_nth:
00356   case at_array_ref_nth:
00357   case at_vector_nth:
00358   case at_if:
00359   case at_when:
00360   case at_unless:
00361   case at_and:
00362   case at_or:
00363   case at_throw:
00364   case at_cond:
00365   case at_cond_legs:
00366   case at_cond_leg:
00367   case at_condelse:
00368   case at_dup:
00369   case at_deref:
00370   case at_inner_ref:
00371   case at_usw_legs:
00372   case at_let:
00373   case at_letrec:    
00374   case at_letStar:
00375   case at_letbindings:
00376   case at_loop:
00377   case at_looptest:
00378   case at_loopbindings:
00379   case at_loopbinding:
00380     {
00381       for (size_t c = 0; c < ast->children.size(); c++)
00382         TOPINIT(ast->child(c), flags);
00383       
00384       break;
00385     }
00386 
00387   case at_nth:
00388     // Shouldn't get here
00389     assert(false);
00390     break;
00391 
00392   case at_try:
00393   case at_uswitch:
00394     {
00395       for (size_t c = 0; c < ast->children.size(); c++)
00396         if (c != IGNORE(ast))
00397           TOPINIT(ast->child(c), flags);
00398       break;
00399     }
00400     
00401   case at_struct_apply:
00402   case at_ucon_apply: 
00403   case at_object_apply: 
00404     {
00405       for (size_t c = 1; c < ast->children.size(); c++)
00406         TOPINIT(ast->child(c), flags);
00407       
00408       break;
00409     }
00410     
00411   case at_apply:
00412     { 
00413       
00414       pop_type pop = primOp(ast->child(0));
00415       switch(pop) {
00416       case pop_sclar:
00417         for (size_t i=1; i < ast->children.size(); i++)
00418           if (!ast->child(0)->symType->isScalar()) {
00419             errFree = false;
00420             break;
00421           }
00422         break;
00423 
00424       case pop_intFl:
00425         for (size_t i=1; i < ast->children.size(); i++)
00426           if (!ast->child(0)->symType->isPrimInt() &&
00427              !ast->child(0)->symType->isPrimFloat()) {
00428             errFree = false;
00429             break;
00430           }
00431         break;
00432 
00433       case pop_int:
00434         for (size_t i=1; i < ast->children.size(); i++)
00435           if (!ast->child(0)->symType->isPrimInt()) {
00436             errFree = false;
00437             break;
00438           }
00439         break;
00440 
00441       case pop_none:
00442         errFree = false;
00443         break;
00444       }
00445 
00446       if (!errFree)
00447         errStream << ast->loc << ": "
00448                   << "This kind of application is not "
00449                   << " a valid Initializer." 
00450                   << std::endl;
00451       break;
00452     }
00453     
00454   case at_setbang:
00455     {
00456       errStream << ast->loc << ": "
00457                 << "set! is not a valid Initializer."
00458                 << std::endl;
00459       errFree = false;
00460       break;
00461     }
00462 
00463   case at_usw_leg:
00464   case at_otherwise:
00465     {
00466       // The identifier that binds the copy is observably defined.
00467       TOPINIT(ast->child(0), flags);
00468       TOPINIT(ast->child(1), flags);
00469     }
00470     
00471   case at_letbinding:
00472     {
00473       TOPINIT(ast->child(1), flags);
00474       if (errFree)
00475         TOPINIT(ast->child(0), flags);
00476       break;
00477     }
00478   }
00479   return errFree;
00480 }
00481 
00482 bool
00483 UocInfo::fe_initCheck(std::ostream& errStream,
00484                       bool init, unsigned long flags)
00485 {
00486   return true;
00487 
00488   bool errFree = true;
00489   CHKERR(errFree, TopInit(errStream, uocAst, flags));
00490   
00491   return errFree;
00492 }
00493 
00494  

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