Fixinit.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 <string>
00044 #include "AST.hxx"
00045 #include "Environment.hxx"
00046 #include "Symtab.hxx"
00047 #include "Unify.hxx"
00048 #include "inter-pass.hxx"
00049 #include <sstream>
00050  
00051 using namespace sherpa;
00052 
00053 bool
00054 isTrivialInit(AST *ast)
00055 {
00056   switch(ast->astType) {
00057     
00058   case at_boolLiteral:
00059   case at_charLiteral:
00060   case at_intLiteral:
00061   case at_floatLiteral:
00062   case at_stringLiteral:
00063   case at_unit:
00064   case at_lambda:
00065     {
00066       return true;
00067     }
00068 
00069   case at_ident:
00070     {
00071       return ast->symType->isAtomic();
00072     }
00073 
00074   case at_tqexpr:
00075     {
00076       return isTrivialInit(ast->children[0]);
00077     }
00078     
00079     //case at_pair:
00080     //case at_cpair:
00081     //case at_array:
00082     //case at_struct_apply:
00083     //case at_ucon_apply: 
00084   case at_begin:
00085     {
00086       for(size_t c = 0; c < ast->children.size(); c++)
00087         if(!isTrivialInit(ast->children[c]))
00088           return false;
00089       return true;
00090     }
00091 
00092   default:
00093     return false;
00094   }
00095 }
00096 
00097 AST *
00098 FixDefs(AST *mod)
00099 {
00100   AST *newMod = new AST(mod->astType, mod->loc);
00101   for(size_t c = 0; c < mod->children.size(); c++) {    
00102     AST *ast = mod->children[c];
00103     switch(ast->astType) {
00104     case at_define:
00105       {
00106         AST *expr = ast->children[1];
00107         if(expr->astType != at_lambda) {
00108           if(!isTrivialInit(expr)) {
00109             
00110             // While the following was true, the closure conversion
00111             // also introduces a new proclaimation for everu top level
00112             // definition, and this this one bacame redundant. 
00117             //AST *defID = ast->children[0]->children[0];
00118             //AST *proclaim = new AST(at_proclaim, ast->loc,
00119             //                        defID->Use(),
00120             //                        defID->symType->asAST(ast->loc),
00121             //                        new AST(at_constraints,
00122             //                                ast->loc));
00123             //newMod->children.append(proclaim);
00124             //proclaim->Flags |= DEF_IS_INIT_AUX;
00125             //ast->Flags2 |= PROCLAIM_IS_INTERNAL;
00126 
00127             // Now build the AST that actually initializes the 
00128             // value. This is called from C code only.
00129             AST *id = AST::genSym(ast, "init");
00130             AST *ip = new AST(at_identPattern, id->loc, id);
00131             AST *argVec = new AST(at_argVec, ast->loc);
00132             AST *lam = new AST(at_lambda, ast->loc, 
00133                                      argVec, expr);
00134             AST *initDef = new AST(at_define, ast->loc, ip, lam);
00135             initDef->addChild(new AST(at_constraints));
00136             newMod->children.append(initDef);
00137             
00138             // For now, have a definition that does the APPLY to
00139             // globally initialize the value, but mark it
00140             // auxiliary. The code generator will move all these
00141             // application to the real main() routine.  I don't want
00142             // to do it as an AST transform as that will mean that I
00143             // can no longer RandT.
00144             
00145             AST *idUse = id->getDCopy();
00146             AST *app = new AST(at_apply, ast->loc, idUse);
00147             ast->children[1] = app;
00148             ast->Flags |= DEF_IS_INIT_AUX;
00149             app->Flags2 |= APP_IS_VALUE;
00150             app->Flags2 |= APP_NATIVE_FNXN;
00151             newMod->children.append(ast);
00152           }
00153           else {
00154             if(expr->astType == at_begin) {
00155               // If this is a begin block containing trivial 
00156               // (i.e. non=side-affecting) contents, then 
00157               // it can be replaced by the finall expression
00158               ast->children[1] = expr->children[expr->children.size() - 1];           
00159             }
00160             newMod->children.append(ast);
00161           }
00162         }
00163         else {
00164           newMod->children.append(ast);
00165         }
00166         break;
00167       }
00168     default:
00169       newMod->children.append(ast);
00170       break;
00171     }
00172   }
00173   return newMod;
00174 }
00175 
00176 bool
00177 fixinit(std::ostream& errStream, UocInfo *uoc)
00178 {
00179   bool errFree = true;  
00180   AST *mod = uoc->ast->children[0];
00181   uoc->ast->children[0] = FixDefs(mod);
00182   
00183   return errFree;
00184 }
00185 
00186 
00187 bool
00188 UocInfo::be_fix4c(std::ostream& errStream,
00189                   bool init, unsigned long flags)
00190 {
00191   bool errFree = true;
00192   UocInfo *uoc = &(UocInfo::linkedUoc);
00193   assert(uoc != NULL);
00194 
00195   CHKERR(errFree, fixinit(errStream, uoc));  
00196 
00197   errStream << "Fixinit AST = " << std::endl
00198            << uoc->ast->asString() << std::endl;
00199 
00200   CHKERR(errFree, RandT(errStream, uoc, true,                   
00201                         CL_SYM_FLAGS, CL_TYP_FLAGS));
00202   
00203   return errFree;
00204 }

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