Simplify.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 "AST.hxx"
00050 #include "Type.hxx"
00051 #include "inter-pass.hxx"
00052 
00053 using namespace boost;
00054 using namespace sherpa;
00055 
00056 // This pass exists to support GC. The idea is to ensure that every
00057 // temporary result has an entry in the stack frame so that it doesn't
00058 // get lost in collection. We do this by "let introduction". That is,
00059 // any time we see an application (including value constructions) such
00060 // as:
00061 //
00062 //   (e1 e2 e3 e4)
00063 //
00064 // we rewrite it (recursively) into:
00065 //
00066 //   (let ((tmp (e1 e2 e3 e4))) tmp)
00067 //
00068 // Doing this naively would turn
00069 //
00070 //    (let ((v (e1 e2))) ...)
00071 //
00072 // into
00073 //
00074 //    (lst ((v (let ((tmp (e1 e2))) tmp))) ...)
00075 //
00076 // so we handle the initializer expression in a let as a special case.
00077 //
00078 // The purpose of this pass is procedure frame construction.  Here is
00079 // an example. Consider:
00080 //
00081 //   (e1 (e2 e3)) =>
00082 //
00083 //   (let ((tmp1 (e1 (let ((tmp2 (e2 e3))) tmp2)))) tmp1) =>
00084 //
00085 //   (make-frame (tmp1 tmp2)
00086 //     ...
00087 //     (begin
00088 //       (set! tmp1 (e1 (begin (set! tmp2 (e2 e3)) tmp2)))
00089 //       tmp1)
00090 //     ...)
00091 //
00092 // which is uglier than sin, but easily compiled (and reordered).
00093 //
00094 // For purposes of this rewrite, string literals are considered
00095 // applications.
00096 //
00097 // NOTE that this pass takes a by-reference argument, and performs
00098 // its re-writing IN PLACE.
00099 
00100 static unsigned long ltmpCounter = 0;
00101 
00102 static shared_ptr<AST> 
00103 LetWrap(shared_ptr<AST> ast)
00104 {
00105   std::stringstream ss;
00106   ss << "_ltmp" << ltmpCounter++;
00107 
00108   shared_ptr<AST> let = AST::make(at_let, ast->loc);
00109   shared_ptr<AST> letBindings = AST::make(at_letbindings, ast->loc);
00110   shared_ptr<AST> binding = AST::make(at_letbinding, ast->loc);
00111   shared_ptr<AST> idPattern = AST::make(at_identPattern, ast->loc);
00112   shared_ptr<AST> id = AST::make(at_ident, ast->loc);
00113   shared_ptr<AST> useid = AST::make(at_ident, ast->loc);
00114 
00115   let->addChild(letBindings);
00116   let->addChild(useid);
00117   let->addChild(AST::make(at_constraints));
00118 
00119   letBindings->addChild(binding);
00120 
00121   binding->addChild(idPattern);
00122   binding->addChild(ast);
00123 
00124   idPattern->addChild(id);
00125 
00126   useid->s = id->s = ss.str();
00127   useid->flags |=  ID_IS_GENSYM;
00128   id->flags |= ID_IS_GENSYM;
00129   useid->identType = id->identType = id_value;
00130   assert(!ast->scheme);
00131   //  useid->scheme = id->scheme = ast->scheme;
00132   useid->symType = id->symType = ast->symType;
00133   useid->symbolDef = id;
00134   useid->fqn.ident = id->fqn.ident = id->s;
00135 
00136   return let;
00137 }
00138 
00139 // MakeFrame -- walk a lambda, looking for LET bindings. Hoist the
00140 // locals into a call frame structure, and rewrite the LET using
00141 // BEGIN and SET!.
00142 void
00143 MakeFrame(shared_ptr<AST> ast, shared_ptr<AST> frameBindings)
00144 {
00145   switch(ast->astType) {
00146   case at_let:
00147     ast->astType = at_begin;
00148     break;
00149 
00150   case at_letbinding:
00151     {
00152       assert(ast->child(0)->astType = at_identPattern);
00153 
00154       // Add the identPattern entry to the frame -- just go ahead and
00155       // alias it.
00156       frameBindings->addChild(ast->child(0));
00157 
00158       // Re-write the letbinding as a set!:
00159       ast->astType = at_setbang;
00160       ast->symType = ast->child(0)->symType;
00161     }
00162   default:
00163     break;
00164   }
00165 
00166   // Do the children recursively
00167   for (size_t i = 0; i < ast->children.size(); i++) {
00168     MakeFrame(ast->child(i), frameBindings);
00169   }
00170 }
00171 
00172 
00173 void
00174 LetInsert(shared_ptr<AST> ast, bool skip = false)
00175 {
00176   switch(ast->astType) {
00177   case at_apply:
00178   case at_struct_apply:
00179   case at_object_apply:
00180   case at_ucon_apply:
00181     {
00182       //      bool needRewrite = false;
00183 
00184       // First, figure out if we require a rewrite:
00185       for (size_t c = 0; c < ast->children.size(); c++) {
00186         shared_ptr<AST> child = ast->child(c);
00187         LetInsert(child);
00188       }
00189 
00190       if (!skip)
00191         ast = LetWrap(ast);
00192 
00193       break;
00194     }
00195 
00196   case at_letbinding:
00197     {
00198       LetInsert(ast->child(1), 
00199                 (ast->child(0)->astType == at_identPattern));
00200       break;
00201     }
00202   default:
00203     break;
00204   }
00205 
00206   for (size_t i = 0; i < ast->children.size(); i++) {
00207     LetInsert(ast->child(i));
00208   }
00209 }

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