c-gen.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 <stdlib.h>
00039 #include <errno.h>
00040 #include <dirent.h>
00041 #include <fstream>
00042 #include <iostream>
00043 #include <string>
00044 #include <assert.h>
00045 #include <sstream>
00046 #include "AST.hxx"
00047 #include "Type.hxx"
00048 #include "Options.hxx"
00049 #include "inter-pass.hxx"
00050 using namespace sherpa;
00051 using namespace std;
00052 
00053 extern void AlphaRename(GCPtr<AST> ast);
00054 /* FIXME later (LOOP2LETREC) */
00055 extern GCPtr<AST> loop2letrec(GCPtr<AST>);
00056 
00057 enum DeclsOrDefs {
00058   WantForward,
00059   WantDecl,
00060   WantGC,
00061   WantConstructors,
00062   WantDefs
00063 };
00064 
00065 // This is a completely sleazy way of making an automatically indenting 
00066 // stream.
00067 struct INOstream {
00068   long depth;
00069   bool needIndent;
00070   std::ostream &ostrm;
00071   void doIndent();
00072 
00073   INOstream(std::ostream &os) 
00074     :ostrm(os)
00075   {
00076     depth = 0;
00077     needIndent = true;
00078   }
00079 
00080   inline void indent(int i)
00081   {
00082     depth += i;
00083   }
00084 
00085   inline void more()
00086   {
00087     indent(2);
00088   }
00089 
00090   inline void less()
00091   {
00092     indent(-2);
00093   }
00094 };
00095 
00096 void
00097 INOstream::doIndent()
00098 {
00099   if (needIndent) {
00100     for (int i = 0; i < depth; i++) {
00101       ostrm << ' ';
00102     }
00103   }
00104   needIndent = false;
00105 }
00106 
00107 // This is where the magic happens. The way that a C++ stream recognizes
00108 // things like std::endl is by overloading this argument type. std::endl 
00109 // is actually a procedure!
00110 inline
00111 INOstream& operator<<(INOstream& inostrm, ostream& (*pf)(ostream&))
00112 {
00113   inostrm.doIndent();
00114   inostrm.ostrm << pf;
00115   if (pf == (ostream& (*)(ostream&)) std::endl)
00116     inostrm.needIndent = true;
00117   return inostrm;
00118 }
00119 
00120 inline
00121 INOstream& operator<<(INOstream& inostrm, const char *s)
00122 {
00123   inostrm.doIndent();
00124   for (size_t i = 0; i < strlen(s); i++) {
00125     if (s[i] != '\n')
00126       inostrm.ostrm << s[i];
00127     else {
00128       inostrm << std::endl;
00129     }
00130   }
00131 
00132   return inostrm;
00133 }
00134 
00135 inline
00136 INOstream& operator<<(INOstream& inostrm, const uint64_t ull)
00137 {
00138   inostrm.doIndent();
00139   inostrm.ostrm << ull;
00140 
00141   return inostrm;
00142 }
00143 
00144 inline
00145 INOstream& operator<<(INOstream& inostrm, const std::string& s)
00146 {
00147   inostrm.doIndent();
00148   for (size_t i = 0; i < s.size(); i++) {
00149     if (s[i] != '\n')
00150       inostrm.ostrm << s[i];
00151     else {
00152       inostrm << std::endl;
00153     }
00154   }
00155 
00156   return inostrm;
00157 }
00158 
00159 template<typename T>
00160 inline
00161 INOstream& operator<<(INOstream& inostrm, T ob)
00162 {
00163   inostrm.doIndent();
00164   inostrm.ostrm << ob;
00165   return inostrm;
00166 }
00167 
00169 //
00170 // Check restrictions imposed by the bootstrap backend
00171 //
00173 
00174 // Take in a binding pattern and fill a vector
00175 // with the names of all new identifiers being defined
00176 // in the pattern.
00177 
00178 bool
00179 getDefs(std::ostream& errStream, 
00180         GCPtr<AST> bp, GCPtr< CVector< GCPtr<AST> > > defs)
00181 {
00182   bool errFree = true;
00183   switch(bp->astType) {
00184   case at_identPattern:
00185     {
00186       // match agt_var   // match agt_type?
00187       defs->append(bp->children[0]);
00188       break;
00189     }
00190 
00191   case at_unitPattern:
00192     break;
00193   case at_cpairPattern:
00194   case at_pairPattern:
00195     {
00196       // match agt_valuePattern*
00197       for (size_t c = 0; c < bp->children.size(); c++)
00198         CHKERR(errFree, getDefs(errStream, bp->children[c], defs));
00199       break;
00200     }
00201 
00202   default:
00203     {
00204       errStream << bp->loc << ": "
00205                 << "Internal Compiler Error." 
00206                 << "Unexpected Binding Pattern type " 
00207                 << bp->astTypeName()
00208                 << " obtained by getDefs() routine."
00209                 << std::endl;
00210       errFree = false;
00211       break;
00212     }
00213   }
00214   return errFree;
00215 }
00216 
00217 
00218 void
00219 getDefNames(GCPtr<AST> bp, CVector<std::string>& names)
00220 {
00221   GCPtr< CVector < GCPtr<AST> > > defs = new CVector< GCPtr<AST> >;
00222 
00223   getDefs(std::cerr, bp, defs);
00224 
00225   for (size_t i = 0; i < defs->size(); i++) {
00226     GCPtr<AST> ident = (*defs)[i];
00227 
00228     names.append(ident->s);
00229   }
00230 }
00231 
00232 // Return true if, wherever /nm/ is free in /ast/, it appears exclusively
00233 // as the first argument of an application in tail position.
00234 bool
00235 pureLoop(std::ostream& errStream, const GCPtr<AST>& ast, 
00236          std::string nm, bool isTail)
00237 {
00238   bool result = true;
00239 
00240   switch(ast->astType) {
00241   case at_Null:
00242   case at_boolLiteral:
00243   case at_charLiteral:
00244   case at_intLiteral:
00245   case at_floatLiteral:
00246   case at_stringLiteral:
00247     return true;
00248 
00249   case at_ident:
00250     {
00251       if (!isTail && ast->s == nm) {
00252         errStream << ast->loc.asString()
00253                   << ": error: loop name "
00254                   << nm
00255                   << " appears in non-tail position."
00256                   << std::endl;
00257        
00258         result = false;
00259       }
00260 
00261       break;
00262     }
00263 
00264   case at_usesel:
00265     // Since the resolver passed, we know that the loop name
00266     // cannot be used in an at_usesel
00267     return true;
00268 
00269   case at_begin:
00270   case at_ibegin:
00271   {
00272     for (size_t i = 0; i < ast->children.size() - 1; i++) {
00273       GCPtr<AST> child = ast->children[i];
00274       if (!pureLoop(errStream, child, nm, false))
00275         result = false;
00276     }
00277     GCPtr<AST> child = ast->children[ast->children.size()-1];
00278     if (!pureLoop(errStream, child, nm, isTail))
00279       result = false;
00280     break;
00281   }
00282 
00283   case at_if:
00284     {
00285       GCPtr<AST> tst = ast->children[0];
00286       GCPtr<AST> thn = ast->children[1];
00287       GCPtr<AST> els = ast->children[2];
00288 
00289       if (!pureLoop(errStream, tst, nm, false))
00290         result = false;
00291       if (!pureLoop(errStream, thn, nm, isTail))
00292         result = false;
00293       if (!pureLoop(errStream, els, nm, isTail))
00294         result = false;
00295 
00296       break;
00297     }
00298 
00299   case at_apply:
00300     {
00301       for (size_t i = 0; i < ast->children.size(); i++) {
00302         GCPtr<AST> child = ast->children[i];
00303         if (!pureLoop(errStream, child, nm, (i > 0) ? false : isTail))
00304           result = false;
00305       }
00306       break;
00307     }
00308 
00309   case at_try:
00310     {
00311       // Try expr tail if try is tail
00312       if (!pureLoop(errStream, ast->children[0], nm, isTail))
00313         result = false;
00314       // case_legs tail if try is tail:
00315       if (!pureLoop(errStream, ast->children[1], nm, isTail))
00316         result = false;
00317       // otherwise tail if try is tail:
00318       if (!pureLoop(errStream, ast->children[2], nm, isTail))
00319         result = false;
00320       break;
00321     }
00322 
00323   case at_loop:
00324     {
00325       /* FIXME later (LOOP2LETREC) */
00326       GCPtr<AST> last = loop2letrec(ast);
00327       GCPtr<AST> bindings = last->children[0];
00328       GCPtr<AST> binding = bindings->children[0];
00329       GCPtr<AST> looplambda = binding->children[1];
00330 
00331       if (!pureLoop(errStream, looplambda->children[1], nm, isTail))
00332         result = false;
00333       break;
00334     }
00335 
00336   case at_let:
00337   case at_letrec:
00338     {
00339       // all of these have the form "letbindings body"
00340       GCPtr<AST> bindings = ast->children[0];
00341       GCPtr<AST> body = ast->children[1];
00342 
00343       CVector<std::string> names;
00344 
00345       // Collect all of the names defined in this binding form:
00346       for (size_t i = 0; i < bindings->children.size(); i++) {
00347         GCPtr<AST> binding = bindings->children[i];
00348         GCPtr<AST> bp = binding->children[0];
00349 
00350         getDefNames(bp, names);
00351       }
00352 
00353       bool shadowed = false;
00354 
00355       // See if the identifier of interest is being shadowed:
00356       for (size_t i = 0; i < names.size(); i++) {
00357         if (names[i] == nm) {
00358           shadowed = true;
00359           break;
00360         }
00361       }
00362 
00363       // If this is a letrec, or if the loop identifier is not
00364       // shadowed, need to check the defining expressions.
00365       if (ast->astType == at_letrec || !shadowed) {
00366         for (size_t i = 0; i < bindings->children.size(); i++) {
00367           GCPtr<AST> binding = bindings->children[i];
00368           GCPtr<AST> expr = binding->children[1];
00369 
00370           if (!pureLoop(errStream, expr, nm, false))
00371             result = false;
00372         }
00373       }
00374 
00375       // If the name is not being shadowed, need to check the body
00376       // recursively:
00377       if (!shadowed && !pureLoop(errStream, body, nm, isTail));
00378         result = false;
00379 
00380       break;
00381     }
00382 
00383   case at_case:
00384     {
00385       // FIX: This is wrong!
00386       if (!pureLoop(errStream, ast->children[0], nm, false))
00387         result = false;
00388       // case_legs tail if case is tail:
00389       if (!pureLoop(errStream, ast->children[1], nm, isTail))
00390         result = false;
00391       // otherwise tail if case is tail:
00392       if (!pureLoop(errStream, ast->children[2], nm, isTail))
00393         result = false;
00394       break;
00395     }
00396 
00397   case at_cond:
00398     {
00399       // case_legs tail if case is tail:
00400       if (!pureLoop(errStream, ast->children[0], nm, isTail))
00401         result = false;
00402       // otherwise tail if case is tail:
00403       if (!pureLoop(errStream, ast->children[1], nm, isTail))
00404         result = false;
00405       break;
00406     }
00407 
00408   case at_cond_legs:
00409   case at_case_legs:
00410     {
00411       // Children tail if parent is tail.
00412       for (size_t i = 0; i < ast->children.size(); i++) {
00413         GCPtr<AST> child = ast->children[i];
00414         if (!pureLoop(errStream, child, nm, isTail))
00415           result = false;
00416       }
00417       break;
00418     }
00419   case at_cond_leg:
00420   case at_case_leg:
00421     {
00422       // FIX: Need to check shadowing in the case leg value pattern.
00423       // Use in condition is not tail
00424       if (!pureLoop(errStream, ast->children[0], nm, false))
00425         result = false;
00426       // Use in expr tail if parent is tail
00427       if (!pureLoop(errStream, ast->children[1], nm, isTail))
00428         result = false;
00429       break;
00430     }
00431   case at_otherwise:
00432     {
00433       // Use in expr tail if parent is tail
00434       if (!pureLoop(errStream, ast->children[0], nm, isTail))
00435         result = false;
00436       break;
00437     }
00438 
00439   // If it appears under any of these, it's not in tail position:
00440   case at_and:
00441   case at_or:
00442 
00443   case at_throw:
00444   case at_setbang:
00445   case at_deref:
00446     //  case at_tuple:
00447   case at_makevector:
00448   case at_vector:
00449   case at_array:
00450     //  case at_tupleref:
00451   case at_select:
00452   case at_array_ref:
00453   case at_vector_ref:
00454   case at_array_length:
00455   case at_vector_length:
00456     {
00457       for (size_t i = 0; i < ast->children.size(); i++) {
00458         GCPtr<AST> child = ast->children[i];
00459         if (!pureLoop(errStream, child, nm, false))
00460           result = false;
00461       }
00462       break;
00463     }
00464 
00465   case at_lambda:
00466   case at_ilambda:
00467     {
00468       errStream << ast->loc.asString()
00469                 << ": error: Something is wrong. This lambda should not have"
00470                 << " survived to this pass."
00471                 << std::endl;
00472       exit(1);
00473       break;
00474     }
00475   default:
00476     {
00477       errStream << ast->loc.asString()
00478                 << ": error: Unhandled case in pureLoop()."
00479                 << std::endl;
00480       exit(1);
00481       break;
00482     }
00483   }
00484 
00485   return result;
00486 }
00487 
00488 bool
00489 hasPureLoops(std::ostream& errStream, const GCPtr<AST>& ast)
00490 {
00491   bool result = true;
00492 
00493   switch(ast->astType) {
00494   case at_loop:
00495     {
00496       /* FIXME later (LOOP2LETREC) */
00497       GCPtr<AST> last = loop2letrec(ast);
00498       GCPtr<AST> bindings = last->children[0];
00499       GCPtr<AST> binding = bindings->children[0];
00500       GCPtr<AST> idPattern = binding->children[0];
00501       GCPtr<AST> id = idPattern->children[0];
00502       GCPtr<AST> looplambda = binding->children[1];
00503       GCPtr<AST> body = last->children[1];
00504 
00505       if (!pureLoop(errStream, looplambda->children[1], id->s, true))
00506         result = false;
00507       if (!hasPureLoops(errStream, looplambda))
00508         result = false;
00509 
00510       break;
00511     }      
00512 
00513   default:
00514     {
00515       for (size_t i = 0; i < ast->children.size(); i++) {
00516         if (!hasPureLoops(errStream, ast->children[i]))
00517           result = false;
00518       }
00519       break;
00520     }
00521   }
00522 
00523 
00524   return result;
00525 }
00526 
00527 bool
00528 hasLambda(std::ostream& errStream, const GCPtr<AST>& ast)
00529 {
00530   bool result = false;
00531 
00532   if (ast->astType == at_lambda || ast->astType == at_ilambda) {
00533     errStream << ast->loc
00534               << ": Error: bootstrap backend does not support "
00535               << ast->atKwd()
00536               << " in this context."
00537               << std::endl;
00538     result = true;
00539   }
00540 
00541   // Singleton lambda in the at_loop special form is okay.
00542   if (ast->astType == at_loop) {
00543     /* FIXME later (LOOP2LETREC) */
00544     GCPtr<AST> last = loop2letrec(ast);
00545     GCPtr<AST> bindings = last->children[0];
00546     GCPtr<AST> binding = bindings->children[0];
00547     GCPtr<AST> looplambda = binding->children[1];
00548     GCPtr<AST> body = last->children[1];
00549 
00550     for (size_t i = 0; i < looplambda->children.size(); i++) {
00551       if (hasLambda(errStream, looplambda->children[i]))
00552         result = true;
00553     }
00554     if (hasLambda(errStream, body))
00555       result = true;
00556   }
00557   else {
00558     for (size_t i = 0; i < ast->children.size(); i++) {
00559       if (hasLambda(errStream, ast->children[i]))
00560         result = true;
00561     }
00562   }
00563 
00564   return result;
00565 }
00566 
00567 bool
00568 hasInnerLambdas(std::ostream& errStream, const GCPtr<AST>& ast)
00569 {
00570   bool result = false;
00571 
00572   switch(ast->astType) {
00573   case at_define:
00574     {
00575       // First child is ID, second child is value or (permitted) LAMBDA 
00576       // or ILAMBDA. Children of 2nd child should not have a lambda
00577 
00578       GCPtr<AST> expr = ast->children[1];
00579 
00580       for (size_t i = 0; i < expr->children.size(); i++) {
00581         if (hasLambda(errStream, expr->children[i]))
00582           result = true;
00583       }
00584 
00585       break;
00586     }      
00587 
00588   default:
00589     break;
00590   }
00591 
00592   for (size_t i = 0; i < ast->children.size(); i++) {
00593     if (hasInnerLambdas(errStream, ast->children[i]))
00594       result = true;
00595   }
00596 
00597   return result;
00598 }
00599 
00600 bool
00601 hasPatternBindings(std::ostream& errStream, const GCPtr<AST>& ast)
00602 {
00603   bool result = false;
00604 
00605   switch(ast->astType) {
00606   case at_define:
00607     {
00608       GCPtr<AST> bp = ast->children[0];
00609 
00610       if (ast->getType()->kind == ty_fn) {
00611       }
00612     }
00613 
00614   case at_letbinding:
00615     {
00616       GCPtr<AST> bp = ast->children[0];
00617       if (bp->astType != at_identPattern) {
00618         errStream << bp->loc.asString()
00619                   << ": Error: bootstrap backend does not support "
00620                   << "binding patterns."
00621                   << std::endl;
00622         result = true;
00623       }
00624       break;
00625     }
00626   default:
00627     break;
00628   }
00629 
00630   for (size_t i = 0; i < ast->children.size(); i++) {
00631     if (hasPatternBindings(errStream, ast->children[i]))
00632       result = true;
00633   }
00634 
00635   return result;
00636 }
00637 
00638 // Simplify certain constructs so that the code generator
00639 // has an easier time of it.
00640 static bool
00641 SimplifyAST(std::ostream& errStream, const GCPtr<AST>& ast)
00642 {
00643   bool result = true;
00644 
00645   switch(ast->astType) {
00646   case at_and:
00647   case at_or:
00648     {
00649       // Reduce and/or to max of two arguments.
00650       if (ast->children.size() > 2) {
00651         GCPtr<AST> newAST = new AST(ast->astType, ast->loc);
00652 
00653         newAST->symType = ast->symType;
00654         newAST->scheme = ast->scheme;
00655         newAST->uocInfo = ast->uocInfo;  
00656         newAST->expr = ast->expr;  
00657         newAST->isDecl = false;
00658 
00659         for (size_t ndx = 1; ndx < ast->children.size(); ndx++)
00660           newAST->children.append(ast->child(ndx));
00661 
00662         while(ast->children.size() > 2)
00663           ast->children.remove(1);
00664 
00665         ast->children[1] = newAST;
00666       }
00667 
00668       break;
00669     }
00670 
00671   default:
00672     break;
00673   }
00674 
00675   for (size_t i = 0; i < ast->children.size(); i++) {
00676     if (!SimplifyAST(errStream, ast->children[i]))
00677       result = false;
00678   }
00679 
00680   return result;
00681 }
00682 
00683 // Very important to keep this sorted (excluding the guard entry),
00684 // since it is searched with bsearch.
00685 static char *kwd_blacklist[] = {
00686   "BitcArray",                  // bitc runtime
00687   "BitcDouble_t",               // bitc runtime
00688   "BitcFloat_t",                // bitc runtime
00689   "BitcInt16_t",                // bitc runtime
00690   "BitcInt32_t",                // bitc runtime
00691   "BitcInt64_t",                // bitc runtime
00692   "BitcInt8_t",                 // bitc runtime
00693   "BitcPair",                   // bitc runtime
00694   "BitcQuad_t",                 // bitc runtime
00695   "BitcString",                 // bitc runtime
00696   "BitcUnit_t",                 // bitc runtime
00697   "BitcUns16_t",                // bitc runtime
00698   "BitcUns32_t",                // bitc runtime
00699   "BitcUns64_t",                // bitc runtime
00700   "BitcUns8_t",                 // bitc runtime
00701   "BitcVector",                 // bitc runtime
00702   "BitcWord_t",                 // bitc runtime
00703   "asm",                        // c++
00704   "auto",
00705   "bool",                       // c++, later ANSI C
00706   "break",
00707   "case",
00708   "catch",                      // c++
00709   "cdecl",                      // c++
00710   "char",
00711   "class",                      // c++
00712   "const",
00713   "const_cast",                 // c++
00714   "continue",
00715   "default",
00716   "defined",                    // some extensions
00717   "delete",                     // c++
00718   "do",
00719   "double",
00720   "dynamic_cast",               // c++
00721   "else",
00722   "entry",                      // some extensions
00723   "enum",
00724   "explicit",                   // c++
00725   "extern",
00726   "false",                      // c++, C99
00727   "far",                        // MS-DOS
00728   "float",
00729   "for",
00730   "fortran",                    // VMS extension
00731   "friend",                     // c++
00732   "generic",                    // ???
00733   "globaldef",                  // ???
00734   "globalref",                  // ???
00735   "globalvalue",                // ???
00736   "goto",
00737   "huge",                       // MS-DOS
00738   "if",
00739   "inline",
00740   "int",
00741   "int16",                      // BSD, POSIX
00742   "int32",                      // BSD, POSIX
00743   "int64",                      // BSD, POSIX
00744   "int8",                       // BSD, POSIX
00745   "interface",                  // c++ (MS)
00746   "long",
00747   "mutable",                    // c++
00748   "namespace",
00749   "near",                       // MS-DOS
00750   "new",                        // C++
00751   "operator",                   // C++
00752   "pascal",                     // VMS extension
00753   "pragma",                     // various
00754   "private",                    // c++
00755   "protected",                  // c++
00756   "public",                     // c++
00757   "quad",                       // shap
00758   "readonly",                   // various
00759   "register",
00760   "reinterpret_cast",           // c++
00761   "return",
00762   "short",
00763   "signed",
00764   "sizeof",
00765   "static",
00766   "static_cast",                // c++
00767   "string",                     // shap
00768   "struct",
00769   "super",                      // c++ (MS)
00770   "switch",
00771   "template",                   // c++
00772   "this",                       // c++
00773   "throw",                      // c++
00774   "true",                       // c++, C99
00775   "try",                        // c++
00776   "typedef",
00777   "typeid",                     // c++
00778   "typename",                   // c++
00779   "uint16",                     // BSD, POSIX
00780   "uint32",                     // BSD, POSIX
00781   "uint64",                     // BSD, POSIX
00782   "uint8",                      // BSD, POSIX
00783   "union",
00784   "unsigned",
00785   "use",
00786   "using",
00787   "virtual",                    // c++
00788   "void",
00789   "volatile",
00790   "while",
00791   "word",                       // just begging for trouble
00792 
00793 
00794   0                             // GUARD ENTRY
00795 };
00796 enum { nkwd = (sizeof(kwd_blacklist)/sizeof(kwd_blacklist[0])) - 1 };
00797 
00798 int istrcmp(const void *vp1, const void *vp2)
00799 {
00800   const char *s1 = *((const char **) vp1);
00801   const char *s2 = *((const char **) vp2);
00802   return strcmp(s1, s2);
00803 }
00804 
00805 bool is_kwd(const std::string& s)
00806 {
00807   const char *cs = s.c_str();
00808 
00809   if (bsearch(&cs, kwd_blacklist, nkwd, sizeof(kwd_blacklist[0]), istrcmp))
00810     return true;
00811   return false;
00812 }
00813 
00814 const struct MangleMap {
00815   char c;
00816   const char *s;
00817 } mangleMap[] = {
00818   { '#',  "_SH" },
00819   { '!',  "_EX" },
00820   { '$',  "_DL" },
00821   { '%',  "_PC" },
00822   { '*',  "_ST" },
00823   { '+',  "_PL" },
00824   { '\\', "_RS" },
00825   { '-',  "_HY" },
00826   { '/',  "_FS" },
00827   { '<',  "_LT" },
00828   { '>',  "_GT" },
00829   { '=',  "_EQ" },
00830   { '?',  "_QU" },
00831   { '@',  "_AT" },
00832   { '_',  "_US" },
00833   { '~',  "_TL" },
00834 
00835   // Following are introduced as a side effect of dotted names and fqns.
00836   { '.',  "::" },               // separator within IFNAME
00837 #ifdef NAMESPACE
00838   { ':',  ":" },                // handles IFNAME::IDENT
00839 #else
00840   { ':',  "__" },               // note special pattern
00841 #endif
00842 };
00843 enum { nSpecial = sizeof(mangleMap) / sizeof(MangleMap) };
00844 
00845 std::string
00846 mangleComponent(const std::string& s)
00847 {
00848   stringstream ss;
00849 
00850   for (size_t i = 0; i < s.size(); i++) {
00851     if (isalnum(s[i])) {
00852       ss << s[i];
00853     }
00854     else {
00855       size_t sp;
00856       for (sp = 0; sp < nSpecial; sp++) {
00857         if (mangleMap[sp].c == s[i]) {
00858           ss << mangleMap[sp].s;
00859           break;
00860         }
00861       }
00862 
00863       // We should have found it.
00864       assert(sp != nSpecial);
00865     }
00866   }
00867 
00868   std::string os = ss.str();
00869 #if 0
00870   return (is_kwd(os) ? ('_' + os) : os);
00871 #else
00872   return 'I' + os;
00873 #endif
00874 }
00875 
00876 static std::string
00877 xmangle(std::string s, const char *pfx)
00878 {
00879   stringstream ss;
00880 
00881   size_t pos;
00882 
00883   while((pos = s.find(".")) != std::string::npos) {
00884     ss << mangleComponent(s.substr(0, pos));
00885 #ifdef NAMESPACE
00886     ss << "::";
00887 #else
00888     ss << "__";
00889 #endif
00890     s = s.substr(pos+1);
00891   }
00892 
00893   ss << pfx;
00894   ss << mangleComponent(s);
00895 
00896   return ss.str();
00897 }
00898 
00899 static inline std::string
00900 xmangle(const FQName& fqn, const char *pfx)
00901 {
00902   return xmangle(fqn.asString("."), pfx);
00903 }
00904 
00905 static std::string 
00906 idname(GCPtr<AST> ast, const char *pfx = "")
00907 {
00908   if (ast->isGlobal())
00909     return xmangle(ast->fqn, pfx);
00910 
00911   if (ast->identFlags & ID_IS_GENSYM)
00912     return ast->s;
00913   
00914   return xmangle(ast->s, pfx);
00915 }
00916 
00917 #define CD_FNCONST   1u
00918 #define CD_IN_STRUCT 2u
00919 std::string
00920 c_decl(TvPrinter& tvp, GCPtr<Type> ty, const std::string& id,
00921        unsigned flags = 0)
00922 {
00923   stringstream ss;
00924   std::string sep = " ";
00925 
00926   ty = ty->getType();
00927 
00928   if (ty->kind == ty_mutable) {
00929     ss << c_decl(tvp, ty->components[0]->typ, id, flags & ~CD_FNCONST);
00930     return ss.str();
00931   }
00932 
00933   // Stuff that shows up BEFORE the identifier:
00934   switch(ty->kind) {
00935 
00936   case ty_bool:
00937     ss << "bool";
00938     break;
00939   case ty_char:
00940     ss << "BitcChar_t";
00941     break;
00942   case ty_string:
00943     ss << "BitcString_t *";
00944     break;
00945   case ty_int8:
00946     ss << "BitcInt8_t";
00947     break;
00948   case ty_int16:
00949     ss << "BitcInt16_t";
00950     break;
00951   case ty_int32:
00952     ss << "BitcInt32_t";
00953     break;
00954   case ty_int64:
00955     ss << "BitcInt64_t";
00956     break;
00957   case ty_uint8:
00958     ss << "BitcUns8_t";
00959     break;
00960   case ty_uint16:
00961     ss << "BitcUns16_t";
00962     break;
00963   case ty_uint32:
00964     ss << "BitcUns32_t";
00965     break;
00966   case ty_uint64:
00967     ss << "BitcUns64_t";
00968     break;
00969   case ty_word:
00970     ss << "BitcWord_t";
00971     break;
00972   case ty_float:
00973     ss << "BitcFloat_t";
00974     break;
00975   case ty_double:
00976     ss << "BitcDouble_t";
00977     break;
00978   case ty_quad:
00979     ss << "BitcQuad_t";
00980     break;
00981 
00982   case ty_bitfield:
00983     {
00984       ss << c_decl(tvp, ty->components[0]->typ, "");
00985       break;
00986     }
00987     
00988   case ty_tvar:
00989     ss << tvp.tvName(ty);
00990     break;
00991 
00992   case ty_unionv:
00993   case ty_unionr:
00994   case ty_structv:
00995   case ty_structr:
00996   case ty_closure:    
00997     {
00998       GCPtr<AST> defAst = ty->defAst;
00999       ss << idname(defAst);
01000 
01001       if (ty->typeArgs.size()) {
01002         ss << "< ";
01003         
01004         for (size_t tparam = 0; tparam < ty->typeArgs.size(); tparam++) {
01005           GCPtr<Type> targ = ty->typeArgs[tparam]->getType();
01006 
01007           if (tparam > 0)
01008             ss << ", ";
01009           ss << c_decl(tvp, targ, "");
01010         }
01011 
01012         ss << " >";
01013       }
01014       if (ty->kind == ty_unionr || 
01015           ty->kind == ty_structr ||
01016           ty->kind == ty_closure)
01017         ss << " *";
01018     }
01019     break;
01020 
01021   case ty_ref:
01022     {
01023       assert(ty->components.size() == 1);
01024       ss << "BitcRef< " << c_decl(tvp, ty->components[0]->typ, "")
01025          << " >";
01026       // ss << c_decl(tvp, ty->components[0]->typ, "*");
01027       break;
01028     }
01029 
01030   case ty_vector:
01031     {
01032       assert(ty->components.size() == 1);
01033       ss << "BitcVector< " << c_decl(tvp, ty->components[0]->typ, "")
01034          << " > *";
01035       break;
01036     }
01037 
01038   case ty_array:
01039     {
01040       assert(ty->components.size() == 1);
01041       ss << "BitcArray< " << c_decl(tvp, ty->components[0]->typ, "")
01042          << ", "
01043          << ty->components[0]->typ->getType()->arrlen
01044          << " >";
01045       break;
01046     }
01047 
01048   case ty_pair:
01049     {
01050       assert(ty->components.size() == 2);
01051       ss << "BitcPair< " 
01052          << c_decl(tvp, ty->components[0]->typ, "")
01053          << ", "
01054          << c_decl(tvp, ty->components[1]->typ, "")
01055          << " >";
01056       break;
01057     }
01058 
01059   case ty_fn:
01060     {
01061       // There is a problem here. The issue is that ty_fn is used 
01062       // both for function pointers and for actual (constant) functions, 
01063       // and we need to decipher which one we are looking at. Part
01064       // of the problem is that some type information has been lost here.
01065       //
01066       // There are two issues at hand:
01067       //
01068       // 1. It is perfectly legal for the user to write something like
01069       //
01070       //      (define f (mutable (lambda (x) ...)))
01071       //
01072       //    This form REQUIRES a pointer, but on the positive side
01073       //    the value restriction guarantees that it has no type scheme.
01074       //    This means that we can actually declare it correctly to
01075       //    C++
01076       //
01077       // 2. Unfortunately, it is ALSO perfectly legal to write something
01078       //    like
01079       //
01080       //      (define f (lambda (x) x))
01081       //
01082       //    The good news is that this is a procedure constant and can
01083       //    be declared as a normal C procedure, but the bad news is
01084       //    that it may have a type scheme.
01085       //
01086       // Ultimately, I decided to resolve this by demanding some context
01087       // from the AST.
01088 
01089       assert(ty->components.size() == 2);
01090 
01091       // Emit the return type first:
01092       ss << c_decl(tvp, ty->components[1]->typ, "");
01093 
01094       ss << ((flags & CD_FNCONST) ? " " : " (*");
01095       sep = "";
01096 
01097       break;
01098     }
01099 
01100   default:
01101     ss << "/* UNHANDLED TYPE " << ty->kindName() << " */";
01102     break;
01103   }
01104 
01105   if (id.size())
01106     ss << sep << id;
01107 
01108   // Stuff that shows up AFTER the identifier:
01109 
01110   switch(ty->kind) {
01111   case ty_bitfield:
01112     {
01113       if (flags & CD_IN_STRUCT)
01114         ss << ":" << ty->Isize;
01115       break;
01116     }
01117     
01118   case ty_fn:
01119     {
01120       ss << ((flags & CD_FNCONST) ? "(" : ")(");
01121 
01122       GCPtr<Type> fnargs = ty->components[0]->typ->getType();
01123 
01124       for (size_t i = 0; i < fnargs->components.size(); i++) {
01125         if (i > 0) ss << ", ";
01126         ss << c_decl(tvp, fnargs->components[i]->typ, "");
01127       }
01128 
01129       ss << ")";
01130 
01131       break;
01132     }
01133 
01134   case ty_bool:
01135   case ty_char:
01136   case ty_string:
01137   case ty_int8:
01138   case ty_int16:
01139   case ty_int32:
01140   case ty_int64:
01141   case ty_uint8:
01142   case ty_uint16:
01143   case ty_uint32:
01144   case ty_uint64:
01145   case ty_word:
01146   case ty_float:
01147   case ty_double:
01148   case ty_quad:
01149 
01150   case ty_tvar:
01151   case ty_unionv:
01152   case ty_unionr:
01153   case ty_structv:
01154   case ty_structr:
01155   case ty_closure:
01156   case ty_ref:
01157   case ty_vector:
01158   case ty_pair:
01159     // No post-decl output
01160     break;
01161 
01162   default:
01163     ss << "/* UNHANDLED POST-DECL " << ty->kindName() << " */";
01164     break;
01165   }
01166 
01167   return ss.str();
01168 }
01169 
01170 #if 0
01171 std::string
01172 c_name(GCPtr<AST> ast)
01173 {
01174   stringstream ss;
01175 
01176 #if 0
01177   if (ast->defn) 
01178     assert(ast = ast->defn);
01179 #endif
01180 
01181 #if 0
01182   GCPtr<Type> ty = ast->getType();
01183 
01184   if (ast->isGlobal) {
01185     switch(ty->kind) {
01186     case ty_tvar:
01187       ss << "T_";
01188       break;
01189     case ty_fn:
01190       ss << "F_";
01191       break;
01192     case ty_structv:
01193       ss << "S_";
01194       break;
01195     case ty_unionv:
01196       ss << "U_";
01197       break;
01198     case ty_structr:
01199     case ty_closure:
01200       ss << "RS_";
01201       break;
01202     case ty_unionr:
01203       ss << "RU_";
01204       break;
01205     case ty_array:
01206       ss << "V_";
01207       break;
01208     case ty_vector:
01209       ss << "V_";
01210       break;
01211     case ty_ref:
01212       ss << "V_";
01213       break;
01214     default:
01215       ss << "UNK_";
01216       break;
01217     }
01218   }
01219 #endif
01220 
01221   ss << mangle(ast);
01222 
01223   return ss.str();
01224 }
01225 #endif
01226 
01227 static std::string
01228 EmitTypeScheme(TvPrinter& tvp, const GCPtr<AST>& id, DeclsOrDefs what)
01229 {
01230   stringstream ss;
01231 
01232   const GCPtr<TypeScheme>& scm = id->scheme;
01233   if (!scm || scm->ftvs.size() == 0)
01234     return "";
01235 
01236   ss << "template<";
01237   for (size_t i = 0; i < scm->ftvs.size(); i++) {
01238     GCPtr<Type> ty = scm->ftvs[i]->getType();
01239     assert(ty->kind == ty_tvar);
01240 
01241     if (i > 0) ss << ", ";
01242     ss << "typename " << tvp.tvName(ty);
01243   }
01244   ss << ">";
01245 
01246   if (what == WantDecl)
01247     ss << "\n";
01248   else
01249     ss << " ";
01250 
01251   return ss.str();
01252 }
01253 
01254 std::string
01255 EmitTypeExpansion(TvPrinter& tvp, const GCPtr<AST>& id, DeclsOrDefs what)
01256 {
01257   stringstream ss;
01258 
01259   const GCPtr<TypeScheme>& scm = id->scheme;
01260   if (!scm || scm->ftvs.size() == 0)
01261     return "";
01262 
01263   ss << "<";
01264   for (size_t i = 0; i < scm->ftvs.size(); i++) {
01265     GCPtr<Type> ty = scm->ftvs[i]->getType();
01266     assert(ty->kind == ty_tvar);
01267 
01268     if (i > 0) ss << ", ";
01269     ss << tvp.tvName(ty);
01270   }
01271   ss << ">";
01272   return ss.str();
01273 }
01274 
01275 static void
01276 EmitExpr(INOstream& ino, TvPrinter& tvp, GCPtr<AST> ast)
01277 {
01278   switch(ast->astType) {
01279   case at_ibegin:
01280   case at_begin:
01281     {
01282       ino << "({ ";
01283       ino.indent(3);
01284 
01285       for (size_t i = 0; i < ast->children.size(); i++) {
01286         if (i > 0) ino << ", ";
01287         EmitExpr(ino, tvp, ast->child(i));
01288       }
01289 
01290       ino.indent(-3);
01291       ino << " ;})";
01292 
01293       break;
01294     }
01295 #if 0
01296   case at_identPattern:
01297     {
01298       EmitExpr(ino, tvp, ast->child(0));
01299       break;
01300     }
01301 #endif
01302 
01303   case at_ident:
01304     {
01305       ino << idname(ast);
01306       break;
01307     }
01308 
01309   case at_if:
01310     {
01311       ino << "(";
01312       EmitExpr(ino, tvp, ast->child(0));
01313       ino << std::endl;
01314       ino.more();
01315       ino << "? ";
01316       EmitExpr(ino, tvp, ast->child(1));
01317       ino << std::endl;
01318       ino << ": ";
01319       EmitExpr(ino, tvp, ast->child(2));
01320       ino << ")";
01321       ino << std::endl;
01322 
01323       ino.less();
01324       break;
01325     }
01326 
01327   case at_and:
01328     {
01329       assert(ast->children.size() == 2);
01330 
01331       ino << "({ ";
01332       ino.indent(3);
01333 
01334       ino << c_decl(tvp, ast->child(0)->getType(), "_tmp", 0);
01335       ino << " = ";
01336       EmitExpr(ino, tvp, ast->child(0));
01337       ino << ";" << std::endl;
01338 
01339       ino << "(_tmp ? ";
01340       EmitExpr(ino, tvp, ast->child(1));
01341       ino << std::endl;
01342       ino.indent(6);
01343       ino << ": _tmp) ;})";
01344       ino << std::endl;
01345       ino.indent(-6);
01346       ino.indent(-3);
01347 
01348       break;
01349     }
01350 
01351   case at_or:
01352     {
01353       assert(ast->children.size() == 2);
01354 
01355       ino << "({ ";
01356       ino.indent(3);
01357 
01358       ino << c_decl(tvp, ast->child(0)->getType(), "_tmp", 0);
01359       ino << " = ";
01360       EmitExpr(ino, tvp, ast->child(0));
01361       ino << ";" << std::endl;
01362 
01363       ino << "(_tmp ? _tmp" << std::endl;
01364       ino.indent(6);
01365       ino << ": ";
01366       EmitExpr(ino, tvp, ast->child(1));
01367       ino << ") ;})";
01368       ino << std::endl;
01369       ino.indent(-6);
01370       ino.indent(-3);
01371 
01372       break;
01373     }
01374 
01375   case at_pair:
01376   case at_cpair:
01377     {
01378       ino << "BitcPair< " 
01379           << c_decl(tvp, ast->child(0)->getType(), "")
01380           << ", "
01381           << c_decl(tvp, ast->child(1)->getType(), "")
01382           << " >(";
01383       EmitExpr(ino, tvp, ast->child(0));
01384       ino << ", ";
01385       EmitExpr(ino, tvp, ast->child(1));
01386       ino << ")";
01387       break;
01388     }
01389 
01390   case at_vector:
01391     {
01392       ino << "({ "
01393           << c_decl(tvp, ast->getType(), "")
01394           << " *_tmp;" << std::endl;
01395 
01396       ino.indent(3);
01397       ino << "void (*_markfn)("
01398           << c_decl(tvp, ast->getType(), "")
01399           << " *&) = gcMark;" << std::endl;
01400 
01401       ino << "_tmp = " 
01402           << std::endl;
01403       ino.more();
01404       ino << "( " << c_decl(tvp, ast->getType(), "") 
01405           << " *)";
01406       ino << "  allocate(sizeof(*_tmp) + sizeof("
01407           << c_decl(tvp, ast->child(0)->getType(), "")
01408           << ") * " << ast->children.size() 
01409           << ", "
01410           << "(void (*)(...))_markfn"
01411           << ");" << std::endl;
01412       ino.less();
01413 
01414       ino << "_tmp->length = " 
01415           << ast->children.size() << ";"
01416           << std::endl;
01417       
01418       for (size_t c = 0; c < ast->children.size(); c++) {
01419         ino << "_tmp->elements[" << c << "] = ";
01420         EmitExpr(ino, tvp, ast->child(c));
01421         ino << ";" << std::endl;
01422       }
01423 
01424       ino << "_tmp ;})";
01425       ino.indent(-3);
01426       break;
01427     }
01428 
01429   case at_makevector:
01430     {
01431       ino << "({ "
01432           << c_decl(tvp, ast->child(0)->getType(), "_len")
01433           << " = ";
01434       EmitExpr(ino, tvp, ast->child(0));
01435       ino << ";" << std::endl;
01436 
01437       ino.indent(3);
01438 
01439       ino << c_decl(tvp, ast->child(1)->getType(), "_e")
01440           << " = ";
01441       EmitExpr(ino, tvp, ast->child(1));
01442       ino << ";" << std::endl;
01443 
01444       ino << c_decl(tvp, ast->getType(), "")
01445           << " *_tmp;" << std::endl;
01446 
01447       ino << "void (*_markfn)("
01448           << c_decl(tvp, ast->getType(), "")
01449           << " *&) = gcMark;" << std::endl;
01450 
01451       ino << "_tmp = " 
01452           << std::endl;
01453       ino.more();
01454       ino << "( " << c_decl(tvp, ast->getType(), "") 
01455           << " *)";
01456       ino << "  allocate(sizeof(*_tmp) + sizeof("
01457           << c_decl(tvp, ast->child(1)->getType(), "")
01458           << ") * _len, "
01459           << "(void (*)(...))_markfn"
01460           << ");" << std::endl;
01461       ino.less();
01462 
01463       ino << "_tmp->length = _len;"
01464           << std::endl;
01465       
01466       ino << "for(BitcWord_t ndx = 0; ndx < _len; ndx++)"
01467           << std::endl;
01468       ino.more();
01469       ino << "_tmp->elements[ndx] = _e;" << std::endl;
01470       ino.less();
01471       
01472       ino << "_tmp ;})";
01473       ino.indent(-3);
01474       break;
01475     }
01476 
01477   case at_array:
01478     {
01479       ino << "({ "
01480           << c_decl(tvp, ast->getType(), "")
01481           << " _tmp;" << std::endl;
01482 
01483       ino.indent(3);
01484 
01485       for (size_t c = 0; c < ast->children.size(); c++) {
01486         ino << "_tmp.elements[" << c << "] = ";
01487         EmitExpr(ino, tvp, ast->child(c));
01488         ino << ";" << std::endl;
01489       }
01490 
01491       ino << "_tmp ;})";
01492       ino.indent(-3);
01493       break;
01494     }
01495 
01496   case at_array_length:
01497     {
01498       GCPtr<Type> ty = ast->child(0)->getType();
01499 
01500       ino << "({ ";
01501       EmitExpr(ino, tvp, ast->child(0));
01502       ino << "," << std::endl;
01503 
01504       ino << ty->arrlen
01505           << " ;})";
01506       break;
01507     }
01508 
01509   case at_vector_length:
01510     {
01511       ino << "({ "
01512           << c_decl(tvp, ast->child(0)->getType(), " *_tmp = ")
01513           << std::endl;
01514       ino.indent(3);
01515       ino.more();
01516       EmitExpr(ino, tvp, ast->child(0));
01517       ino << ";" << std::endl;
01518       ino.less();
01519       ino << "_tmp->length ;})";
01520       ino.indent(-3);
01521       break;
01522     }
01523   case at_array_ref:
01524     {
01525       EmitExpr(ino, tvp, ast->child(0));
01526       ino << ".elements[";
01527       EmitExpr(ino, tvp, ast->child(1));
01528       ino << "]";
01529       break;
01530     }
01531   case at_vector_ref:
01532     {
01533       EmitExpr(ino, tvp, ast->child(0));
01534       ino << "->elements[";
01535       EmitExpr(ino, tvp, ast->child(1));
01536       ino << "]";
01537       break;
01538     }
01539 
01540   case at_deref:
01541     {
01542       ino << "*(";
01543       EmitExpr(ino, tvp, ast->child(0));
01544       ino << ")";
01545       break;
01546     }
01547 
01548   case at_select:
01549     {
01550       EmitExpr(ino, tvp, ast->child(0));
01551       ino << "."
01552           << idname(ast->child(1));
01553       break;
01554     }
01555 
01556   case at_setbang:
01557     {
01558       ino << "({ "
01559           << c_decl(tvp, ast->child(0)->getType(), "& _target")
01560           << " = ";
01561       EmitExpr(ino, tvp, ast->child(0));
01562       ino << ";" << std::endl;
01563       ino.indent(3);
01564       ino << "_target = ";
01565       EmitExpr(ino, tvp, ast->child(1));
01566       ino << "; _target ;})" << std::endl;
01567       ino.indent(-3);
01568       break;
01569     }
01570 
01571   case at_charLiteral:
01572     {
01573       std::streamsize w = ino.ostrm.width();
01574       char fillChar = ino.ostrm.fill('0');
01575       
01576       ino.ostrm << right << oct;
01577 
01578       ino << "'\\";
01579       ino << ast->litValue.c;
01580       ino.ostrm << dec;
01581       ino.ostrm.width(w);
01582       ino.ostrm.fill(fillChar);
01583       ino << "'";
01584 
01585       break;
01586     }
01587 
01588   case at_boolLiteral:
01589     {
01590       ino << (ast->litValue.b
01591               ? "true" 
01592               : "false");
01593       break;
01594     }
01595 
01596   case at_intLiteral:
01597     {
01598       // An int literal is going to show up as either a ty_int
01599       // or it is one of the magical ty_struct types defined in the prelude.
01600       // In the latter case, component[0] is the type of the first
01601       // field, which is the "v" field, and *that* tells us how to
01602       // generate this.
01603 
01604       GCPtr<Type> ty = ast->getType();
01605 
01606       char valStr[mpz_sizeinbase(ast->litValue.i, 10)];
01607       mpz_get_str(valStr, 10, ast->litValue.i);
01608 
01609       assert(ty->kind != ty_structv); // legacy issue
01610       ino << valStr;
01611 
01612       break;
01613     }
01614 
01615   case at_floatLiteral:
01616     {
01617       GCPtr<Type> ty = ast->getType();
01618 
01619       // FIX: (shap) how to tell which kind?
01620       // FIX: (shap) This is flatly wrong!
01621       double d = mpf_get_d(ast->litValue.d);
01622 
01623       assert(ty->kind != ty_structv); // legacy issue
01624       ino << d;
01625 
01626       break;
01627     }
01628   case at_stringLiteral:
01629     // This one is going to need a helper function in the runtime.
01630     {
01631       // needs to initialize the vector properly...
01632       const char *s = ast->litValue.s.c_str();
01633       const char *sbegin = s;
01634 
01635       ino << "mkStringLiteral(\"";
01636       
01637       std::streamsize w = ino.ostrm.width();
01638       char fillChar = ino.ostrm.fill('0');
01639       
01640       ino.ostrm << right << oct;
01641 
01642       while ((size_t)(s - sbegin) < ast->litValue.s.size())
01643         ino << "\\" << LitValue::DecodeRawCharacter(s, &s);
01644 
01645       ino.ostrm << dec;
01646       ino.ostrm.width(w);
01647       ino.ostrm.fill(fillChar);
01648 
01649       ino << "\")";
01650 
01651       break;
01652     }
01653 
01654   case at_case:
01655   case at_cond:
01656   case at_let:
01657   case at_letrec:
01658   case at_loop:
01659   case at_throw:
01660   case at_try:
01661   case at_unit:
01662   case at_apply:
01663   case at_struct_apply:
01664   case at_ucon_apply:
01665   default:
01666     {
01667       ino << "/* AST " << ast->ID << ": " << ast->astTypeName() 
01668           << " */" << std::endl;
01669       ino << ast->astTypeName() << " IS NOT IMPLEMENTED IN EmitExpr YET"
01670           << std::endl;
01671       assert(false);
01672       break;
01673     }
01674   }
01675 }
01676 
01677 static void
01678 EmitDeclValue(INOstream& ino, GCPtr<AST> ast, DeclsOrDefs what)
01679 {
01680   if (what != WantForward)
01681     return;
01682 
01683   GCPtr<AST> id = ast->child(0);
01684 
01685   TvPrinter tvp("TV_");
01686 
01687   // If it is global and mutable, then c_decl will recursively call
01688   // itself in the ty_mutable handler in such a way as to suppress the
01689   // isFnConst argument, so it should be okay to pass it blindly here.
01690   ino << EmitTypeScheme(tvp, id, what)
01691       << "extern " << c_decl(tvp, id->getType(), idname(id), 
01692                              id->isGlobal() ? CD_FNCONST : 0)
01693       << ";" << std::endl;
01694 }
01695 
01696 static void
01697 EmitDefine(INOstream& ino, GCPtr<AST> ast, DeclsOrDefs what)
01698 {
01699   GCPtr<AST> idPattern = ast->child(0);
01700   GCPtr<AST> id = idPattern->child(0);
01701 
01702   TvPrinter tvp("TV_");
01703 
01704   if (what == WantDefs) {
01705     ino << "/* AST " << ast->ID << " " << ast->astTypeName() 
01706         << " " << id->s << " (" << id->fqn.asString() << ")"
01707         << " */" << std::endl;
01708 
01709     switch(id->getType()->kind) {
01710     case ty_fn:
01711       {
01712         GCPtr<AST> lambda = ast->child(1);
01713         GCPtr<AST> args = lambda->child(0);
01714         GCPtr<AST> body = lambda->child(1);
01715 
01716         ino << EmitTypeScheme(tvp, id, what)
01717             << c_decl(tvp, id->getType()->components[1]->typ, "")
01718             << std::endl << idname(id)
01719             << "(";
01720 
01721         for (size_t arg = 0; arg < args->children.size(); arg++) {
01722           GCPtr<AST> idPattern = args->child(arg);
01723           GCPtr<AST> id = idPattern->child(0);
01724 
01725           if (arg > 0) ino << ", ";
01726           ino << c_decl(tvp, id->getType(), idname(id));
01727         }
01728 
01729         ino << ")" << std::endl;
01730         ino << "{" << std::endl;
01731         ino.more();
01732 
01733         ino << "return ";
01734         ino.indent(7);
01735 
01736         EmitExpr(ino, tvp, body);
01737         ino << ";" << std::endl;
01738         ino.indent(-7);
01739 
01740         ino.less();
01741         ino << "}" << std::endl;
01742 
01743         ino << std::endl;
01744         break;
01745       }
01746     default:
01747       {
01748         GCPtr<AST> body = ast->child(1);
01749         ino << c_decl(tvp, id->getType(), idname(id), 
01750                       id->isGlobal() ? CD_FNCONST : 0)
01751             << " = ";
01752         EmitExpr(ino, tvp, body);
01753         ino << ";" << std::endl;
01754         break;
01755       }
01756     }
01757   }
01758   else if (what == WantDecl) {
01759     // If it is global and mutable, then c_decl will recursively call
01760     // itself in the ty_mutable handler in such a way as to suppress the
01761     // isFnConst argument, so it should be okay to pass it blindly here.
01762     ino << EmitTypeScheme(tvp, id, what)
01763         << "extern " << c_decl(tvp, id->getType(), idname(id), 
01764                                id->isGlobal() ? CD_FNCONST : 0)
01765         << ";" << std::endl;
01766   }
01767 }
01768 
01769 static void
01770 EmitDefexcept(INOstream& ino, GCPtr<AST> ast, DeclsOrDefs what)
01771 {
01772   GCPtr<AST> id = ast->child(0);
01773 
01774   // Exceptions are ALWAYS reference types!
01775   assert(id->symType->isRefType());
01776 
01777   // Note assert swapped by Swaroop
01778   // assert(id->scheme == 0);
01779   assert(id->scheme->ftvs.size() == 0);
01780 
01781   TvPrinter tvp("TV_");
01782 
01783   if (what == WantForward) {
01784     ino << "struct " << idname(id) << ";" << std::endl;
01785   }
01786   else if (what == WantDecl) {
01787     ino << "struct " << idname(id) << ":public BitcException {"
01788         << " /* " << id->fqn.asString() << " */" << std::endl;
01789 
01790     ino.more();
01791 
01792     ino << "static BitcWord_t tagValue;" << std::endl;
01793 
01794     ino << idname(id) << "()" << std::endl;
01795     ino << ": BitcException(&tagValue)" << std::endl;
01796     ino << "{ }" << std::endl;
01797 
01798     for (size_t i = 0; i < ast->children.size() - 1; i++) {
01799       GCPtr<AST> fld = ast->child(i+1);
01800 
01801       stringstream argName;
01802       argName << "arg" << i;
01803 
01804       ino << c_decl(tvp, fld->getType(), argName.str())
01805           << ";" << std::endl;
01806     }
01807 
01808     ino.less();
01809     ino << "};" << std::endl;
01810   }
01811   else if (what == WantGC) {
01812     // Emit mark routine:
01813     ino << "inline void gcMark(" << idname(id)
01814         << "*& pob"             // always a reference type
01815         << ")" << std::endl
01816         << "{" << std::endl;
01817     ino.more();
01818 
01819     if (ast->children.size() > 1) {
01820       ino << idname(id)
01821           << EmitTypeExpansion(tvp, id, what)
01822           << "& ob __attribute__((unused)) = *pob;" << std::endl;
01823 
01824       for (size_t ndx = 0; ndx < ast->children.size() - 1; ndx++) {
01825         GCPtr<AST> fld = ast->child(ndx+1);
01826 
01827         if (!fld->symType->isAtomic())
01828           ino << "gcMark(ob.arg" << ndx << ");" << std::endl;
01829       }
01830     }
01831 
01832     ino.less();
01833     ino << "}" << std::endl;
01834   }
01835   else if (what == WantConstructors) {
01836     // Emit the static, one-time declaration for the tag word:
01837     ino << "BitcWord_t " << idname(id)
01838         << "::tagValue = 0;" << std::endl;
01839 
01840     // For arity zero exceptions, we will simply use a statically
01841     // declared instance, but we do need to instantiate it:
01842     if (ast->children.size() == 1) {
01843       ino << idname(id)
01844           << " the" << idname(id)
01845           << ";" << std::endl;
01846 
01847       return;
01848     }
01849 
01850     // Below here we are handling arity > 0. 
01851 
01852     ino << "inline " << idname(id)
01853         << "* C" << idname(id) << "(";
01854 
01855     for (size_t ndx = 0; ndx < ast->children.size()-1; ndx++) {
01856       GCPtr<AST> arg = ast->child(ndx+1);
01857 
01858       stringstream ss;
01859       ss << "arg" << ndx;
01860 
01861       if (ndx > 0) ino << ", ";
01862       ino << c_decl(tvp, arg->getType(), ss.str());
01863     }
01864 
01865     ino << ")" << std::endl;
01866 
01867     ino << "{" << std::endl;
01868     ino.more();
01869 
01870     ino << "void (*_markfn)(" << idname(id)
01871         << EmitTypeExpansion(tvp, id, what)
01872         << "*&) = gcMark;" << std::endl;
01873 
01874     ino << idname(id)
01875         << "* _pInstance = (" 
01876         << idname(id)
01877         << "*)" << std::endl;
01878 
01879     ino << "  allocate(sizeof("
01880         << idname(id)
01881         << "), "
01882         << "(void (*)(...))_markfn"
01883         << ");" << std::endl;
01884 
01885     ino << idname(id)
01886         << "& _instance = *_pInstance;" << std::endl << std::endl;
01887 
01888     // Dynamically allocated BitcExceptions never get their C++
01889     // constructors run, so we need to set the tag pointer by hand.
01890     ino << "_instance.tag = &"
01891         << idname(id)
01892         << "::tagValue;" << std::endl;
01893 
01894     for (size_t ndx = 0; ndx < ast->children.size()-1; ndx++) {
01895       GCPtr<AST> arg = ast->child(ndx);
01896 
01897       ino << "_instance.arg" << ndx
01898           << " = " << "arg" << ndx
01899           << ";" << std::endl;
01900     }
01901 
01902     ino << "return &_instance;" << std::endl;
01903 
01904     ino.less();
01905     ino << "}" << std::endl;
01906   }
01907 }
01908 
01909 static void
01910 EmitDefstruct(INOstream& ino, GCPtr<AST> ast, DeclsOrDefs what)
01911 {
01912   GCPtr<AST> id = ast->child(0);
01913 
01914   //ino << "/* AST " << ast->ID << ": " << ast->astTypeName() 
01915   //<< " " << c_name(id)
01916   //<< " */" << std::endl;
01917 
01918   TvPrinter tvp("TV_");
01919 
01920   if (what == WantForward) {
01921     ino << EmitTypeScheme(tvp, id, what)
01922         << "struct " << idname(id) << ";" << std::endl;
01923 
01924     ino << EmitTypeScheme(tvp, id, what)
01925         << "extern " << idname(id,"C") << "(";
01926 
01927     GCPtr<AST> fields = ast->children[4];
01928     for (size_t i = 0; i < fields->children.size(); i++) {
01929       GCPtr<AST> field = fields->children[i];
01930       GCPtr<AST> fname = field->children[0];
01931 
01932       if (i > 0) ino << ", ";
01933       ino << c_decl(tvp, fname->getType(), "");
01934     }
01935 
01936     ino << ");" << std::endl;
01937     return;
01938   }
01939   else if (what == WantDecl) {
01940     ino << EmitTypeScheme(tvp, id, what)
01941         << "struct " << idname(id) << " {"
01942         << " /* " << id->fqn.asString() << " */" << std::endl;
01943 
01944     ino.more();
01945 
01946     GCPtr<AST> fields = ast->children[4];
01947     for (size_t i = 0; i < fields->children.size(); i++) {
01948       GCPtr<AST> field = fields->children[i];
01949       GCPtr<AST> fname = field->children[0];
01950       ino << c_decl(tvp, fname->getType(), idname(fname), CD_IN_STRUCT)
01951           << ";" << std::endl;
01952     }
01953     ino.less();
01954 
01955     ino << "};" << std::endl;
01956   }
01957   else if (what == WantGC) {
01958     GCPtr<AST> fields = ast->children[4];
01959 
01960     // Emit mark routine:
01961     ino << EmitTypeScheme(tvp, id, what)
01962         << "inline void gcMark(" << idname(id)
01963         << EmitTypeExpansion(tvp, id, what)
01964         << (id->symType->isRefType()? "*& pob" : "& ob")
01965         << ")" << std::endl
01966         << "{" << std::endl;
01967     ino.more();
01968 
01969     if (id->symType->isRefType()) {
01970       ino << idname(id)
01971           << EmitTypeExpansion(tvp, id, what)
01972           << "& ob __attribute__((unused)) = *pob;" << std::endl;
01973     }
01974 
01975     for (size_t i = 0; i < fields->children.size(); i++) {
01976       GCPtr<AST> field = fields->children[i];
01977       GCPtr<AST> fname = field->children[0];
01978 
01979       if (!fname->symType->isAtomic())
01980         ino << "gcMark(ob." << idname(fname) << ");" << std::endl;
01981     }
01982     ino.less();
01983     ino << "}" << std::endl;
01984   }
01985   else if (what == WantConstructors) {
01986     GCPtr<AST> fields = ast->children[4];
01987 
01988     // Emit constructor routine:
01989 
01990     ino << EmitTypeScheme(tvp, id, what)
01991         << "inline " << idname(id)
01992         << EmitTypeExpansion(tvp, id, what)
01993         << (id->symType->isRefType() ? "*" : "")
01994         << " "
01995         << idname(id,"C") << "(";
01996 
01997     for (size_t i = 0; i < fields->children.size(); i++) {
01998       GCPtr<AST> field = fields->children[i];
01999       GCPtr<AST> fname = field->children[0];
02000       if (i > 0) ino << ", ";
02001       ino << c_decl(tvp, fname->getType(), idname(fname));
02002     }
02003 
02004     ino << ")" << std::endl;
02005     ino << "{" << std::endl;
02006     ino.more();
02007 
02008     if (id->symType->isRefType()){
02009       ino << "void (*_markfn)(" << idname(id)
02010           << EmitTypeExpansion(tvp, id, what)
02011           << "*&) = gcMark;" << std::endl;
02012 
02013       ino << idname(id)
02014           << EmitTypeExpansion(tvp, id, what)
02015           << "* _pInstance = (" 
02016           << idname(id)
02017           << EmitTypeExpansion(tvp, id, what)
02018           << "*)" << std::endl;
02019       ino << "  allocate(sizeof("
02020           << idname(id)
02021           << EmitTypeExpansion(tvp, id, what)
02022           << "), "
02023           << "(void (*)(...))_markfn"
02024           << ");" << std::endl;
02025 
02026       ino << idname(id)
02027           << EmitTypeExpansion(tvp, id, what)
02028           << "& _instance = *_pInstance;" << std::endl;
02029     }
02030     else {
02031       ino << idname(id)
02032           << EmitTypeExpansion(tvp, id, what)
02033           << " _instance;" << std::endl;
02034     }
02035 
02036     for (size_t i = 0; i < fields->children.size(); i++) {
02037       GCPtr<AST> field = fields->children[i];
02038       GCPtr<AST> fname = field->children[0];
02039       ino << "_instance." << idname(fname)
02040           << "= " << idname(fname) << ";" << std::endl;
02041     }
02042 
02043     ino << "return "
02044         << (id->symType->isRefType() ? "&" : "")
02045         << "_instance;" << std::endl;
02046 
02047     ino.less();
02048     ino << "}" << std::endl;
02049   }
02050 }
02051 
02052 static void
02053 EmitDefunion(INOstream& ino, GCPtr<AST> ast, DeclsOrDefs what)
02054 {
02055   GCPtr<AST> id = ast->child(0);
02056   GCPtr<AST> legs = ast->children[4];
02057 
02058   //  ino << "/* AST " << ast->ID << ": " << ast->astTypeName() 
02059   //      << " " << c_name(id)
02060   //      << " */" << std::endl;
02061 
02062   TvPrinter tvp("TV_");
02063 
02064   if (what == WantForward) {
02065     ino << EmitTypeScheme(tvp, id, what)
02066         << "struct " << idname(id) << ";" << std::endl;
02067 
02068     // Swaroop had a clever idea, which was to simply predeclare all
02069     // of the arity zero constants. Unfortunately, C++ does not know
02070     // how to do templated values, so I have resorted here to the less
02071     // desirable alternative of templated procedures taking no
02072     // arguments. The constructors themselves can, at least, return
02073     // references to statically allocated instances.
02074     //
02075     // As long as they inline properly, they should all dissappear.
02076     for (size_t i = 0; i < legs->children.size(); i++) {
02077       GCPtr<AST> leg = legs->children[i];
02078       GCPtr<AST> cname = leg->children[0];
02079 
02080       ino << EmitTypeScheme(tvp, id, what)
02081           << "extern struct "
02082           << idname(id) 
02083           << ((leg->children.size() == 1) ? "& C" : " C")
02084           << idname(cname) << "(";
02085 
02086       if (leg->children.size() > 1) {
02087         for (size_t ndx = 1; ndx < leg->children.size(); ndx++) {
02088           GCPtr<AST> arg = leg->child(ndx);
02089 
02090           if (ndx > 0) ino << ", ";
02091           ino << c_decl(tvp, arg->getType(), "");
02092         }
02093       }
02094 
02095       ino << ");" << std::endl;
02096     }
02097 
02098     return;
02099   }
02100   else if (what == WantDecl) {
02101     ino << EmitTypeScheme(tvp, id, what)
02102         << "struct " << idname(id) << " {"
02103         << " /* " << id->fqn.asString() << " */" << std::endl;
02104 
02105     bool needUnion = false;
02106 
02107     ino.more();
02108 
02109     // Print the tag value enumeration:
02110     ino << "enum { " << std::endl;
02111 
02112     ino.more();
02113 
02114     for (size_t i = 0; i < legs->children.size(); i++) {
02115       GCPtr<AST> leg = legs->children[i];
02116       GCPtr<AST> cname = leg->children[0];
02117       if (leg->children.size() > 1)
02118         needUnion = true;
02119 
02120       // ino << "    " << mangle(cname->fqn.asString());
02121       ino << "tag" << idname(cname);
02122       if (i < (legs->children.size() - 1))
02123         ino << ",  ";
02124       else
02125         ino << "   ";
02126       ino << "/* "
02127           << cname->s
02128           << " */"
02129           << std::endl;
02130     }
02131 
02132     ino.less();
02133 
02134     ino << "} tag;" << std::endl;
02135 
02136     //ino << "  "
02137     //<< mangle("prelude::word")
02138     //<< " tag;" << std::endl;
02139 
02140     // In order to actually emit a union, we need to know if
02141     // any of the legs have members.
02142 
02143     if (needUnion) {
02144       ino << "union {" << std::endl;
02145 
02146       // Children of union node are it's legs:
02147 
02148       ino.more();
02149 
02150       for (size_t i = 0; i < legs->children.size(); i++) {
02151         GCPtr<AST> leg = legs->children[i];
02152         GCPtr<AST> cname = leg->children[0];
02153         if (leg->children.size() > 1) {
02154           ino << "struct {" << std::endl;
02155           ino.more();
02156 
02157           for (size_t ndx = 0; ndx < leg->children.size()-1; ndx++) {
02158             GCPtr<AST> arg = leg->child(ndx+1);
02159 
02160             stringstream argName;
02161             argName << "arg" << ndx;
02162 
02163             ino << c_decl(tvp, arg->getType(), argName.str(), CD_IN_STRUCT)
02164                 << ";" << std::endl;
02165           }
02166           ino.less();
02167           ino << "} "<< idname(cname) << ";" << std::endl;
02168         }
02169       }
02170 
02171       ino.less();
02172       ino << "} u;" << std::endl;
02173     }
02174 
02175     // Implement the static singleton instances for the arity zero
02176     // value constructors:
02177     for (size_t i = 0; i < legs->children.size(); i++) {
02178       GCPtr<AST> leg = legs->children[i];
02179       GCPtr<AST> cname = leg->children[0];
02180 
02181       if (leg->children.size() == 1)
02182         ino << "static " << idname(id) << " " 
02183             << idname(cname) << ";" << std::endl;
02184     }
02185 
02186     ino.less();
02187     ino << "};" << std::endl;
02188   }
02189   else if (what == WantGC) {
02190     GCPtr<AST> fields = ast->children[4];
02191 
02192     // Emit mark routine:
02193     ino << EmitTypeScheme(tvp, id, what)
02194         << "inline void gcMark(" << idname(id)
02195         << EmitTypeExpansion(tvp, id, what)
02196         << (id->symType->isRefType() ? "*& pob" : "& ob")
02197         << ")" << std::endl;
02198     ino << "{" << std::endl;
02199     ino.more();
02200     if (id->symType->isRefType()) {
02201       ino << idname(id)
02202           << EmitTypeExpansion(tvp, id, what)
02203           << "& ob __attribute__((unused))= *pob;" << std::endl;
02204     }
02205 
02206     ino << "switch(ob.tag) {" << std::endl;
02207 
02208     for (size_t i = 0; i < legs->children.size(); i++) {
02209       GCPtr<AST> leg = legs->children[i];
02210       GCPtr<AST> cname = leg->children[0];
02211 
02212       ino << "case " << idname(id)
02213           << EmitTypeExpansion(tvp, id, what)
02214           << "::tag" << idname(cname) << ":" << endl;
02215       ino.more();
02216       ino << "{" << std::endl;
02217       ino.more();
02218 
02219       if (leg->children.size() > 1) {
02220         for (size_t ndx = 0; ndx < leg->children.size()-1; ndx++) {
02221           GCPtr<AST> arg = leg->child(ndx+1);
02222 
02223           stringstream argName;
02224           argName << "arg" << ndx;
02225 
02226           if (!arg->symType->isAtomic())
02227             ino << "gcMark(ob.u." << idname(cname) << "."
02228                 << argName.str() << ");" << std::endl;
02229         }
02230       }
02231       ino << "break;" << std::endl;
02232 
02233       ino.less();
02234       ino << "}" << std::endl;
02235       ino.less();
02236     }
02237 
02238     ino << "}" << std::endl;
02239 
02240     ino.less();
02241     ino << "}" << std::endl;
02242 
02243   }
02244   else if (what == WantConstructors) {
02245     for (size_t i = 0; i < legs->children.size(); i++) {
02246       GCPtr<AST> leg = legs->children[i];
02247       GCPtr<AST> cname = leg->children[0];
02248 
02249       // For arity zero constructors, we will simply use
02250       // the statically declared instance, but we do need
02251       // to instantiate it:
02252       if (leg->children.size() == 1) {
02253         ino << EmitTypeScheme(tvp, id, what)
02254             << idname(id)
02255             << EmitTypeExpansion(tvp, id, what)
02256             << " " << idname(id)
02257             << EmitTypeExpansion(tvp, id, what)
02258             << "::" << idname(cname) 
02259             << " = { "
02260             << idname(id)
02261             << EmitTypeExpansion(tvp, id, what)
02262             << "::tag" << idname(cname)
02263             << " };" << std::endl;
02264 
02265         continue;
02266       }
02267 
02268       // Below here we are handling arity > 0
02269 
02270       ino << EmitTypeScheme(tvp, id, what)
02271           << "inline " << idname(id)
02272           << EmitTypeExpansion(tvp, id, what)
02273           << (id->symType->isRefType() ? "*" : "")
02274           << " C" << idname(cname) << "(";
02275 
02276       for (size_t ndx = 0; ndx < leg->children.size()-1; ndx++) {
02277         GCPtr<AST> arg = leg->child(ndx+1);
02278 
02279         stringstream ss;
02280         ss << "arg" << ndx;
02281 
02282         if (ndx > 0) ino << ", ";
02283         ino << c_decl(tvp, arg->getType(), ss.str());
02284       }
02285 
02286       ino << ")" << std::endl;
02287 
02288       ino << "{" << std::endl;
02289       ino.more();
02290 
02291       if (id->symType->isRefType()){
02292         ino << "void (*_markfn)(" << idname(id)
02293             << EmitTypeExpansion(tvp, id, what)
02294             << "*&) = gcMark;" << std::endl;
02295 
02296         ino << idname(id)
02297             << EmitTypeExpansion(tvp, id, what)
02298             << "* _pInstance = (" 
02299             << idname(id)
02300             << EmitTypeExpansion(tvp, id, what)
02301             << "*)" << std::endl;
02302 
02303         ino << "  allocate(sizeof("
02304             << idname(id)
02305             << EmitTypeExpansion(tvp, id, what)
02306             << "), "
02307             << "(void (*)(...))_markfn"
02308             << ");" << std::endl;
02309 
02310         ino << idname(id)
02311             << EmitTypeExpansion(tvp, id, what)
02312             << "& _instance = *_pInstance;" << std::endl << std::endl;
02313       }
02314       else {
02315         ino << idname(id)
02316             << EmitTypeExpansion(tvp, id, what)
02317             << " _instance;" << std::endl << std::endl;
02318       }
02319 
02320       ino << "_instance.tag = "
02321           << idname(id)
02322           << EmitTypeExpansion(tvp, id, what)
02323           << "::tag" << idname(cname)
02324           << ";" << std::endl;
02325 
02326       for (size_t ndx = 0; ndx < leg->children.size()-1; ndx++) {
02327         GCPtr<AST> arg = leg->child(ndx);
02328 
02329         ino << "_instance.u." << idname(cname) << ".arg" << ndx
02330             << " = " << "arg" << ndx
02331             << ";" << std::endl;
02332       }
02333 
02334       if (id->symType->isRefType())
02335         ino << "return &_instance;" << std::endl;
02336       else
02337         ino << "return _instance;" << std::endl;
02338 
02339       ino.less();
02340       ino << "}" << std::endl;
02341     }
02342   }
02343 }
02344 
02345 static void
02346 EmitSUDecl(INOstream& ino, GCPtr<AST> ast, DeclsOrDefs what)
02347 {
02348   if (what != WantDecl)
02349     return;
02350   // EmitDecl must recognize certain standard prelude types
02351   // as special cases.
02352 
02353   GCPtr<AST> id = ast->child(0);
02354   ino << "/* AST " << ast->ID << ": " << ast->astTypeName() 
02355       << " " << idname(id)
02356       << " */" << std::endl;
02357 }
02358 
02359 static void
02360 EmitAst(INOstream& ino, GCPtr<AST> ast, DeclsOrDefs what)
02361 {
02362   switch(ast->astType) {
02363   case at_defexception:
02364     {
02365       EmitDefexcept(ino, ast, what);
02366       break;
02367     }
02368   case at_defstruct:
02369     {
02370       EmitDefstruct(ino, ast, what);
02371       break;
02372     }
02373   case at_defunion:
02374     {
02375       EmitDefunion(ino, ast, what);
02376       break;
02377     }
02378   case at_define:
02379     {
02380       EmitDefine(ino, ast, what);
02381       break;
02382     }
02383 
02384   case at_declValue:
02385     {
02386       EmitDeclValue(ino, ast, what);
02387       break;
02388     }
02389 
02390   case at_declunionr:
02391   case at_declstructr:
02392     {
02393       EmitSUDecl(ino, ast, what);
02394       break;
02395     }
02396 
02397   default:
02398     {
02399       ino << "/* AST " << ast->ID << ": " << ast->astTypeName() 
02400           << " */" << std::endl;
02401       break;
02402     }
02403   }
02404 }
02405 
02406 static void
02407 GenerateInterface(INOstream& ino, const GCPtr<UocInfo> &uoc, 
02408                   DeclsOrDefs what)
02409 {
02410   assert(uoc->ast->children.size() == 2);
02411   assert(uoc->ast->child(0)->astType == at_version);
02412 
02413   GCPtr<AST> srcmod = uoc->ast->child(1);
02414 
02415   assert((srcmod->astType == at_module) ||
02416          (srcmod->astType == at_interface));
02417 
02418   // An at_interface's first child is an at_ident giving the if_name.
02419   // Skip that.
02420   for (size_t i = (srcmod->astType == at_interface) ? 1 : 0;
02421        i < srcmod->children.size(); i++) {
02422     GCPtr<AST> ast = srcmod->child(i);
02423     
02424     EmitAst(ino, ast, what);
02425   }
02426 }
02427 
02428 bool
02429 CheckBootstrapConstraints(std::ostream& errStream, const GCPtr<UocInfo> &uoc)
02430 {
02431   bool ok = true;
02432 
02433   if (hasPatternBindings(errStream, uoc->ast))
02434     ok = false;
02435 
02436   if(hasInnerLambdas(errStream, uoc->ast))
02437     ok = false;
02438 
02439   if(!hasPureLoops(errStream, uoc->ast))
02440     ok = false;
02441 
02442   return ok;
02443 }
02444 
02445 #if 0
02446 void
02447 GenerateC(std::ostream& out, const GCPtr<UocInfo> &uoc)
02448 {
02449 #if 0
02450   if(!escapeCheck(uoc->ast)) {
02451     out << "Exiting due to errors during escape analysis." 
02452         << std::endl;
02453     exit(1);
02454   }
02455 #endif
02456 
02457   INOstream ino(out);
02458 
02459   ino << "namespace " << mangle(uoc->ifName) << " {" << std::endl;
02460   ino.more();
02461 
02462   GenerateInterface(ino, uoc, WantDecls);
02463 
02464   ino.less();
02465   ino << "} /* namespace " << mangle(uoc->ifName) << " */;" << std::endl;
02466 
02467   GenerateInterface(ino, uoc, WantDefs);
02468 }
02469 #endif
02470 
02471 bool
02472 GenerateC()
02473 {
02474   for(size_t i = 0; i < UocInfo::ifList.size(); i++) {
02475     GCPtr<UocInfo> uoc = UocInfo::ifList[i];
02476 
02477     if (!CheckBootstrapConstraints(std::cerr, uoc)) {
02478       std::cerr << "Errors found during bootstrap constraint check of " 
02479                 << uoc->path
02480                 << std::endl;
02481       return false;
02482     }
02483 
02484     if (!SimplifyAST(std::cerr, uoc->ast)) {
02485       std::cerr << "Unable to simplify AST for code generation in " 
02486                 << uoc->path
02487                 << std::endl;
02488       return false;
02489     }
02490 
02491     AlphaRename(uoc->ast);
02492   }
02493 
02494   for(size_t i = 0; i < UocInfo::srcList.size(); i++) {
02495     GCPtr<UocInfo> uoc = UocInfo::srcList[i];
02496 
02497     if (!CheckBootstrapConstraints(std::cerr, uoc)) {
02498       std::cerr << "Errors found during bootstrap constraint check of " 
02499                 << uoc->path
02500                 << std::endl;
02501       return false;
02502     }
02503 
02504     if (!SimplifyAST(std::cerr, uoc->ast)) {
02505       std::cerr << "Unable to simplify AST for code generation in " 
02506                 << uoc->path
02507                 << std::endl;
02508       return false;
02509     }
02510 
02511     AlphaRename(uoc->ast);
02512   }
02513 
02514   if (Options::outputFileName.size() == 0)
02515     Options::outputFileName = "/dev/stdout";
02516 
02517   std::ofstream out(Options::outputFileName.c_str(),
02518                     std::ios_base::out|std::ios_base::trunc);
02519   
02520   if (!out.is_open()) {
02521     std::cerr << "Couldn't open output file \""
02522               << Options::outputFileName
02523               << "\" -- "
02524               << strerror(errno)
02525               << "\n";
02526     exit(1);
02527   }
02528 
02529   INOstream ino(out);
02530 
02531   ino << "#include \""
02532       << BITCCDIR
02533       << "/BitcRuntime.hxx\"" << std::endl;
02534 
02535 #if 0
02536   // Emit forward declarations for all interfaces:
02537   for(size_t i = 0; i < UocInfo::ifList.size(); i++) {
02538     GCPtr<UocInfo> uoc = UocInfo::ifList[i];
02539 
02540     ino << "namespace " << mangle(uoc->ifName) << " {" << std::endl;
02541     ino.more();
02542 
02543     GenerateInterface(ino, uoc, WantForward);
02544 
02545     ino.less();
02546     ino << "} /* namespace " << mangle(uoc->ifName) << " */;" << std::endl;
02547   }
02548 
02549   // .. and for all sources:
02550   for(size_t i = 0; i < UocInfo::srcList.size(); i++) {
02551     GCPtr<UocInfo> uoc = UocInfo::srcList[i];
02552 
02553     ino << "namespace " << mangle(uoc->ifName) << " {" << std::endl;
02554     ino.more();
02555 
02556     GenerateInterface(ino, uoc, WantForward);
02557 
02558     ino.less();
02559     ino << "} /* namespace " << mangle(uoc->ifName) << " */;" << std::endl;
02560   }
02561 #endif
02562 
02563   // Emit declarations for all interfaces and sources:
02564   for(size_t i = 0; i < UocInfo::ifList.size(); i++) {
02565     GCPtr<UocInfo> uoc = UocInfo::ifList[i];
02566 
02567 #ifdef NAMESPACE
02568     ino << "namespace " << xmangle(uoc->ifName) << " {" << std::endl;
02569     ino.more();
02570 #endif
02571 
02572     GenerateInterface(ino, uoc, WantDecl);
02573 
02574 #ifdef NAMESPACE
02575     ino.less();
02576     ino << "} /* namespace " << xmangle(uoc->ifName) << " */;" << std::endl;
02577 #endif
02578   }
02579 
02580   for(size_t i = 0; i < UocInfo::srcList.size(); i++) {
02581     GCPtr<UocInfo> uoc = UocInfo::srcList[i];
02582 
02583 #ifdef NAMESPACE
02584     ino << "namespace " << xmangle(uoc->ifName) << " {" << std::endl;
02585     ino.more();
02586 #endif
02587 
02588     GenerateInterface(ino, uoc, WantDecl);
02589 
02590 #ifdef NAMESPACE
02591     ino.less();
02592     ino << "} /* namespace " << xmangle(uoc->ifName) << " */;" << std::endl;
02593 #endif
02594   }
02595 
02596   // Emit GC routines for all interfaces and sources:
02597   for(size_t i = 0; i < UocInfo::ifList.size(); i++) {
02598     GCPtr<UocInfo> uoc = UocInfo::ifList[i];
02599 
02600     GenerateInterface(ino, uoc, WantGC);
02601   }
02602 
02603   for(size_t i = 0; i < UocInfo::srcList.size(); i++) {
02604     GCPtr<UocInfo> uoc = UocInfo::srcList[i];
02605 
02606     GenerateInterface(ino, uoc, WantGC);
02607   }
02608 
02609   // Emit constructor implementations for all interfaces and sources:
02610   for(size_t i = 0; i < UocInfo::ifList.size(); i++) {
02611     GCPtr<UocInfo> uoc = UocInfo::ifList[i];
02612 
02613 #ifdef NAMESPACE
02614     ino << "namespace " << xmangle(uoc->ifName) << " {" << std::endl;
02615     ino.more();
02616 #endif
02617 
02618     GenerateInterface(ino, uoc, WantConstructors);
02619 
02620 #ifdef NAMESPACE
02621     ino.less();
02622     ino << "} /* namespace " << xmangle(uoc->ifName) << " */;" << std::endl;
02623 #endif
02624   }
02625 
02626   for(size_t i = 0; i < UocInfo::srcList.size(); i++) {
02627     GCPtr<UocInfo> uoc = UocInfo::srcList[i];
02628 
02629 #ifdef NAMESPACE
02630     ino << "namespace " << xmangle(uoc->ifName) << " {" << std::endl;
02631     ino.more();
02632 #endif
02633 
02634     GenerateInterface(ino, uoc, WantConstructors);
02635 
02636 #ifdef NAMESPACE
02637     ino.less();
02638     ino << "} /* namespace " << xmangle(uoc->ifName) << " */;" << std::endl;
02639 #endif
02640   }
02641 
02642   // FIX: This needs to move into the runtime support library.
02643   ino << "/* HELPER ROUTINE */" << std::endl;
02644   // Emit a special helper routine to deal with string literals:
02645   ino << "BitcString_t *" << std::endl;
02646   ino << "mkStringLiteral(const char *s)" << std::endl;
02647   ino << "{" << std::endl;
02648   ino.more();
02649   ino << "size_t len = strlen(s);" << std::endl;
02650   ino << "void (*markfn)(BitcString_t *&) = gcMark;" << std::endl;
02651   ino << std::endl;
02652   ino << "BitcString_t *tmp =" << std::endl;
02653   ino.more();
02654   ino << "(BitcString_t *) allocate(sizeof(BitcString_t) "
02655       << "+ sizeof(tmp->s[0]) * len," 
02656       << std::endl;
02657   ino << "                  (void (*)(...)) markfn);" << std::endl;
02658   ino.less();
02659 
02660   ino << "tmp->length = len;" << std::endl;
02661   ino << "for(size_t i = 0; i < len; i ++)" << std::endl;
02662   ino.more();
02663   ino << "tmp->s[i] = s[i];" << std::endl;
02664   ino.less();
02665 
02666   ino << "return tmp;" << std::endl;
02667 
02668   ino.less();
02669   ino << "}";
02670 
02671   // Emit definitions for all interfaces and sources:
02672   for(size_t i = 0; i < UocInfo::ifList.size(); i++) {
02673     GCPtr<UocInfo> uoc = UocInfo::ifList[i];
02674 
02675     GenerateInterface(ino, uoc, WantDefs);
02676   }
02677 
02678   for(size_t i = 0; i < UocInfo::srcList.size(); i++) {
02679     GCPtr<UocInfo> uoc = UocInfo::srcList[i];
02680 
02681     GenerateInterface(ino, uoc, WantDefs);
02682   }
02683 
02684   // Just for testing:
02685 #ifdef NAMESPACE
02686   ino << "using namespace Iprelude;" << std::endl;
02687   ino << std::endl;
02688 #endif
02689   ino << "int main(int argc, char *argv[])" << std::endl;
02690   ino << "{" << std::endl;
02691   ino.more();
02692   ino << "BitcInt32_t i = 1;" << std::endl;
02693   ino << "BitcChar_t  c = 'c';" << std::endl;
02694   ino << "BitcFloat_t f = 3.414;" << std::endl;
02695   ino << std::endl;
02696 #ifdef NAMESPACE
02697   ino << "(void) Icgen::CIstr3(i, c, f);" << std::endl;
02698 #else
02699   ino << "(void) Icgen__CIstr3(i, c, f);" << std::endl;
02700 #endif
02701   ino << std::endl;
02702   ino << "majorGC();" << std::endl;
02703   ino.less();
02704   ino << "}" << std::endl;
02705   return true;
02706 }
02707           

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