TypeValRes.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 #include <sstream>
00046 
00047 #include <libsherpa/UExcept.hxx>
00048 
00049 #include "UocInfo.hxx"
00050 #include "AST.hxx"
00051 #include "Type.hxx"
00052 #include "TypeInfer.hxx"
00053 #include "TypeScheme.hxx"
00054 #include "TypeMut.hxx"
00055 #include "Typeclass.hxx"
00056 #include "inter-pass.hxx"
00057 #include "Unify.hxx"
00058 
00059 using namespace boost;
00060 using namespace sherpa;
00061 using namespace std;
00062 
00063 
00064 #define CHKEXP(itsExpansive, exp) do {\
00065 bool ans = (exp);\
00066 if (ans == true) \
00067  (itsExpansive) = true; \
00068 }while (0)
00069            
00070 // Shap has tripped on the term "expansive" for years. What
00071 // "expansive" means is that term substitution might result in a term
00072 // that requires more evaluation steps than the original term. That
00073 // is, it violates the downward deconstructive induction intuition. A
00074 // discussion of the term "expansive" can probably be found in the ML
00075 // book or the value restriction paper.
00076 
00077 // FIX: I am not clear why an identifier is intrinsically considered
00078 // expansive, since many identifiers are bound to compile-time deeply 
00079 // immutable values and these can be viewed as term
00080 // substitutions. Handling them in this way would let many of the
00081 // special cases below collapse.
00082 // Swaroop: Identifiers are intrinsically NOT expansive. This code
00083 // only detects applications as expansive. I think I am missing your
00084 // point.
00085 
00086 bool
00087 isExpansive(std::ostream& errStream, 
00088             shared_ptr<const TSEnvironment > gamma,
00089             shared_ptr<const AST> ast) 
00090 {
00091   bool itsExpansive = false;
00092   
00093   switch (ast->astType) {
00094   case at_intLiteral:
00095   case at_floatLiteral:
00096   case at_boolLiteral:
00097   case at_charLiteral:
00098   case at_stringLiteral:
00099   case at_lambda:
00100   case at_sizeof:
00101   case at_bitsizeof:
00102     {
00103       itsExpansive = false;
00104       break;
00105     }
00106 
00107   case at_apply:
00108     {
00109       itsExpansive = true;
00110       break;
00111     }
00112   case at_setbang:
00113     {
00114       itsExpansive = true;
00115       break;
00116     }
00117 
00118   case at_allocREF:
00119   case at_mkClosure:
00120   case at_ident:
00121   case at_fill:
00122   case at_usesel:
00123   case at_dup:
00124   case at_docString:
00125     {
00126       itsExpansive = false;
00127       break;
00128     }
00129 
00130   case at_letStar:
00131   case at_let:
00132   case at_letrec:
00133     {
00134       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00135                                        ast->child(0)));
00136       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00137                                        ast->child(1)));
00138       break;
00139     }
00140 
00141   case at_copyREF:
00142   case at_setClosure:
00143   case at_letbindings:
00144   case at_loopbindings:
00145     {
00146       for (size_t i=0; !itsExpansive && i < ast->children.size(); i++)
00147         CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00148                                          ast->child(i)));
00149       break;
00150     }
00151 
00152   case at_letbinding:
00153     {
00154       itsExpansive = isExpansive(errStream, gamma,
00155                                  ast->child(1));
00156       break;
00157     }
00158 
00159   case at_loopbinding:
00160     {
00161       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00162                                        ast->child(1)));
00163       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00164                                        ast->child(2)));
00165       break;
00166     }
00167 
00168   case at_try:
00169   case at_throw:
00170   case at_labeledBlock:
00171   case at_return_from:
00172 #if 0
00173     {
00174       itsExpansive = true;
00175       break;
00176     }
00177 #endif
00178   case at_loop:
00179   case at_looptest:
00180   case at_begin:
00181     {
00182       for (size_t i=0; !itsExpansive && i < ast->children.size(); i++)
00183         CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00184                                          ast->child(i)));
00185       break;
00186     }
00187 
00188   case at_suspend:
00189     {
00190       itsExpansive = isExpansive(errStream, gamma,
00191                                   ast->child(1));
00192       break;
00193     }
00194 
00195   case at_typeAnnotation:
00196     {
00197       itsExpansive = isExpansive(errStream, gamma,
00198                                   ast->child(0));
00199       break;
00200     }
00201 
00202   case at_if:
00203     {
00204       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00205                                        ast->child(0)));
00206       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00207                                        ast->child(1)));
00208       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00209                                        ast->child(2)));
00210       break;
00211     }
00212 
00213   case at_when:
00214   case at_unless:
00215     {
00216       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00217                                        ast->child(0)));
00218       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00219                                        ast->child(1)));
00220       break;
00221     }
00222 
00223   case at_cond:
00224     {
00225       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00226                                        ast->child(0)));
00227       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00228                                        ast->child(1)));
00229       break;
00230     }
00231 
00232   case at_cond_legs:
00233     {
00234       for (size_t i=0; !itsExpansive && i < ast->children.size(); i++)
00235         CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00236                                          ast->child(i)));
00237       break;
00238     }
00239 
00240   case at_cond_leg:
00241     {
00242       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00243                                        ast->child(1)));
00244       break;
00245     }
00246     
00247   case at_condelse:
00248     {
00249       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00250                                        ast->child(0)));
00251       break;
00252     }
00253 
00254   case at_uswitch:
00255     {
00256       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00257                                        ast->child(2)));
00258       if (ast->child(3)->astType != at_Null)
00259         CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00260                                          ast->child(3)));
00261       break;
00262     }
00263 
00264   case at_otherwise:
00265   case at_usw_leg:
00266     {
00267       // expr is at the same position
00268       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00269                                        ast->child(1)));
00270       break;
00271     }
00272     
00273   case at_unit:
00274     break;
00275 
00276   case at_MakeVector:             
00277     {
00278       /* Make vector takes a lambda as the second argument, but
00279          implicitely performs application on it possibly 
00280          multiple times */ 
00281       itsExpansive = true;        
00282       break;
00283     }
00284     
00285   case at_letGather:
00286   case at_vector:
00287   case at_array:
00288   case at_mkArrayRef:
00289 #ifdef HAVE_INDEXABLE_LENGTH_OPS
00290   case at_array_length:
00291   case at_array_ref_length:
00292   case at_vector_length:
00293 #endif
00294   case at_array_nth:
00295   case at_array_ref_nth:
00296   case at_vector_nth:
00297   case at_inner_ref:
00298   case at_deref:
00299   case at_usw_legs:
00300   case at_and:
00301   case at_or:
00302     {
00303       for (size_t i=0; !itsExpansive && i < ast->children.size(); i++)
00304         CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00305                                          ast->child(i)));
00306       break;
00307     }
00308   case at_nth:
00309     // Shouldn't get here
00310     assert(false);
00311     break;
00312     
00313   case at_fqCtr:
00314     {
00315       itsExpansive = false;
00316       break;
00317     }
00318 
00319   case at_select:
00320   case at_sel_ctr:
00321     {
00322       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00323                                        ast->child(0)));      
00324       break;
00325     }
00326 
00327   case at_struct_apply:
00328   case at_object_apply:
00329   case at_ucon_apply:
00330     {
00331       for (size_t i=1; !itsExpansive && i < ast->children.size(); i++)
00332         CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00333                                          ast->child(i)));
00334       break;
00335     }
00336    
00337   case at_container:
00338     {
00339         CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00340                                          ast->child(1)));
00341         break;
00342     }
00343     
00344   case at_tcapp:
00345     {
00346       // Special case to facilitate generalization 
00347       // of instance declarations
00348       itsExpansive = false;
00349       break;
00350     }
00351     
00352   case at_unboxedCat:
00353   case at_boxedCat:
00354   case at_oc_closed:
00355   case at_oc_open:
00356   case at_opaqueCat:
00357   case agt_category:
00358   case at_module:
00359   case at_define:
00360   case at_recdef:
00361   case at_defrepr:
00362   case at_defstruct:
00363   case at_defunion:
00364   case at_declrepr:
00365   case at_declstruct:
00366   case at_declunion:
00367   case at_declares:
00368   case at_declare:
00369   case at_tvlist:
00370   case at_constructors:
00371   case at_constructor:
00372   case at_fields:
00373   case at_field:
00374   case at_fieldType:
00375   case at_methdecl:
00376   case at_bitfieldType:
00377   case at_arrayRefType:
00378   case at_byRefType:
00379   case at_boxedType:
00380   case at_exceptionType:
00381   case at_dummyType:
00382   case at_unboxedType:
00383   case at_fn:
00384   case at_primaryType:
00385   case at_arrayType:
00386   case at_vectorType:
00387   case at_mutableType:
00388   case at_constType:
00389   case at_typeapp:
00390   case at_qualType:
00391   case at_methType:
00392   case at_constraints:
00393   case at_identPattern:
00394   case at_Null:
00395   case at_AnyGroup:
00396   case agt_literal:
00397   case agt_tvar:
00398   case agt_var:
00399   case agt_definition:
00400   case agt_type_definition:
00401   case agt_value_definition:
00402   case agt_uselhs:
00403   case agt_type:
00404   case agt_openclosed:
00405     //case at_reprbody:
00406     //case at_reprcase:
00407     //case at_reprcaselegR:
00408     //case at_reprtag:
00409     //case agt_reprbodyitem:
00410   case at_reprctrs:
00411   case at_reprctr:
00412   case at_reprrepr:
00413   case agt_expr:
00414   case agt_expr_or_define:
00415   case agt_eform:
00416   case at_proclaim:
00417   case at_interface:
00418   case at_importAs:
00419   case at_provide:
00420   case at_import:
00421   case at_ifsel:
00422   case agt_CompilationUnit:
00423   case at_defexception:
00424   case at_deftypeclass:
00425   case at_tcdecls:
00426   case at_tyfn:
00427   case at_method_decls:
00428   case at_method_decl:
00429   case at_definstance:
00430   case at_tcmethods:
00431   case at_tcmethod_binding:
00432   case agt_tc_definition:
00433   case agt_if_definition:
00434   case agt_ow:
00435   case agt_qtype:
00436   case agt_fielditem:
00437   case at_ifident:
00438   case at_argVec:
00439   case at_fnargVec:
00440   case at_localFrame:
00441   case at_frameBindings:
00442   case at_identList:
00443   case agt_ucon:
00444     {
00445       errStream << ast->loc << ": "
00446                 << "Internal Compiler Error." 
00447                 << "Unexpected ast-type " << ast->tagName()
00448                 << " obtained by isExpansive() routine."
00449                 << std::endl;
00450       itsExpansive = true; // be conservative ...
00451       break;
00452     }
00453   }
00454   return itsExpansive;
00455 }
00456 
00457 
00458 // Is this AST a Syntactic value? 
00459 // Permitted cases are literals, functions, value constructors that
00460 // take no arguments, and the special case of array-length.
00461 // This function must only be passed an expresssion AST.
00462 // It returns false (rather than asserting false) if an unexpected AST
00463 // like type-AST, group AST or at_Null is passed.
00464 bool
00465 isAValue(shared_ptr<const AST> ast) 
00466 {
00467   switch (ast->astType) {
00468   case at_unit:
00469   case at_boolLiteral:
00470   case at_charLiteral:
00471   case at_intLiteral:
00472   case at_floatLiteral:
00473   case at_stringLiteral:
00474   case at_lambda:
00475   case at_sizeof:
00476   case at_bitsizeof:
00477   case at_mkClosure:
00478   case at_ident:
00479   case at_usesel:
00480     return true;
00481     
00482   case at_typeAnnotation:
00483     return isAValue(ast->child(0));
00484     
00485 #ifdef HAVE_INDEXABLE_LENGTH_OPS
00486   case at_array_length:
00487     // This should have just been TRUE, since it always reduces to a
00488     // constant.
00489     return isAValue(ast->child(0));
00490 #else
00491   case at_select:
00492     {
00493       shared_ptr<Type> t = ast->child(0)->symType->getBareType();
00494       if (t->typeTag == ty_array)
00495         return true;
00496       else
00497         return false;
00498     }
00499 #endif
00500     
00501   default:
00502     return false;
00503   }
00504 }
00505 
00506 bool
00507 isExpansive(std::ostream& errStream, 
00508             shared_ptr<const TSEnvironment > gamma,
00509             shared_ptr<Type> typ) 
00510 {
00511   bool itsExpansive = false;
00512   shared_ptr<Type> t = typ->getType();
00513   
00514   if (t->mark & MARK_PREDICATE)
00515     return itsExpansive;
00516 
00517   t->mark |= MARK_PREDICATE;
00518 
00519   switch(t->typeTag) {
00520   case ty_unit:
00521   case ty_bool:
00522   case ty_char:
00523   case ty_string:
00524   case ty_int8:
00525   case ty_int16:
00526   case ty_int32:
00527   case ty_int64:
00528   case ty_uint8:
00529   case ty_uint16:
00530   case ty_uint32:
00531   case ty_uint64:
00532   case ty_word:
00533   case ty_float:
00534   case ty_double:
00535   case ty_quad:
00536   case ty_field:
00537     
00538   case ty_tvar:
00539   case ty_dummy:
00540   case ty_kvar:
00541   case ty_kfix:
00542     
00543 #ifdef KEEP_BF
00544   case ty_bitfield:
00545 #endif
00546   case ty_fn:
00547   case ty_method:
00548   case ty_typeclass:
00549     break;
00550 
00551   case ty_tyfn:
00552   case ty_fnarg:
00553   case ty_byref:
00554     assert(false); // Function case breaks
00555     break;
00556 
00557   case ty_letGather:
00558   case ty_array:
00559   case ty_array_ref:
00560   case ty_vector:
00561     for (size_t i=0; i<t->components.size(); i++) 
00562       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00563                                        t->CompType(i)));
00564     break;
00565 
00566   case ty_structv:
00567   case ty_structr:
00568   case ty_unionv: 
00569   case ty_unionr:
00570   case ty_uconv:
00571   case ty_uconr:
00572   case ty_uvalv:
00573   case ty_uvalr:
00574   case ty_mbFull:
00575   case ty_mbTop:
00576   case ty_pcst:
00577   case ty_ref:
00578   case ty_exn:
00579     {    
00580       for (size_t i=0; i<t->typeArgs.size(); i++) 
00581         CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00582                                          t->TypeArg(i)));
00583     
00584       for (size_t i=0; i<t->components.size(); i++) 
00585         CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00586                                          t->CompType(i)));
00587       break;
00588     }
00589 
00590   case ty_const:
00591     {
00592       CHKEXP(itsExpansive, isExpansive(errStream, gamma,
00593                                        t->Base()->minimizeMutability()));
00594       break;
00595     }
00596     
00597   case ty_mutable:
00598     {
00599       itsExpansive = true;
00600       break;
00601     }
00602   }
00603   
00604   t->mark &= ~MARK_PREDICATE;
00605   return itsExpansive;
00606 }

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