gen-c.cxx

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright (C) 2010, Jonathan S. Shapiro
00004  * Portions Copyright (C) 2008, Johns Hopkins University.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or
00008  * without modification, are permitted provided that the following
00009  * conditions are met:
00010  *
00011  *   - Redistributions of source code must contain the above
00012  *     copyright notice, this list of conditions, and the following
00013  *     disclaimer.
00014  *
00015  *   - Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions, and the following
00017  *     disclaimer in the documentation and/or other materials
00018  *     provided with the distribution.
00019  *
00020  *   - Neither the names of the copyright holders nor the names of any
00021  *     of any contributors may be used to endorse or promote products
00022  *     derived from this software without specific prior written
00023  *     permission.
00024  *
00025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00026  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00027  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00028  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00029  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00030  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00031  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00032  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00033  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00034  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00035  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036  *
00037  **************************************************************************/
00038 
00039 #include "../config.h"
00040 
00041 #include <stdint.h>
00042 #include <stdlib.h>
00043 #include <dirent.h>
00044 #include <errno.h>
00045 #include <fstream>
00046 #include <iostream>
00047 #include <string>
00048 #include <set>
00049 #include <sstream>
00050 #include <cctype>
00051 
00052 #ifdef HAVE_SYS_WAIT_H
00053 #include <sys/wait.h>
00054 #endif
00055 
00056 #include <libsherpa/utf8.hxx>
00057 #include <libsherpa/INOstream.hxx>
00058 #include <libsherpa/BigNum.hxx>
00059 #include <boost/filesystem/operations.hpp>
00060 
00061 #include "config.h"
00062 
00063 #include "Version.hxx"
00064 #include "Options.hxx"
00065 #include "UocInfo.hxx"
00066 #include "AST.hxx"
00067 #include "Environment.hxx"
00068 #include "inter-pass.hxx"
00069 #include "backend.hxx"
00070 
00071 #define TOC_HEADER_MODE 0x01u
00072 
00073 using namespace std;
00074 using namespace boost;
00075 using namespace boost;
00076 using namespace sherpa;
00077 
00078 const char *TY_PFX   = "ty_";
00079 const char *CTOR_PFX = "ct_";
00080 const char *CVAL_PFX = "val_";
00081 const char *TAG_PFX  = "tag_";
00082 const char *ENUM_PFX = "en_";
00083 const char *ARG_PFX  = "arg_";
00084 const char *RET_PFX  = "ret_";
00085 const char *ENV_PFX  = "env_"; // Environment argument
00086 const char *XFN_PFX  = "xfn_"; // transition function for closures
00087 const char *MFN_PFX  = "mfn_"; // Real Function (label) in the case of
00088                                // mutable top-level functions.
00089 const char *WFN_PFX  = "wfn_"; // If a immutable function-pointer is
00090                                // not a lambda, we will emit a
00091                                // wrapper-label function with the true
00092                                // name. This prifix is for the inner
00093                                // function (that actually does all the
00094                                // word).
00095 const char *LBL_PFX   = "__escape___"; // Name of the C-label at
00096                                        // labeled-return
00097 
00098 #if 0
00099 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00100 // As of now, ALL identifiers that the use has input will be mangled
00101 // to have a leading _ so I don't need to check for keywords, unless
00102 // the implementer is careless enough to generate names that collide
00103 // with the C keywords. If this *ever* happens, re-enable this check.
00104 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00105 
00106 // Very important to keep this sorted (excluding the guard entry),
00107 // since it is searched with bsearch.
00108 static char *kwd_blacklist[] = {
00109   "asm",                        // c++
00110   "auto",
00111   "bitc_bool_t",                // bitc runtime
00112   "bitc_char_t",                // bitc runtime
00113   "bitc_double_t",                // bitc runtime
00114   "bitc_float_t",                // bitc runtime
00115   "bitc_int16_t",                // bitc runtime
00116   "bitc_int32_t",                // bitc runtime
00117   "bitc_int64_t",                // bitc runtime
00118   "bitc_int8_t",                // bitc runtime
00119   "bitc_quad_t",                // bitc runtime
00120   "bitc_string",                // bitc runtime
00121   "bitc_uns16_t",                // bitc runtime
00122   "bitc_uns32_t",                // bitc runtime
00123   "bitc_uns64_t",                // bitc runtime
00124   "bitc_uns8_t",                // bitc runtime
00125   "bitc_vector",                // bitc runtime
00126   "bitc_word_t",                // bitc runtime
00127   "bool",                        // c++, later ANSI C
00128   "break",
00129   "case",
00130   "catch",                        // c++
00131   "cdecl",                        // c++
00132   "char",
00133   "class",                        // c++
00134   "const",
00135   "const_cast",                        // c++
00136   "continue",
00137   "default",
00138   "defined",                        // some extensions
00139   "delete",                        // c++
00140   "do",
00141   "double",
00142   "dynamic_cast",                // c++
00143   "else",
00144   "entry",                        // some extensions
00145   "enum",
00146   "explicit",                        // c++
00147   "extern",
00148   "false",                        // c++, C99
00149   "far",                        // MS-DOS
00150   "float",
00151   "for",
00152   "fortran",                        // VMS extension
00153   "friend",                        // c++
00154   "generic",                        // ???
00155   "globaldef",                        // ???
00156   "globalref",                        // ???
00157   "globalvalue",                // ???
00158   "goto",
00159   "huge",                        // MS-DOS
00160   "if",
00161   "inline",
00162   "int",
00163   "int16",                        // BSD, POSIX
00164   "int32",                        // BSD, POSIX
00165   "int64",                        // BSD, POSIX
00166   "int8",                        // BSD, POSIX
00167   "interface",                        // c++ (MS)
00168   "long",
00169   "mutable",                        // c++
00170   "namespace",
00171   "near",                        // MS-DOS
00172   "new",                        // C++
00173   "operator",                        // C++
00174   "pascal",                        // VMS extension
00175   "pragma",                        // various
00176   "private",                        // c++
00177   "protected",                        // c++
00178   "public",                        // c++
00179   "quad",                        // shap
00180   "readonly",                        // various
00181   "register",
00182   "reinterpret_cast",                // c++
00183   "return",
00184   "short",
00185   "signed",
00186   "sizeof",
00187   "static",
00188   "static_cast",                // c++
00189   "string",                        // shap
00190   "struct",
00191   "super",                        // c++ (MS)
00192   "switch",
00193   "template",                        // c++
00194   "this",                        // c++
00195   "throw",                        // c++
00196   "true",                        // c++, C99
00197   "try",                        // c++
00198   "typedef",
00199   "typeid",                        // c++
00200   "typename",                        // c++
00201   "uint16",                        // BSD, POSIX
00202   "uint32",                        // BSD, POSIX
00203   "uint64",                        // BSD, POSIX
00204   "uint8",                        // BSD, POSIX
00205   "union",
00206   "unsigned",
00207   "use",
00208   "using",
00209   "virtual",                        // c++
00210   "void",
00211   "volatile",
00212   "while",
00213   "word",                        // just begging for trouble
00214 
00215 
00216   0                                // GUARD ENTRY
00217 };
00218 
00219 enum { nkwd = (sizeof(kwd_blacklist)/sizeof(kwd_blacklist[0])) - 1 };
00220 
00221 bool
00222 is_kwd(const std::string& s)
00223 {
00224   const char *cs = s.c_str();
00225 
00226   // &OK
00227   if (bsearch(&cs, kwd_blacklist, nkwd, sizeof(kwd_blacklist[0]),
00228               ((int (*)(const void*, const void*)) strcmp)))
00229     return true;
00230   return false;
00231 }
00232 #endif
00233 
00234 // Very important that none of these ever use _UC, because that is our
00235 // prefix for a unicode character encoding.
00236 const struct MangleMap {
00237   char c;
00238   const char *s;
00239 } mangleMap[] = {
00240   { '#',  "_SH" },
00241   { '!',  "_EX" },
00242   { '$',  "_DL" },
00243   { '%',  "_PC" },
00244   { '*',  "_ST" },
00245   { '+',  "_PL" },
00246   { '\\', "_RS" },
00247   { '-',  "_HY" },
00248   { '/',  "_FS" },
00249   { '<',  "_LT" },
00250   { '>',  "_GT" },
00251   { '=',  "_EQ" },
00252   { '?',  "_QU" },
00253   { '@',  "_AT" },
00254   { '~',  "_TL" },
00255   { ':',  "_CN" },
00256   { '_',  "_" },                // THIS IS HORRIBLE!
00257   { '.',  "_DT"},
00258   { '\'', "_QT" }
00259 };
00260 enum { nSpecial = sizeof(mangleMap) / sizeof(MangleMap) };
00261 
00262 const char *
00263 punctMangle(uint32_t codePoint)
00264 {
00265   for (size_t sp = 0; sp < nSpecial; sp++) {
00266     if (mangleMap[sp].c == (char) codePoint) {
00267       return mangleMap[sp].s;
00268     }
00269   }
00270 
00271   return 0;
00272 }
00273 
00274 std::string
00275 CMangle(std::string idName)
00276 {
00277   std::stringstream ss;
00278   const char *s = idName.c_str();
00279 
00280   while (*s) {
00281     const char *snext;
00282     uint32_t codePoint = sherpa::utf8_decode(s, &snext);
00283     const char *pm;
00284 
00285     if (isalnum(codePoint)) {
00286       ss << *s;
00287     }
00288     else if ((pm=punctMangle(codePoint))) {
00289       ss << pm;
00290     }
00291     else {
00292       ss << "_UC"
00293          << hex
00294          << codePoint
00295          << dec
00296          << "_";
00297     }
00298     s = snext;
00299   }
00300 
00301   return ss.str();
00302 }
00303 
00304 #define CMGL_ID_FLD 0x1u
00305 std::string
00306 CMangle(shared_ptr<AST> ast, unsigned long flags = 0)
00307 {
00308   assert(ast->astType == at_ident);
00309 
00310   shared_ptr<AST> id = ast;
00311 
00312   if (id->symbolDef)
00313     id = id->symbolDef;
00314 
00315   if (id->isDecl && (id->defn))
00316     id = id->defn;
00317 
00318   if (id->externalName.size())
00319     return id->externalName;
00320 
00321   std::stringstream ss;
00322   if ((id->flags & ID_IS_GLOBAL) ||
00323      (id->flags & ID_IS_GENSYM) ||
00324      (flags & CMGL_ID_FLD))
00325     ss << id->s;
00326   else
00327     ss << id->s << "#" << id->ID;
00328   string idName = ss.str();
00329 
00330   return CMangle(ss.str());
00331 }
00332 
00333 /* Forward Declaration */
00334 bool
00335 toc(std::ostream& errStream, shared_ptr<UocInfo> uoc,
00336     shared_ptr<AST> ast, INOstream &out, const string &IDname,
00337     set<string> &decls,
00338     shared_ptr<AST> parent,
00339     const size_t chno, unsigned long flags);
00340 
00341 #define CTYP_EMIT_BF      0x01u        // bitfield
00342 #define CTYP_BYREF        0x02u // Used to declare by-ref
00343                                 // arguments in decl() routine.
00344 
00345 static string
00346 toCtype(shared_ptr<Type> typ, string IDname="", unsigned long flags=0,
00347         uint64_t arrsz = 0)
00348 {
00349   shared_ptr<Type> t = typ->getBareType();
00350   stringstream out;
00351 
00352   switch(t->typeTag) {
00353   case ty_tvar:
00354     {
00355       // This case is not wrong; for example, consider
00356       // (define (main) (throw Xn) (the int32 10))
00357       // The intermediate result that holds (throw Xn)
00358       // has no concrete type.
00359       out << "bitc_tvar_t";
00360       break;
00361     }
00362 
00363   case ty_mbTop:
00364   case ty_mbFull:
00365     out << toCtype(t->Core(), IDname, flags, arrsz);
00366     break;
00367 
00368   case ty_mutable:
00369     out << toCtype(t->Base(), IDname, flags, arrsz);
00370     break;
00371     
00372   case ty_const:
00373     out << toCtype(t->Base(), IDname, flags, arrsz);
00374     break;
00375     
00376   case ty_dummy:
00377     // Dummy types fixed to unit
00378   case ty_unit:
00379     out << "bitc_unit_t";
00380     break;
00381 
00382   case ty_bool:
00383     out << "bitc_bool_t";
00384     break;
00385   case ty_char:
00386     out << "bitc_char_t";
00387     break;
00388   case ty_string:
00389     out << "bitc_string_t *";
00390     break;
00391   case ty_int8:
00392     out << "bitc_int8_t";
00393     break;
00394   case ty_int16:
00395     out << "bitc_int16_t";
00396     break;
00397   case ty_int32:
00398     out << "bitc_int32_t";
00399     break;
00400   case ty_int64:
00401     out << "bitc_int64_t";
00402     break;
00403   case ty_uint8:
00404     out << "bitc_uns8_t";
00405     break;
00406   case ty_uint16:
00407     out << "bitc_uns16_t";
00408     break;
00409   case ty_uint32:
00410     out << "bitc_uns32_t";
00411     break;
00412   case ty_uint64:
00413     out << "bitc_uns64_t";
00414     break;
00415   case ty_word:
00416     out << "bitc_word_t";
00417     break;
00418   case ty_float:
00419     out << "bitc_float_t";
00420     break;
00421   case ty_double:
00422     out << "bitc_double_t";
00423     break;
00424   case ty_quad:
00425     out << "bitc_quad_t";
00426     break;
00427 
00428 #ifdef KEEP_BF
00429   case ty_bitfield:
00430     if (IDname.size() && (flags & CTYP_EMIT_BF))
00431       out << toCtype(t->CompType(0), IDname, flags, arrsz)
00432           << " " << IDname
00433           << ":" << t->Isize;
00434     else
00435       out << toCtype(t->CompType(0), IDname, flags, arrsz);
00436 #endif
00437 
00438     break;
00439 
00440   case ty_method:
00441     {
00442       // This case cannot happen for static dispatch since it will be
00443       // re-written to a normal function call. In the case of dynamic
00444       // dispatch, we will have to handle this case, probably by
00445       // falling through to the function case (handled similarly)
00446       assert(false);
00447       break;
00448     }
00449 
00450   case ty_fn:
00451     {
00452       out << CMangle(t->mangledString(true));
00453       break;
00454     }
00455 
00456   case ty_fnarg:
00457     {
00458       for (size_t i=0; i<t->components.size(); i++) {
00459         if (i > 0)
00460           out << ", ";
00461         out << toCtype(t->CompType(i), IDname, flags, arrsz);
00462       }
00463       break;
00464     }
00465 
00466   case ty_structv:
00467   case ty_unionv:
00468     {
00469       out << TY_PFX << CMangle(t->defAst);
00470       break;
00471     }
00472 
00473   case ty_structr:
00474   case ty_unionr:
00475     {
00476       out << TY_PFX << CMangle(t->defAst) << " *";
00477       break;
00478     }
00479 
00480   case ty_uvalv:
00481   case ty_uconv:
00482     {
00483       out << TY_PFX <<CMangle(t->myContainer);
00484       break;
00485     }
00486 
00487   case ty_uvalr:
00488   case ty_uconr:
00489     {
00490       out << TY_PFX << CMangle(t->myContainer) << " *";
00491       break;
00492     }
00493 
00494   case ty_array:
00495   case ty_array_ref:
00496     {
00497       out << CMangle(t->mangledString(true));
00498       break;
00499     }
00500 
00501   case ty_vector:
00502     {
00503       out << CMangle(t->mangledString(true)) << " *";
00504       break;
00505     }
00506 
00507   case ty_byref:
00508   case ty_ref:
00509     {
00510       out << toCtype(t->Base(), IDname, flags, arrsz)
00511           << " *";
00512       break;
00513     }
00514 
00515   case ty_exn:
00516     {
00517       if (t->defAst)
00518         out << TY_PFX << CMangle(t->defAst) << " *";
00519       else
00520         out << "bitc_exception_t *";
00521       break;
00522     }
00523 
00524   case ty_tyfn:
00525   case ty_typeclass:
00526   case ty_pcst:
00527   case ty_kvar:
00528   case ty_kfix:
00529   case ty_letGather:
00530   case ty_field:
00531     assert(false);
00532     break;
00533   }
00534   return out.str();
00535 }
00536 
00537 static inline bool
00538 isUnitType(shared_ptr<Type> ty)
00539 {
00540   return (ty->getBareType()->typeTag == ty_unit);
00541 }
00542 
00543 static inline bool
00544 isUnitType(shared_ptr<AST> ast)
00545 {
00546   return isUnitType(ast->symType);
00547 }
00548 
00549 static inline std::string
00550 decl(shared_ptr<Type> typ, string idName, unsigned flags=0,
00551      size_t field_bits=0)
00552 {
00553   stringstream ss;
00554   ss << toCtype(typ) << " ";
00555 
00556   if (flags & CTYP_BYREF)
00557     ss << "*";
00558 
00559   ss << idName;
00560 
00561   if ((flags & CTYP_EMIT_BF) && field_bits)
00562     ss << ":" << field_bits;
00563 
00564   return ss.str();
00565 }
00566 
00567 static inline std::string
00568 decl(shared_ptr<AST> id, string idPrefix="", unsigned flags=0,
00569      unsigned long cmFlags=0)
00570 {
00571   assert(id->astType == at_ident);
00572   stringstream ss;
00573 
00574   ss << toCtype(id->symType) << " ";
00575 
00576   if (flags & CTYP_BYREF)
00577     ss << "*";
00578 
00579   ss << idPrefix << CMangle(id, cmFlags);
00580 
00581   if ((flags & CTYP_EMIT_BF) && (id->field_bits > 0))
00582     ss << ":" << id->field_bits;
00583 
00584   return ss.str();
00585 }
00586 
00587 static inline void
00588 declare(INOstream &out, shared_ptr<AST> id, string prefix="",
00589         unsigned flags=0)
00590 {
00591   out << decl(id, prefix, flags) << ";" << endl;
00592 }
00593 
00594 
00595 static void
00596 emit_ct_args(INOstream &out, shared_ptr<AST> fields, size_t start=0)
00597 {
00598   out << "(";
00599 
00600   bool emitted1=false;
00601   for (size_t c = start; c < fields->children.size(); c++) {
00602     shared_ptr<AST> field = fields->child(c);
00603 
00604     if (field->astType != at_field ||
00605         (field->flags & FLD_IS_DISCM))
00606       continue;
00607 
00608     if (emitted1)
00609       out << ", ";
00610 
00611     emitted1=true;
00612 
00613     out << decl(field->child(1)->symType,
00614                 "_" + CMangle(field->child(0), CMGL_ID_FLD));
00615   }
00616   out << ")" << endl;
00617 }
00618 
00619 static void
00620 emit_ct_inits(INOstream &out, shared_ptr<AST> fields,
00621               string pre="", size_t start=0)
00622 {
00623   for (size_t i = start; i < fields->children.size(); i++) {
00624     shared_ptr<AST> field = fields->child(i);
00625 
00626     if (field->astType == at_methdecl)
00627       continue;
00628 
00629     if (field->astType == at_fill) {
00630       if(field->children.size() == 2) {
00631         out << pre << "__reserved" << field->ID
00632             << " = "
00633             << field->child(1)->litValue.i;
00634         out << ";" << endl;
00635       }
00636       continue;
00637     }
00638 
00639     string fMang = CMangle(field->child(0), CMGL_ID_FLD);
00640     if (field->flags & FLD_IS_DISCM) {
00641       out << pre << fMang << " = "
00642           << field->unin_discm
00643           << ";" << endl;
00644     }
00645     else {
00646       out << pre << fMang << " = "
00647           << "_" << CMangle(field->child(0), CMGL_ID_FLD)
00648           << ";" << endl;
00649     }
00650   }
00651 }
00652 
00653 static void
00654 emit_fnxn_type(INOstream &out, std::string &id, shared_ptr<Type> fn,
00655                bool makePointer=false)
00656 {
00657   fn = fn->getType();
00658   shared_ptr<Type> ret = fn->Ret()->getType();
00659   shared_ptr<Type> args = fn->Args()->getBareType();
00660 
00661   /* If return type is unit, emit void as a special case. */
00662   if (isUnitType(ret))
00663     out << "void ";
00664   else
00665     out << toCtype(ret) << " ";
00666 
00667 
00668   if (!makePointer)
00669     out << CMangle(id) << " ";
00670   else
00671     out << "(*" << CMangle(id) << ") ";
00672 
00673   out << "(";
00674   size_t argCount = 0;
00675   for (size_t i=0; i < args->components.size(); i++) {
00676     shared_ptr<Type> arg = args->CompType(i);
00677     if (isUnitType(arg))
00678       continue;
00679     if (argCount > 0)
00680       out << ", ";
00681         
00682     out << toCtype(arg) << " ";
00683     if (args->CompFlags(i) & COMP_BYREF)
00684       out << "*";
00685     out << " arg" << argCount;
00686     argCount++;
00687   }
00688   if (argCount == 0)
00689     out << "void";
00690   out << ")";
00691 }
00692 
00693 static void
00694 emit_fnxn_decl(INOstream &out, shared_ptr<AST> ast,
00695                bool oneLine, std::string pfx="",
00696                size_t startParam=0)
00697 {
00698   shared_ptr<AST> id = ast->child(0)->child(0);
00699   shared_ptr<Type> fnType = id->symType->getBareType();
00700   shared_ptr<Type> retType = fnType->Ret()->getType();
00701   shared_ptr<AST> lam = ast->child(1);
00702   shared_ptr<AST> argvec = lam->child(0);
00703   shared_ptr<Type> fnargvec = fnType->Args()->getBareType();
00704   assert(argvec->children.size() == fnargvec->components.size());
00705 
00706   /* If return type is unit, emit void as a special case. */
00707   if (isUnitType(retType))
00708     out << "void";
00709   else
00710     out << toCtype(retType);
00711   if (!oneLine)
00712     out << endl;
00713 
00714   out << pfx << CMangle(id) << " ";
00715   out << "(";
00716   assert(startParam <= argvec->children.size());
00717   int paramCount = 0;
00718   for (size_t i=startParam; i < argvec->children.size(); i++) {
00719     shared_ptr<AST> pat = argvec->child(i);
00720     assert(pat->astType == at_identPattern);
00721     shared_ptr<AST> arg = pat->child(0);
00722     unsigned long flags = ((fnargvec->CompFlags(i) & COMP_BYREF)
00723                            ? CTYP_BYREF : 0);
00724 
00725     /* Do not emit parameters of type unit, since there is no point
00726      * passing them. Even if they are mutable, the
00727      * passed actual parameter is already initialized and therefore
00728      * already holds the unit value. Since it can only be overwritten
00729      * by another copy of the unit value, we simply short-circuit any
00730      * possible assignment.
00731      */
00732     if (isUnitType(arg))
00733       continue;
00734 
00735     if (paramCount)
00736       out << ", ";
00737 
00738     out << decl(arg, "", flags);
00739     paramCount++;
00740   }
00741 
00742   /* If no parameters got emitted, say f(void) explicitly. */
00743   if (paramCount == 0)
00744     out << "void";
00745 
00746   out << ")";
00747 }
00748 
00749 static bool
00750 emit_fnxn_label(std::ostream& errStream,
00751                 shared_ptr<UocInfo> uoc,
00752                 shared_ptr<AST> ast,
00753                 INOstream &out,
00754                 set<string> &decls,
00755                 shared_ptr<AST> parent,
00756                 const size_t chno,
00757                 unsigned long flags)
00758 {
00759   bool errFree = true;
00760   assert(ast->astType == at_define || ast->astType == at_recdef);
00761   shared_ptr<AST> id = ast->child(0)->child(0);
00762   assert(id->isFnxn());
00763   bool isHeader = (flags & TOC_HEADER_MODE);
00764 
00765   emit_fnxn_decl(out, ast, isHeader);
00766                 
00767   if (isHeader) {
00768     out << ";" << endl;
00769     return errFree;
00770   }
00771         
00772   out << endl;        
00773   out << "{"
00774       << endl;        
00775   out.more();
00776 
00777   shared_ptr<AST> lam = ast->child(1);
00778   shared_ptr<AST> body = lam->child(1);
00779   shared_ptr<AST> ret= GC_NULL;
00780 
00781   /* While emitting the function parameters, we omitted any parameters
00782    * of unit type, because there is no point passing those or letting
00783    * them occupy storage. However, code within the procedure may
00784    * refer to those variables, so we need to define them locally.
00785    *
00786    * Note that even if the formal paramter is by-ref, it's value
00787    * cannot change because there is only one legal value and it is
00788    * already initialized. We can simply declare a (possibly mutable)
00789    * local of unit type and initialize it to the unit literal here.
00790    *
00791    * This will often result in parameters of unit type being
00792    * eliminated by the C optimizer on the grounds that they are
00793    * unreachable.
00794    */
00795 
00796   shared_ptr<AST> argvec = lam->child(0);
00797   for (size_t i= 0; i < argvec->children.size(); i++) {
00798     shared_ptr<AST> pat = argvec->child(i);
00799 
00800     assert(pat->astType == at_identPattern);
00801     shared_ptr<AST> arg = pat->child(0);
00802 
00803     if (isUnitType(arg)) {
00804       /* Note that even if the formal paramter is by-ref, we aren't
00805        * going to pass anything back here, so we can simply re-declare a
00806        * (possibly mutable) local of unit type and initialize it to
00807        * the unit literal here. */
00808       out << decl(arg, "", 0) << " = " << "0;" << '\n';
00809     }
00810   }
00811 
00812   assert(body->astType == at_container);
00813   if (body->child(1)->astType == at_letStar) {
00814     CHKERR(errFree, toc(errStream, uoc, body, out, CMangle(id),
00815                         decls, lam, 1, flags));
00816     out << ";" << endl;
00817         
00818     ret = FEXPR(body->child(1));        
00819   }
00820   else {
00821     ret = body->child(1); // trivial return
00822   }
00823   assert(ret);
00824 
00825   /* If function returns unit, we run the body for side effects and
00826      perform a return without any value. */
00827   if (! isUnitType(ret))
00828     out << "return ";
00829   CHKERR(errFree, toc(errStream, uoc, ret, out, CMangle(id),
00830                       decls, lam, 1, flags));        
00831   out << ";" << endl;
00832 
00833   if (isUnitType(ret))
00834     out << "return;" << endl;
00835 
00836   out.less();
00837   out << "}" << endl;
00838 
00839   /* Need to emit a transition function if this is a hoisted
00840      function that is a part of closure conversion operation
00841 
00842      Transition function is a function label that internally calls the
00843      actual closure object with the extra environment argument
00844      (communicated through the global currentClosurePtr.
00845      The code generated for a function f is:
00846 
00847      retType
00848      xfn_f(args)
00849      {
00850        BITC_GET_CLOSURE_ENV(__bitc_closure_env);
00851        return f(__bitc_closure_env, args);
00852      }
00853   */
00854   if (ast->flags & LAM_NEEDS_TRANS) {
00855 
00856     // Top level mutable function pointers are not cl-lambdas
00857     // There are converted into function+init in the fix4C pass.
00858     assert(!id->symType->isMutable());
00859 
00860     out << endl;
00861     out << "/* Transition Function */" << endl;
00862     emit_fnxn_decl(out, ast, false, XFN_PFX, 1);
00863     out << endl;        
00864     out << "{"
00865         << endl;        
00866     out.more();
00867 
00868     out << "BITC_GET_CLOSURE_ENV(__bitc_closure_env);" << endl;
00869 
00870     shared_ptr<AST> argvec = lam->child(0);
00871     if (! isUnitType(ret))
00872       out << "return ";
00873     out << CMangle(id) << "(__bitc_closure_env";
00874     for (size_t i=1; i < argvec->children.size(); i++) {
00875       shared_ptr<AST> pat = argvec->child(i);
00876       shared_ptr<AST> arg = pat->child(0);
00877       if (!isUnitType(arg))
00878         out << ", " << CMangle(arg);
00879     }
00880     out << ");" << endl;
00881     if (isUnitType(ret))
00882       out << "return;" << endl;
00883     out.less();
00884     out << "}" << endl <<endl;
00885   }
00886 
00887   return errFree;
00888 }
00889 
00890 bool
00891 typeIsUnmangled(shared_ptr<Type> typ)
00892 {
00893   typ = typ->getBareType();
00894   switch(typ->typeTag) {
00895 
00896   case ty_tvar:
00897   case ty_unit:
00898   case ty_dummy:
00899   case ty_bool:
00900   case ty_char:
00901   case ty_string:
00902   case ty_int8:
00903   case ty_int16:
00904   case ty_int32:
00905   case ty_int64:
00906   case ty_uint8:
00907   case ty_uint16:
00908   case ty_uint32:
00909   case ty_uint64:
00910   case ty_word:
00911   case ty_float:
00912   case ty_double:
00913   case ty_quad:
00914   case ty_exn:
00915 #ifdef KEEP_BF
00916   case ty_bitfield:
00917 #endif
00918       return true;
00919 
00920   case ty_ref:
00921     return typeIsUnmangled(typ->Base());
00922 
00923   default:
00924     return false;
00925   }
00926 }
00927 
00928 static bool
00929 needsBackslashEscape(uint32_t c)
00930 {
00931   return (c == '"' || c == '\'' || c == '\\');
00932 }
00933 
00934 static bool
00935 asciiPrintableCharacter(uint32_t c)
00936 {
00937   /* ASCII printable glyphs are in the range [0x20,0x7e], but a few
00938      of these require special escaping. */
00939   return (c >= 0x20 && c < 0x7f);
00940 }
00941 
00942 
00943 //WARNING: **REQUIRES** answer and errorFree.
00944 #define TOC(errStream, uoc, ast, out, IDname,                        \
00945             decla, parent, chno,  flags)                        \
00946   do {                                                                \
00947     answer = toc((errStream), (uoc), (ast), (out), (IDname),         \
00948                  (decla), (parent), (chno), (flags));                \
00949     if (answer == false)                                                \
00950       errorFree = false;                                        \
00951   }while (0)
00952 
00953 bool
00954 toc(std::ostream& errStream,
00955     shared_ptr<UocInfo> uoc,
00956     shared_ptr<AST> ast,
00957     INOstream &out,
00958     const string &IDname,
00959     set<string> &decls,
00960     shared_ptr<AST> parent,
00961     const size_t chno,
00962     unsigned long flags)
00963 {
00964   bool errorFree = true, answer = false;
00965   // shared_ptr<AST> res = NULL;
00966 
00967   //cout << "---- " << ast->astTypeName() << " flags = " << flags << endl;
00968 
00969   switch(ast->astType) {
00970 
00971   case at_Null:
00972   case at_boxedCat:
00973   case at_unboxedCat:
00974   case at_oc_closed:
00975   case at_oc_open:
00976   case at_opaqueCat:
00977   case agt_category:
00978   case at_AnyGroup:
00979   case agt_literal:
00980   case agt_tvar:
00981   case agt_var:
00982   case agt_definition:
00983   case agt_type:
00984   case agt_expr:
00985   case agt_expr_or_define:
00986   case agt_eform:
00987   case agt_type_definition:
00988   case agt_value_definition:
00989   case agt_CompilationUnit:
00990   case agt_tc_definition:
00991   case agt_if_definition:
00992   case agt_openclosed:
00993   case agt_ow:
00994   case agt_qtype:
00995   case agt_fielditem:
00996   case at_localFrame:
00997   case at_frameBindings:
00998   case at_ifident:
00999   case agt_ucon:
01000   case agt_uselhs:
01001 
01002   case at_declares:
01003   case at_declare:
01004 
01005   case at_tcdecls:
01006   case at_tyfn:
01007   case at_tcapp:
01008   case at_method_decls:
01009   case at_method_decl:
01010   case at_usesel:
01011 
01012   case at_boxedType:
01013   case at_byRefType:
01014   case at_arrayRefType:
01015   case at_exceptionType:
01016   case at_dummyType:
01017   case at_unboxedType:
01018   case at_fn:
01019   case at_fnargVec:
01020   case at_primaryType:
01021   case at_arrayType:
01022   case at_vectorType:
01023   case at_mutableType:
01024   case at_constType:
01025   case at_typeapp:
01026   case at_bitfieldType:
01027   case at_qualType:
01028   case at_constraints:
01029   case at_fieldType:
01030   case at_methType:
01031     
01032   case at_deftypeclass:
01033   case at_definstance:
01034   case at_tcmethods:
01035   case at_tcmethod_binding:
01036   case at_importAs:
01037   case at_provide:
01038   case at_import:
01039   case at_ifsel:
01040   case at_tvlist:
01041 
01042   case at_lambda:
01043   case at_argVec:
01044   case at_and:
01045   case at_or:
01046   case at_loopbindings:
01047   case at_loopbinding:
01048   case at_looptest:
01049 
01050   case at_docString:
01051 
01052   case at_cond:
01053   case at_cond_legs:
01054   case at_cond_leg:
01055   case at_letGather:
01056     {
01057       errStream << ast->loc << "Internal Compiler Error. "
01058                 << "Function toc, unexpected astType: "
01059                 << ast->tagName()
01060                 << endl;
01061 
01062       errorFree = false;
01063       break;
01064     }
01065 
01066   case at_allocREF:
01067     {
01068       out << "GC_ALLOC_ATOMIC(sizeof("
01069           << toCtype(ast->child(0)->symType)
01070           << "))";
01071       break;
01072     }
01073 
01074   case at_copyREF:
01075     {
01076       out << "*";
01077       TOC(errStream, uoc, ast->child(0), out,
01078           IDname, decls, ast, 0, flags);
01079       out << " = ";
01080       out << "*";
01081       TOC(errStream, uoc, ast->child(1), out,
01082           IDname, decls, ast, 1, flags);
01083       out << ";" << endl;        
01084       break;
01085     }
01086 
01087   case at_mkClosure:
01088     {
01089       shared_ptr<AST> fn = ast->child(1);
01090       shared_ptr<AST> env = ast->child(0);
01091       assert(IDname.size());
01092       assert(fn->astType == at_ident);
01093 
01094       out << IDname << " = "
01095           << "(" << toCtype(ast->symType) << ")"
01096           << "bitc_emit_procedure_object("
01097           << XFN_PFX << CMangle(fn)
01098           << ", ";
01099       TOC(errStream, uoc, env, out, IDname, decls, ast, 0, flags);
01100       out << ");" << endl;
01101       break;
01102     }
01103 
01104   case at_setClosure:
01105     {
01106       /* This has also now become obselete */
01107       assert(false);
01108       break;
01109     }
01110 
01111   case at_ident:
01112     {
01113       shared_ptr<AST> id;
01114       if (ast->symbolDef)
01115         id = ast->symbolDef;
01116       else
01117         id = ast;
01118 
01119       if (id->isIdentType(id_ucon0)) {
01120         shared_ptr<Type> t = id->symType->getBareType();
01121         if (t->typeTag == ty_uvalv || t->typeTag == ty_uvalr ||
01122            t->typeTag == ty_exn) {
01123           shared_ptr<AST> dummy = AST::make(at_ucon_apply, ast->loc, ast);
01124           dummy->symType = ast->symType;
01125           TOC(errStream, uoc, dummy, out, IDname,
01126               decls, GC_NULL, 0, flags);        
01127         }
01128         break;
01129       }
01130 
01131 
01132       if (id->flags & ARG_BYREF)
01133         out << "(*";
01134 
01135       out << CMangle(ast);
01136 
01137       if (id->flags & ARG_BYREF)
01138         out << ")";
01139 
01140       break;
01141     }
01142 
01143   case at_identPattern:
01144     {
01145       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
01146           ast, 0, flags);
01147       break;
01148     }
01149 
01150     // Should have skipped through these
01151   case at_interface:
01152   case at_module:
01153     {
01154       assert(false);
01155       break;
01156     }
01157 
01158   case at_boolLiteral:
01159     {
01160       if (ast->litValue.b == true)
01161         out << "true";
01162       else
01163         out << "false";
01164       break;
01165     }
01166 
01167   case at_charLiteral:
01168     {
01169       uint32_t c = ast->litValue.c;
01170 
01171       if (asciiPrintableCharacter(c))
01172         out << (needsBackslashEscape(c) ? "'\\" : "'")
01173             << (unsigned char) c << "'";
01174       else
01175         out << (unsigned long)(ast->litValue.c);
01176       break;
01177     }
01178 
01179   case at_intLiteral:
01180     {
01181       out << ast->litValue.i;
01182       break;
01183     }
01184 
01185   case at_floatLiteral:
01186     {
01187       //       mp_exp_t expptr;
01188       //       std::string s = mpf_get_str(NULL, &expptr, 10, 0,
01189       //                                   ast->litValue.d);
01190 
01191       //       if (s.size())
01192       //         for (size_t i=0; i < s.size(); i++) {
01193       //           if (i == (size_t)(expptr-1))
01194       //             out << ".";
01195       //           out << s[i];
01196       //         }
01197       //       else
01198       //         out << "0.0";
01199 
01200       char buf[256];
01201       snprintf(buf, sizeof(buf), " %f\n", ast->litValue.d);
01202       out << buf;
01203       break;
01204     }
01205 
01206   case at_stringLiteral:
01207     // This one is going to need a helper function in the runtime.
01208     {
01209       // needs to initialize the vector properly...
01210       const char *s = ast->litValue.s.c_str();
01211       const char *send = s + ast->litValue.s.size();
01212 
01213       out << "mkStringLiteral(\"";
01214 
01215       while (s != send) {
01216         const char *snext;
01217         char utf8[7];
01218         uint32_t codePoint = LitValue::DecodeStringCharacter(s, &snext);
01219         unsigned len = sherpa::utf8_encode(codePoint, utf8);
01220 
01221         if (asciiPrintableCharacter(codePoint)) {
01222           if (needsBackslashEscape(codePoint)) out << '\\';
01223           out << (unsigned char) codePoint;
01224         }
01225         else {
01226           for (unsigned pos = 0; pos < len; pos++) {
01227             unsigned char c = utf8[pos];
01228             char d2 = '0' + (c >> 6);
01229             char d1 = '0' + ((c >> 3) % 8);
01230             char d0 = '0' + (c % 8);
01231 
01232             out << '\\' << d2 << d1 << d0;
01233           }
01234         }
01235 
01236         s = snext;
01237       }
01238 
01239       out << "\")";
01240 
01241       break;
01242     }
01243 
01244   case at_unit:
01245     {
01246       out << "0";
01247       break;
01248     }
01249 
01250   case at_defstruct:
01251     {
01252       shared_ptr<AST> ident = ast->child(0);
01253       shared_ptr<AST> fields = ast->child(4);
01254       out << "struct " << TY_PFX << CMangle(ident) << "{" << endl;
01255       out.more();
01256       TOC(errStream, uoc, fields, out, IDname, decls, ast, 4, flags);
01257       out.less();
01258       out << "};" << endl
01259           << endl;
01260 
01261       //emit the constructor
01262       out << "/* Constructor */" << endl;
01263       out << "INLINE " << toCtype(ident->symType) << endl
01264           << CTOR_PFX << CMangle(ident) << " ";
01265 
01266       emit_ct_args(out, fields);
01267       out << "{" << endl;
01268 
01269       out.more();
01270       std::string pre;
01271       if (ident->symType->getBareType()->typeTag == ty_structv) {
01272         out << toCtype(ident->symType)
01273             << " val;";
01274         pre = "val.";
01275       }
01276       else {
01277         out << toCtype(ident->symType)
01278             << " val = "
01279             << "(" << toCtype(ident->symType) << ") "
01280             << "GC_ALLOC(sizeof(" << TY_PFX << CMangle(ident) << "));" << endl;
01281         pre = "val->";
01282       }
01283 
01284       emit_ct_inits(out, fields, pre);
01285       out << "return val;" << endl;
01286       out.less();
01287       out << "}" << endl;
01288       break;
01289     }
01290 
01291   case at_fields:
01292     {
01293       for (size_t c=0; c < ast->children.size(); c++) {
01294         TOC(errStream, uoc, ast->child(c), out, IDname, decls,
01295             ast, c, flags);        
01296       }
01297       break;
01298     }
01299 
01300   case at_methdecl:
01301     break;
01302 
01303   case at_field:
01304     {
01305       out << decl(ast->child(1)->symType,
01306                   CMangle(ast->child(0), CMGL_ID_FLD),
01307                   CTYP_EMIT_BF, ast->field_bits)
01308           << ";" << endl;
01309       break;
01310     }
01311 
01312   case at_fill:
01313     {
01314       string s = "/* fill */";
01315       if(ast->children.size() == 2) {
01316         stringstream ss;
01317         ss << "__reserved" << ast->ID;
01318         s = CMangle(ss.str());
01319       }
01320 
01321       out << decl(ast->child(0)->symType, s,
01322                   CTYP_EMIT_BF, ast->field_bits)
01323           << ";" << endl;
01324 
01325       break;
01326     }
01327 
01328   case at_object_apply:
01329     {
01330       // FIX: This needs to be handled differently.
01331       errStream << "Object apply not yet implemented in code generator" << endl;
01332       break;
01333     }
01334   case at_ucon_apply:
01335   case at_struct_apply:
01336     {
01337       shared_ptr<AST> ctr = ast->child(0)->getCtr();
01338 
01339       if (ctr->symType->isException() &&
01340          (ast->children.size() == 1)) {
01341               out << "&" << CVAL_PFX << CMangle(ast->child(0));
01342               break;
01343       }
01344 
01345       out << CTOR_PFX << CMangle(ctr)
01346           << "(";
01347       for (size_t c=1; c < ast->children.size(); c++) {
01348         if (c > 1)
01349           out << ", ";
01350         
01351         TOC(errStream, uoc, ast->child(c), out, IDname, decls,
01352             ast, c, flags);
01353       }
01354       out << ")";
01355 
01356       break;
01357     }
01358 
01359   case at_fqCtr:
01360     {
01361       TOC(errStream, uoc, ast->child(1), out, IDname, decls,
01362           ast, 1, flags);
01363       break;
01364     }
01365 
01366   case at_sel_ctr:
01367     {
01368       shared_ptr<Type> t = ast->child(0)->symType->getBareType();
01369       out << "(" <<  "TAG_" << CMangle(t->myContainer) << "(";        
01370 
01371       if (!ast->child(0)->symType->isRefType())
01372         out << "&";
01373 
01374       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
01375           ast, 0, flags);
01376         
01377       out << ") == ";        
01378       out << ENUM_PFX << CMangle(ast->child(1), CMGL_ID_FLD)
01379           << ")";
01380       break;
01381     }
01382 
01383   case at_select:
01384     {
01385       shared_ptr<Type> t = ast->child(0)->symType->getBareType();
01386 
01387       // Array, array-ref, and vector have "length" as a special-case
01388       // field. If we see an at_select whose LHS has one of these
01389       // types, it can *only* be a length access, so we handle these
01390       // as special cases.
01391 
01392       // For arrays, the result is an integer literal length, not an
01393       // actual field selection:
01394 
01395       if (t->typeTag == ty_array) {
01396         out << t->arrLen->len;
01397         break;
01398       }
01399 
01400       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
01401           ast, 0, flags);
01402 
01403       // We have already handled array. Handle special cases for
01404       // array-ref and vector here:
01405       if (t->typeTag == ty_vector) {
01406         out << "->length";
01407       }
01408       else if (t->typeTag == ty_array_ref) {
01409         out << ".length";
01410       }
01411       else {
01412         out << ((ast->child(0)->symType->isRefType()) ? "->" : "." );
01413         out << CMangle(ast->child(1), CMGL_ID_FLD);
01414       }
01415       break;
01416     }
01417 
01418   case at_defunion:
01419     {
01420       shared_ptr<AST> ident = ast->child(0);
01421       shared_ptr<AST> ctrs = ast->child(4);
01422 
01423       bool repr = ast->flags & UNION_IS_REPR;
01424       out << "/*** Tag Enumerations ***/" << endl;
01425       out << "typedef enum {" << endl;
01426       out.more();
01427         
01428       if (ident->flags & NULLABLE_UN) {
01429         assert(!repr);
01430 
01431         // Nullable is a special case, and we fake the
01432         // tag values.
01433         for (size_t c=0; c < ctrs->children.size(); c++) {
01434           shared_ptr<AST> ctr = ctrs->child(c);
01435           if (ctr->children.size() > 1) {
01436             out << ENUM_PFX << CMangle(ctr->child(0))
01437                 << " = 1," << endl;        
01438           }
01439           else {
01440             out << ENUM_PFX << CMangle(ctr->child(0));
01441             out << " = 0," << endl;
01442           }
01443         }
01444       }
01445       else if (ident->flags & CARDELLI_UN) {
01446         assert(!repr);
01447         // Nullable is handled as special case.
01448         for (size_t c=0; c < ctrs->children.size(); c++) {
01449           shared_ptr<AST> ctr = ctrs->child(c);
01450           if (ctr->children.size() > 1) {
01451             out << ENUM_PFX << CMangle(ctr->child(0))
01452                 << " = 0," << endl;        
01453           }
01454           else {
01455             out << ENUM_PFX << CMangle(ctr->child(0));
01456             out << " = ";
01457             out << ((2*c)+1);
01458             out << "," << endl;        
01459           }
01460         }
01461       }
01462       else {
01463         for (size_t c=0; c < ctrs->children.size(); c++) {
01464           shared_ptr<AST> ctr = ctrs->child(c);
01465           out << ENUM_PFX << CMangle(ctr->child(0))
01466               << " = " << c
01467               << "," << endl;
01468         }
01469       }
01470 
01471       out.less();
01472       out << "} " << TAG_PFX << CMangle(ident) << ";"
01473           << endl << endl;
01474 
01475 
01476       out << "/*** Structures for constructor legs ***/" << endl;
01477       for (size_t c = 0; c < ctrs->children.size(); c++) {
01478         shared_ptr<AST> ctr = ctrs->child(c);
01479         shared_ptr<AST> ctrID = ctr->child(0);
01480         
01481         if (ctrID->stCtr == ctrID) {        
01482           out << "typedef struct {" << endl;
01483           out.more();
01484         
01485           if (!repr)
01486             if ((ident->flags & SINGLE_LEG_UN) == 0)
01487               if ((((ident->flags & CARDELLI_UN) == 0) &&
01488                   ((ident->flags & NULLABLE_UN) == 0)) ||
01489                  (ctr->children.size() == 1)) {
01490                 out << decl(ident->tagType, "tag", CTYP_EMIT_BF,
01491                             ident->field_bits)<< ";" << endl;
01492               }
01493         
01494           for (size_t i = 1; i < ctr->children.size(); i++) {
01495             shared_ptr<AST> field = ctr->child(i);
01496             TOC(errStream, uoc, field, out, IDname, decls, ctr, i, flags);
01497           }
01498         
01499           out.less();
01500           out << "} " << TY_PFX << CMangle(ctrID)
01501               << ";" << endl << endl;
01502         }
01503         else {
01504           out << "typedef "
01505               << TY_PFX << CMangle(ctrID->stCtr) << " "
01506               << TY_PFX << CMangle(ctrID)
01507               << ";" << endl << endl;
01508         }
01509       }
01510 
01511       out << "/*** Main union ***/"  << endl;
01512       out << "union " << TY_PFX << CMangle(ident) << "{" << endl;
01513       out.more();
01514 
01515       if (!repr)
01516         out << TAG_PFX << CMangle(ident) << " tag;" << endl;
01517 
01518       for (size_t c = 0; c < ctrs->children.size(); c++) {
01519         shared_ptr<AST> ctr = ctrs->child(c);
01520         out << TY_PFX << CMangle(ctr->child(0)) << " "
01521             << "leg_" << CMangle(ctr->child(0)) << ";" << endl;        
01522       }
01523       out.less();
01524       out << "};" << endl << endl;
01525 
01526 
01527       out << "/*** Tag Accessor ***/" << endl;
01528       if (!repr)
01529         out << "INLINE ";
01530       out << TAG_PFX << CMangle(ident) << endl
01531           << "TAG_" << CMangle(ident) << "("
01532           << toCtype(ident->symType);
01533       if (!ident->symType->isRefType())
01534         out << "*";
01535       out << " arg)"
01536           << endl
01537           << "{"
01538           << endl;
01539       out.more();
01540 
01541       string accessor = "arg->tag";
01542 
01543       if (repr) {
01544         for (size_t c = 0; c < ctrs->children.size(); c++) {
01545           shared_ptr<AST> ctr = ctrs->child(c);
01546           out << "if (";
01547           bool emitted1=false;
01548           for (size_t i = 1; i < ctr->children.size(); i++) {
01549             shared_ptr<AST> field = ctr->child(i);
01550             if (field->flags & FLD_IS_DISCM) {
01551               if (emitted1)
01552                 out << " && ";
01553               out << "("
01554                   << "((" << TY_PFX << CMangle(ctr->child(0)) << " *)"
01555                   << "arg)->"
01556                   << CMangle(field->child(0), CMGL_ID_FLD)
01557                   << " == "
01558                   << field->unin_discm
01559                   << ")";
01560               emitted1=true;
01561             }
01562           }
01563           assert(emitted1);
01564           out << ")" << endl;
01565           out.more();
01566           out << "return " << ENUM_PFX << CMangle(ctr->child(0)) << ";" << endl;
01567           out.less();
01568         }
01569         
01570         out << " /* Keep the Compiler happy */ " << endl;
01571         out << " assert(false);" << endl;
01572         out << " return 0;" << endl;        
01573       }
01574       else if (ident->flags & SINGLE_LEG_UN) {
01575         out << "return 0;" << endl;
01576       }
01577       else if (ident->flags & NULLABLE_UN) {
01578         out << "if (" << accessor << ")" << endl;
01579         out.more();
01580         out << "return 1;" << endl;
01581         out.less();
01582         out << "else" << endl;
01583         out.more();
01584         out << "return 0;" << endl;
01585         out.less();
01586       }
01587       else if (ident->flags & CARDELLI_UN) {
01588         out << "if (" << accessor << " & 0x1u)" << endl;
01589         out.more();
01590         out << "return " << accessor << ";" << endl;
01591         out.less();
01592         out << "else" << endl;
01593         out.more();
01594         out << "return 0;" << endl;
01595         out.less();
01596       }
01597       else {
01598         out << "return " << accessor << ";" << endl;
01599       }
01600       out.less();
01601       out << "}"
01602           << endl;
01603 
01604       out << "/*** Constructors: ***/" << endl;
01605       std::string pre;
01606       stringstream udecl;
01607       if (ident->symType->getBareType()->typeTag == ty_unionv) {
01608         udecl << toCtype(ident->symType) << " val;" << endl;
01609         pre = "val.";
01610       }
01611       else {
01612         udecl << toCtype(ident->symType)
01613               << " val = "
01614               << "(" << toCtype(ident->symType) << ") "
01615               << "GC_ALLOC(sizeof(" << TY_PFX << CMangle(ident) << "));"
01616               << endl;
01617         pre = "val->";
01618       }
01619 
01620       for (size_t c = 0; c < ctrs->children.size(); c++) {
01621         shared_ptr<AST> ctr = ctrs->child(c);        
01622         shared_ptr<AST> ctrID = ctr->child(0);
01623         out << "INLINE " << toCtype(ident->symType) << endl
01624             << CTOR_PFX << CMangle(ctrID) << " ";
01625 
01626         emit_ct_args(out, ctr, 1);
01627 
01628         out << "{" << endl;
01629         out.more();
01630         out << udecl.str();
01631         out << TY_PFX << CMangle(ctrID) << " leg;" << endl;
01632         
01633         if (!repr)
01634           if ((ident->flags & SINGLE_LEG_UN) == 0)
01635             if (((ident->flags & CARDELLI_UN) == 0) ||
01636                (ctr->children.size() == 1)) {
01637               out << "leg.tag = " << ENUM_PFX << CMangle(ctrID)
01638                   << ";" << endl;
01639             }
01640 
01641         emit_ct_inits(out, ctr, "leg.", 1);
01642 
01643         out << pre << "leg_" << CMangle(ctrID) << " = leg;" << endl;
01644         out << "return val;" << endl;
01645         out.less();
01646         out << "}" << endl;
01647         out << endl;
01648       }
01649 
01650       break;
01651     }
01652 
01653   case at_constructors:
01654   case at_constructor:
01655     {
01656       assert(false);
01657       break;
01658     }
01659 
01660   case at_defrepr:
01661     //case at_reprbody:
01662     //case at_reprcase:
01663     //case at_reprcaselegR:
01664     //case at_reprtag:
01665     //case agt_reprbodyitem:
01666   case at_reprctrs:
01667   case at_reprctr:
01668   case at_reprrepr:
01669     {
01670       assert(false);
01671       break;
01672     }
01673 
01674   case at_defexception:
01675     {
01676       shared_ptr<AST> ident = ast->child(0);
01677 
01678       if (flags & TOC_HEADER_MODE) {
01679         out << "extern const char " << TAG_PFX << CMangle(ident) << "[]; "
01680             << endl;
01681       }
01682       else {
01683         out << "const char " << TAG_PFX << CMangle(ident) << "[] = "
01684             << "\"" << ident->fqn.ident << "\"" << ";" << endl;
01685       }
01686 
01687       shared_ptr<AST> fields = ast->child(4);
01688 
01689       if (fields->children.size() > 1) {
01690         out << "typedef struct {" << endl;
01691         out.more();
01692         out << "const char *__fileName;" << endl;
01693         out << "int __line;" << endl;
01694 
01695         out << "const char* __name;" << endl;
01696 
01697         TOC(errStream, uoc, fields, out, IDname, decls, ast, 4, flags);
01698 
01699 #if 0
01700         for (size_t c = 0; c < ast->children.size(); c++) {
01701           shared_ptr<AST> field = ast->child(c);
01702           if (field->astType == at_fill)
01703             continue;
01704 
01705           out << decl(field->child(1)->symType,
01706                       field->child(0)->s, true)
01707               << ";" << endl;        
01708         }
01709 #endif
01710 
01711         out.less();
01712         out << "} " << TY_PFX << CMangle(ident) << ";" << endl << endl;
01713 
01714         out << "/* Exception Constructor */" << endl;
01715         out << "INLINE " << TY_PFX << CMangle(ident) << "*" << endl
01716             << CTOR_PFX << CMangle(ident) << " ";
01717 
01718         emit_ct_args(out, fields);
01719         out << "{" << endl;
01720         out.more();
01721         out << TY_PFX << CMangle(ident) << "* val = (" << TY_PFX << CMangle(ident) << "*)"
01722             << "GC_ALLOC(sizeof(" << TY_PFX << CMangle(ident) << "));" << endl;
01723         out << "val->__name = " << TAG_PFX << CMangle(ident) << ";" << endl;
01724         
01725         emit_ct_inits(out, fields, "val->", 1);
01726 
01727         out << "return val;" << endl;
01728         out.less();
01729         out << "}" << endl << endl;
01730       }
01731       else {
01732         // Static allocation for singled valued exceptions.
01733         out << "typedef bitc_exception_t " << TY_PFX << CMangle(ident)
01734             << ";" << endl;
01735 
01736         if (flags & TOC_HEADER_MODE) {
01737           out << "extern bitc_exception_t " << CVAL_PFX << CMangle(ident)
01738               << ";" << endl;
01739         }
01740          else {
01741           out << "bitc_exception_t " << CVAL_PFX << CMangle(ident)
01742               << " = { " << endl;
01743           out.more();
01744           out << ".__name = " << TAG_PFX << CMangle(ident) << endl;
01745           out.less();
01746           out << "};" << endl << endl;
01747         }
01748       }
01749       break;
01750     }
01751 
01752   case at_declunion:
01753   case at_declstruct:
01754   case at_declrepr:
01755     {
01756       shared_ptr<AST> ident = ast->child(0);
01757       if (ident->defn)
01758         ident = ident->defn;
01759 
01760       string nm = TY_PFX + CMangle(ident);
01761       if (decls.find(nm) != decls.end())
01762         break;
01763 
01764       decls.insert(nm);
01765 
01766       out << "typedef ";
01767       if (ast->astType == at_declunion || ast->astType == at_declrepr)
01768         out << "union ";
01769       else
01770         out << "struct ";
01771       out << nm << " " << nm << ";" << endl;
01772       break;
01773     }
01774 
01775   case at_proclaim:
01776     {
01777       shared_ptr<AST> id = ast->getID();
01778       bool hasDefn = false;
01779 
01780       if (id->defn) {
01781         id = id->defn;
01782         hasDefn = true;
01783       }
01784 
01785       out << "extern ";
01786 
01787       decls.insert(CMangle(id));
01788 
01789       //shared_ptr<Type> t = id->symType->getType();
01790       //if (hasDefn && t->isSimpleTypeForC() && (t->typeTag != ty_mutable))
01791       // out << "const ";
01792 
01793       if (id->symType->isFnxn() && !id->symType->isMutable()) {
01794         std::string name = (id->externalName.size())?id->externalName:id->s;
01795         emit_fnxn_type(out, name, id->symType);
01796         out << ";" << endl;
01797       }
01798       else {
01799         declare(out, id, "");
01800       }
01801 
01802       /* If this declaration has an external name, and is a function,
01803          emit typedefs of names relative to the external name so that
01804          they can easily be accessed */
01805       if (id->symType->isFnxn() && id->externalName.size()) {
01806         shared_ptr<Type> fnType = id->symType->getBareType();
01807         shared_ptr<Type> ret = fnType->Ret();
01808         shared_ptr<Type> args = fnType->Args();
01809         
01810         if (!typeIsUnmangled(ret)) {
01811           out << "typedef "
01812               << decl(ret, RET_PFX + id->externalName)
01813               << ";" << endl;
01814         }
01815         
01816         for (size_t i=0; i < args->components.size(); i++) {
01817           shared_ptr<Type> arg = args->CompType(i);
01818         
01819           if (!typeIsUnmangled(arg)) {
01820             stringstream as;
01821             as << ARG_PFX << i << "_"  << id->externalName;
01822         
01823             out << "typedef "
01824                 << decl(arg, as.str())
01825                 << ";" << endl;
01826           }
01827         }
01828       }
01829 
01830       break;
01831     }
01832 
01833   case at_recdef:
01834   case at_define:
01835     {
01836       shared_ptr<AST> id = ast->child(0)->child(0);
01837 
01838       // If this name is file-local, emit it as a static.
01839       // However, if there was a previous declaration,
01840       // that would have been declared as extern, don't emit
01841       // it as static, unless it is a function
01842 
01843       if (decls.find(CMangle(id)) == decls.end())
01844         if (id->flags & ID_IS_PRIVATE)        
01845           out << "static ";
01846 
01847       if (ast->child(1)->astType == at_lambda) {
01848         // Function Label case
01849         // Mutable or immutable, we do the same thing. The mutable
01850         // case and name adjustment is taken care of by
01851         // emitGlobalInitializers() function.
01852         CHKERR(errorFree, emit_fnxn_label(errStream, uoc, ast, out,
01853                                           decls, parent, chno, flags));
01854       }
01855       else if (flags & TOC_HEADER_MODE) {
01856         // Header Mode
01857         // Header mode for function labels taken care of
01858         // within the helper function.
01859         // Note: Don't worry about function pointers,
01860         //       they are emitted as typedefs
01861         out << "extern ";
01862         out << decl(id) << ";"
01863             << endl;        
01864       }
01865       else {
01866         // Non-function
01867         shared_ptr<AST> e = ast->child(1);
01868         shared_ptr<AST> p = ast;
01869         size_t c = 1;
01870         
01871         while (e->astType == at_typeAnnotation) {
01872           p = e;
01873           c = 0;
01874           e = e->child(0);
01875         }
01876         
01877         //if (t->isSimpleTypeForC() && t->typeTag != ty_mutable)
01878         // out << "const ";
01879         
01880         out << decl(id) << " = ";
01881         TOC(errStream, uoc, e, out, IDname, decls, p, c, flags);        
01882         out << ";" << endl;        
01883       }
01884       break;
01885     }
01886 
01887   case at_container:
01888     {
01889       if (ast->child(0)->children.size() != 0) {
01890         //out++;
01891         TOC(errStream, uoc, ast->child(0), out, IDname, decls,
01892             ast, 0, flags);
01893         out << "_" << IDname << ":" << endl;
01894         TOC(errStream, uoc, ast->child(1), out, IDname, decls,
01895             ast, 1, flags);
01896         //out--;
01897       }
01898       else {
01899         TOC(errStream, uoc, ast->child(1), out, IDname, decls,
01900             ast, 1, flags);
01901       }
01902       break;
01903     }
01904 
01905   case at_identList:
01906     {
01907       for (size_t c=0; c < ast->children.size(); c++)
01908         declare(out, ast->child(c));        
01909       break;
01910     }
01911 
01912   case at_suspend:
01913     {
01914       TOC(errStream, uoc, ast->child(1), out, IDname, decls,
01915           ast, 1, flags);
01916 
01917       break;
01918     }
01919 
01920   case at_typeAnnotation:
01921     {
01922       // match agt_eform
01923       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
01924           ast, 0, flags);
01925 
01926       break;
01927     }
01928 
01929   case at_loop:
01930     {
01931       shared_ptr<AST> lbs = ast->child(0);
01932 
01933       for (size_t c = 0; c < lbs->children.size(); c++) {
01934         shared_ptr<AST> lb = lbs->child(c);
01935         shared_ptr<AST> init = lb->child(1);
01936         TOC(errStream, uoc, init, out, IDname, decls, lb, 1, flags);
01937       }
01938 
01939       out << "loop_" << ast->ID << ":" << endl;
01940       out.indent(2);
01941 
01942       shared_ptr<AST> dotest = ast->child(1);
01943       shared_ptr<AST> cond = dotest->child(0);
01944       shared_ptr<AST> res = dotest->child(1);
01945       shared_ptr<AST> body = ast->child(2);
01946       shared_ptr<AST> theCond;
01947 
01948       if (cond->astType == at_letStar) {
01949         TOC(errStream, uoc, cond, out, IDname, decls,
01950             dotest, 0, flags);
01951         theCond = FEXPR(cond);
01952       }
01953       else {
01954         theCond = cond;
01955       }
01956         
01957       out << "if (";
01958       TOC(errStream, uoc, theCond, out, IDname, decls,
01959           GC_NULL, 0, flags);
01960       out << ") {" << endl;
01961       out.more();
01962       TOC(errStream, uoc, res, out, IDname, decls,
01963           dotest, 1, flags);
01964       out << endl;
01965       out.less();
01966       out << "}" << endl;
01967 
01968       out << "else {" << endl;
01969       out.more();
01970       TOC(errStream, uoc, body, out, IDname, decls,
01971           ast, 1, flags);
01972 
01973       if (body->astType != at_letStar)
01974         out << ";" << endl;
01975 
01976       for (size_t c = 0; c < lbs->children.size(); c++) {
01977         shared_ptr<AST> lb = lbs->child(c);
01978         shared_ptr<AST> step = lb->child(2);
01979         TOC(errStream, uoc, step, out, IDname, decls, lb, 2, flags);
01980       }
01981 
01982       out << "goto " << "loop_" << ast->ID << ";" << endl;
01983       out << endl;
01984       out.less();
01985       out << "}" << endl;
01986       out.indent(-2);
01987       break;
01988     }
01989 
01990   case at_labeledBlock:
01991     {
01992       // Emit the expression to be evaluated followed by the escape label:
01993       TOC(errStream, uoc, ast->child(1), out, IDname, decls,
01994           ast, 1, flags);
01995       out << ";" << endl;
01996 
01997       shared_ptr<AST> labelDef = ast->child(0);
01998       std::stringstream ss;
01999       ss << LBL_PFX << CMangle(labelDef->s) << labelDef->ID;
02000 
02001       out.indent(-1);
02002       out << ss.str() << ":" << endl;
02003       out.indent(1);
02004 
02005       break;
02006     }
02007 
02008   case at_return_from:
02009     {
02010       // Emit the expression to be returned followed by a goto to the
02011       // escape label:
02012       TOC(errStream, uoc, ast->child(1), out, IDname, decls,
02013           ast, 1, flags);
02014       out << ";" << endl;
02015 
02016       shared_ptr<AST> labelDef = ast->child(0)->symbolDef;
02017       std::stringstream ss;
02018       ss << LBL_PFX << CMangle(labelDef->s) << labelDef->ID;
02019 
02020       out << "goto " << ss.str() << ";" << endl;
02021 
02022       break;
02023     }
02024 
02025   case at_begin:
02026     {
02027       if (ast->children.size()) {
02028         // out++;
02029         for (size_t c = 0; c < ast->children.size(); c++) {
02030           TOC(errStream, uoc, ast->child(c), out, IDname, decls,
02031               ast, c, flags);
02032         
02033           out << ";" << endl;
02034         }
02035       }
02036       else {
02037         // Empty block emits unit:
02038         out << 0;
02039       }
02040       // out--;
02041 
02042       break;
02043     }
02044 
02045   case at_apply:
02046     {
02047       // FIX: Shap has a test case that shows that the thing in apply
02048       // position can be an arbitrary location expression, so this
02049       // assert is wrong.
02050       // assert(ast->child(0)->astType == at_ident);
02051 
02052       // There is some additional work needed here to deal with
02053       // self-recursion within LETREC bodies...
02054 
02055       if (ast->child(0)->astType == at_ident) {
02056         shared_ptr<AST> id = ast->child(0);
02057         assert(id->symbolDef);
02058 
02059         if (id->flags & SELF_TAIL) {
02060           shared_ptr<AST> lbps = id->symbolDef->defbps;
02061           assert(lbps);
02062           assert(ast->children.size() == lbps->children.size() + 1);
02063           out << "/* Tail recursive application: */ " << endl;
02064           for (size_t c = 0; c < lbps->children.size(); c++) {
02065             shared_ptr<AST> ident = lbps->child(c)->child(0);
02066             TOC(errStream, uoc, ident, out, IDname, decls,
02067                 lbps->child(c), 0, flags);
02068             out << " = ";
02069             TOC(errStream, uoc, ast->child(c+1), out, IDname, decls,
02070                 ast, c+1, flags);
02071             out << ";" << endl;
02072           }
02073           out << "goto " << "_" << CMangle(id) << ";" << endl;
02074           break;
02075         }
02076       }
02077 
02078       shared_ptr<Type> clType = ast->child(0)->symType->getBareType();
02079       assert(clType->typeTag == ty_fn);
02080       shared_ptr<Type> retType = clType->Ret()->getType();
02081       shared_ptr<Type> argsType = clType->Args()->getType();
02082 
02083       /* If function returns unit type, we emit it to C as returning
02084        * void. This is necessary in order to be able to declare
02085        * external procedures in C. Which is all well and good, except
02086        * that we need to get back the unit instance after the function
02087        * returns. Re-introduce the unit instance here by turning such
02088        * calls into a comma expression of the form
02089        *
02090        *    ( fn(args), 0 )
02091        */
02092       if (isUnitType(retType))
02093         out << "(";
02094 
02095       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02096           ast, 0, flags);
02097 
02098       out << "(";
02099       size_t count = 0;
02100       for (size_t c=1; c < ast->children.size(); c++) {
02101         /* Do not emit anything at an argument position that is of
02102          * unit type. Remember that we have run the SSA pass, so any
02103          * side effects from this computation have already been
02104          * computed. With that handled, it is okay to just not pass
02105          * the parameter here.
02106          */
02107         if (isUnitType(ast->child(c)))
02108           continue;
02109 
02110         if (count > 0)
02111           out << ", ";        
02112         
02113         if (argsType->CompFlags(c-1) & COMP_BYREF)
02114           out << "&";
02115         
02116         TOC(errStream, uoc, ast->child(c), out, IDname, decls,
02117             ast, c, flags);
02118         count++;
02119       }
02120       out << ")";
02121 
02122       if (isUnitType(retType))
02123         out << ",0)";
02124 
02125       break;
02126     }
02127     
02128   case at_mkArrayRef:
02129     {
02130       assert(IDname.size());
02131       shared_ptr<Type> arrType = ast->child(0)->symType->getType();
02132       assert(arrType->arrLen->len != 0);
02133       out << IDname << ".length = " << arrType->arrLen->len << ";" << endl;
02134       out << IDname << ".elem = ";
02135       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02136           ast, 0, flags);
02137       out << ".elem;" << endl;
02138       break;
02139     }
02140 
02141   case at_array:
02142     {
02143       assert(IDname.size());
02144       for (size_t c = 0; c < ast->children.size(); c++) {
02145         out << IDname << ".elem[" << c << "] = ";
02146          TOC(errStream, uoc, ast->child(c), out, IDname, decls,
02147             ast, c, flags);
02148         out << ";" << endl;
02149       }
02150       out << endl;
02151       break;
02152     }
02153 
02154   case at_vector:
02155     {
02156       if (IDname.size() == 0) {
02157         assert(1);
02158       }
02159       assert(IDname.size());
02160       shared_ptr<Type> t = ast->symType->getBareType();
02161       out << IDname << " = (" << toCtype(t) << ") "
02162           << "GC_ALLOC(sizeof("
02163           << CMangle(t->mangledString(true)) << ") + "
02164           << "(" << ast->children.size() << " * sizeof("
02165           << toCtype(t->Base()) << ")));"
02166           << endl;
02167 
02168       out << IDname << "->length = " << ast->children.size()
02169           << ";" << endl;
02170       out << IDname << "->elem = (("
02171           << toCtype(t->Base())
02172           << " *) (((char *) " << IDname << ") + "
02173           << "sizeof(" << CMangle(t->mangledString(true)) << ")));"
02174           << endl;
02175       for (size_t c = 0; c < ast->children.size(); c++) {
02176         out << IDname << "->elem[" << c << "] = ";
02177          TOC(errStream, uoc, ast->child(c), out, IDname, decls,
02178             ast, c, flags);
02179         out << ";" << endl;
02180       }
02181       out << endl;
02182       break;
02183     }
02184 
02185   case at_MakeVector:
02186     {
02187       assert(IDname.size());
02188       shared_ptr<Type> t = ast->symType->getBareType();
02189       out << IDname << " = (" << toCtype(ast->symType) << ") "
02190           << "GC_ALLOC(sizeof("
02191           << CMangle(t->mangledString(true)) << ") + "
02192           << "(";
02193       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02194           ast, 0, flags);
02195       out << " * sizeof("
02196           << toCtype(t->Base()) << ")));"
02197           << endl;
02198 
02199       out << IDname << "->length = ";
02200       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02201           ast, 0, flags);
02202       out << ";" << endl;
02203 
02204       out << IDname << "->elem = (("
02205           << toCtype(t->Base())
02206           << " *) (((char *) " << IDname << ") + "
02207           << "sizeof(" << CMangle(t->mangledString(true)) << ")));"
02208           << endl;
02209 
02210       out << "{" << endl;
02211       out.more();
02212       out << "bitc_word_t __bitc_temp_mvec;" << endl;
02213       out << "for (__bitc_temp_mvec = 0; __bitc_temp_mvec < ";
02214       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02215           ast, 0, flags);
02216       out << "; __bitc_temp_mvec++)" << endl;
02217       out.more();        
02218       out << IDname << "->elem[__bitc_temp_mvec] = ";
02219       /* This is actually an application, get at_apply case to do the
02220          work :) */
02221       shared_ptr<AST> hackIdent = AST::make(at_ident, ast->loc);
02222       hackIdent->s = "__bitc_temp_mvec";
02223       hackIdent->flags |= ID_IS_GENSYM; // don't add extra astID after name
02224       hackIdent->symType = Type::make(ty_word);
02225       shared_ptr<AST> apply = AST::make(at_apply, ast->loc,
02226                            ast->child(1), hackIdent);
02227       TOC(errStream, uoc, apply, out, IDname, decls, ast, 1, flags);
02228       out << ";" << endl;
02229       out.less();
02230       out.less();
02231       out << "}" << endl;
02232       out << endl;
02233       break;
02234     }
02235 
02236 #ifdef HAVE_INDEXABLE_LENGTH_OPS
02237   case at_array_length:
02238     {
02239       shared_ptr<Type> arrType =
02240         ast->child(0)->symType->getBareType();
02241       out << arrType->arrLen->len;
02242       break;
02243     }
02244 
02245   case at_array_ref_length:
02246     {
02247       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02248           ast, 0, flags);
02249       out << ".length";
02250       break;
02251     }
02252 
02253   case at_vector_length:
02254     {
02255       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02256           ast, 0, flags);
02257       out << "->length";
02258       break;
02259     }
02260 #endif
02261 
02262   case at_nth:
02263     // Shouldn't survive to this point.
02264     assert(false);
02265     break;
02266   case at_array_nth:
02267   case at_array_ref_nth:
02268   case at_vector_nth:
02269     {
02270       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02271           ast, 0, flags);
02272 
02273       if (ast->astType == at_vector_nth)
02274         out << "->";
02275       else
02276         out << ".";
02277       
02278       out << "elem[";
02279       TOC(errStream, uoc, ast->child(1), out, IDname, decls,
02280           ast, 1, flags);
02281       out << "]";
02282       break;
02283     }
02284 
02285   case at_uswitch:
02286     {
02287       shared_ptr<AST> topExp = ast->child(1);
02288       shared_ptr<AST> cases = ast->child(2);
02289       shared_ptr<AST> ow = ast->child(3);
02290 
02291       shared_ptr<Type> t = topExp->symType->getBareType();
02292 
02293       out << "switch(";
02294 
02295       assert(t->typeTag == ty_uvalv || t->typeTag == ty_unionv ||
02296              t->typeTag == ty_uvalr || t->typeTag == ty_unionr ||
02297              t->typeTag == ty_uconr || t->typeTag == ty_uconv);
02298 
02299       out << "TAG_" << CMangle(t->myContainer) << "(";
02300       if (!topExp->symType->isRefType())
02301         out << "&";
02302       TOC(errStream, uoc, topExp, out, IDname, decls, ast, 0, flags);
02303       out << ")";        
02304       out << ") {" << endl;;
02305       out.more();
02306 
02307       for (size_t c=0; c < cases->children.size(); c++) {
02308         
02309         shared_ptr<AST> theCase = cases->child(c);
02310         shared_ptr<AST> expr = theCase->child(1);
02311         shared_ptr<AST> legIdent = theCase->child(0);
02312 
02313         for (size_t n=2; n < theCase->children.size(); n++) {
02314           shared_ptr<AST> ctr = theCase->child(n)->getCtr();
02315         
02316           std::string leg = CMangle(ctr);        
02317           out << "case " << ENUM_PFX << leg << " :" << endl;
02318         }
02319 
02320         out.more();
02321         out << "{" << endl;
02322         out.more();
02323 
02324         TOC(errStream, uoc, legIdent, out, IDname, decls, theCase, 0, flags);
02325         out << " = ";
02326 
02327         if (t->isRefType())
02328           out << "&";
02329         TOC(errStream, uoc, topExp, out, IDname, decls, ast, 0, flags);        
02330         if (t->isValType())
02331           out << ".";
02332         else
02333           out << "->";        
02334 
02335         out << "leg_" << CMangle(theCase->child(2)->getCtr());
02336         out << ";" << endl;
02337                 
02338         TOC(errStream, uoc, expr, out, IDname, decls, theCase, 1, flags);
02339         out << "break;";
02340         out << endl;
02341         out.less();
02342         out << "}" << endl;
02343         out.less();
02344         out << endl;
02345       } // for each case
02346 
02347       if (ow->astType != at_Null) {
02348         shared_ptr<AST> legIdent = ow->child(0);
02349 
02350         out << "default:" << endl;
02351         out.more();
02352         out << "{" << endl;
02353         out.more();
02354 
02355         TOC(errStream, uoc, legIdent, out, IDname, decls, ow, 0, flags);
02356         out << " = ";
02357 
02358         TOC(errStream, uoc, topExp, out, IDname, decls, ast, 0, flags);        
02359         out << ";" << endl;
02360                 
02361         TOC(errStream, uoc, ow->child(1), out, IDname, decls, ow, 1, flags);
02362         out << "break;";
02363         out << endl;
02364         out.less();
02365         out << "}" << endl;
02366         out.less();
02367         out << endl;
02368       }
02369       out.less();
02370       out << "}" << endl;
02371 
02372       break;
02373     }
02374 
02375   case at_usw_legs:
02376   case at_usw_leg:
02377   case at_otherwise:
02378   case at_condelse:
02379     {
02380       assert(false);
02381       break;
02382     }
02383 
02384   case at_try:
02385     {
02386       shared_ptr<AST> topExpr = ast->child(0);
02387       shared_ptr<AST> cases = ast->child(2);
02388       shared_ptr<AST> ow = ast->child(3);
02389       out << "{" << endl;
02390       out.more();
02391       out << "jmp_buf jb;" << endl;
02392       out << "jmp_buf *lastJB = curCatchBlock;" << endl;
02393       out << "curCatchBlock = &jb;" << endl;
02394       out << endl;
02395       out << "int result = setjmp(jb);" << endl;
02396       out << "if (!result) {" << endl;
02397       out.more();
02398       TOC(errStream, uoc, topExpr, out, IDname, decls,
02399           ast, 0, flags);
02400       out << "curCatchBlock = lastJB;" << endl;
02401       out.less();
02402       out << "}" << endl;
02403       out << "else {" << endl;
02404       out.more();
02405       out << "curCatchBlock = lastJB;" << endl;
02406 
02407       // Too bad I cannot use a switch ...
02408       for (size_t c = 0; c < cases->children.size(); c++) {
02409         shared_ptr<AST> theCase = cases->child(c);
02410         shared_ptr<AST> expr = theCase->child(1);
02411         shared_ptr<AST> legIdent = theCase->child(0);
02412 
02413         if (c > 0)
02414           out << "else " << endl;
02415         
02416         out << "if (";
02417         for (size_t n=2; n < theCase->children.size(); n++) {
02418           shared_ptr<AST> exn = theCase->child(n);
02419         
02420           if (n > 2)
02421             out << " || ";
02422           out << "(curException->__name == "
02423               << TAG_PFX << CMangle(exn) << ")";
02424         }
02425         out << ") {" << endl;
02426         out.more();
02427         TOC(errStream, uoc, legIdent, out, IDname, decls, ow, 0, flags);
02428         out << " = "
02429             << "((" << toCtype(legIdent->symType, legIdent->s) <<  ") "
02430             << "curException);" << endl;
02431 
02432         TOC(errStream, uoc, expr, out, IDname, decls, theCase, 1, flags);
02433         out.less();
02434         out << "}" << endl;
02435       } /* for each case */
02436 
02437       if (ow->astType != at_Null) {
02438         // Careful! There may not have been any cases.
02439         if (cases->children.size())
02440           out << "else ";
02441 
02442         out << "{" << endl;
02443         out.more();
02444 
02445         shared_ptr<AST> legIdent = ow->child(0);
02446 
02447         // In otherwise leg, id has type exception, so no need for a
02448         // cast here.
02449         TOC(errStream, uoc, legIdent, out, IDname, decls, ow, 0, flags);
02450         out << " = curException;" << endl;
02451 
02452         TOC(errStream, uoc, ow->child(1), out, IDname, decls, ow, 1, flags);
02453         out.less();
02454         out << "}" << endl;
02455         out << endl;
02456       }
02457       else {
02458         out << "else {" << endl;
02459         out.more();
02460         out << "longjmp(*curCatchBlock, 1);" << endl;
02461         out.less();
02462         out << "}" << endl;
02463       }
02464       out.less();
02465       out << "}" << endl; // else case in setjmp () return
02466       out.less();
02467       out << "}" << endl; //Entire try/catch block
02468 
02469       break;
02470     }
02471 
02472   case at_throw:
02473     {
02474       // Value passed may be either an exception or an exception
02475       // instance. Both have the same underlying representation, but
02476       // emit an explicit cast to suppress complaint from the
02477       // high-level macroassembler. Er, um, I mean the C compiler.
02478       out << "bitc_throw(\""
02479           << ast->loc.origin << "\", "
02480           << ast->loc.line << ", "
02481           << "(bitc_exception_t *) ";
02482       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02483           ast, 0, flags);
02484       out <<");" << endl;
02485       break;
02486     }
02487 
02488   case at_setbang:
02489     {
02490       assert(IDname.size());
02491 
02492       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02493           ast, 0, flags);
02494       out << " = ";
02495       TOC(errStream, uoc, ast->child(1), out, IDname, decls,
02496           ast, 1, flags);
02497       out << ";" << endl;
02498 
02499       out << IDname << " = (bitc_unit_t) 0;" << endl;
02500       break;
02501     }
02502 
02503   case at_sizeof:
02504     {
02505       shared_ptr<Type> ty = ast->child(0)->getType();
02506       out << " sizeof(" << toCtype(ty) << ") ";
02507       break;
02508     }
02509 
02510   case at_bitsizeof:
02511     {
02512       shared_ptr<Type> ty = ast->child(0)->getType();
02513       out << " (8*sizeof(" << toCtype(ty) << ")) ";
02514       break;
02515     }
02516 
02517   case at_dup:
02518     {
02519       assert(IDname.size());
02520       shared_ptr<AST> arg = ast->child(0);
02521       out << IDname << " = "
02522           << "(("
02523           << toCtype(ast->symType)
02524           << ") GC_ALLOC(sizeof("
02525           << toCtype(arg->symType)
02526           << ")));" << endl;
02527       out << "*" << IDname << " = ";
02528       TOC(errStream, uoc, arg, out, IDname, decls, ast, 0, flags);
02529       out << ";" << endl;
02530       break;
02531     }
02532 
02533   case at_deref:
02534     {
02535       out << "(* ";
02536       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02537           ast, 0, flags);
02538       out << ")";
02539       break;
02540     }
02541 
02542   case at_inner_ref:
02543     {
02544       out << "&";
02545       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02546           ast, 0, flags);
02547       out << "->";
02548 
02549       if (ast->flags & INNER_REF_NDX) {
02550         out << "elem[";
02551         TOC(errStream, uoc, ast->child(1), out, IDname, decls,
02552             ast, 1, flags);
02553         out << "]";
02554       }
02555       else {
02556         out << CMangle(ast->child(1), CMGL_ID_FLD);
02557       }
02558       break;
02559     }
02560 
02561   case at_if:
02562     {
02563       shared_ptr<AST> testAst = ast->child(0);
02564       shared_ptr<AST> thenAst = ast->child(1);
02565       shared_ptr<AST> elseAst = ast->child(2);
02566       out << "if (";
02567       TOC(errStream, uoc, testAst, out, IDname, decls,
02568           ast, 0, flags);
02569       out << ") {" << endl;
02570       out.more();
02571       TOC(errStream, uoc, thenAst, out, IDname, decls,
02572           ast, 1, flags);
02573       if (thenAst->astType != at_letStar)
02574         out << ";";
02575       out << endl;
02576       out.less();
02577       out << "}" << endl;
02578       out << "else {" << endl;
02579       out.more();
02580       TOC(errStream, uoc, elseAst, out, IDname, decls,
02581           ast, 2, flags);
02582       if (elseAst->astType != at_letStar)
02583         out << ";";
02584       out << endl;
02585       out.less();
02586       out << "}" << endl;
02587       break;
02588     }
02589 
02590   case at_when:
02591   case at_unless:
02592     {
02593       shared_ptr<AST> testAst = ast->child(0);
02594       shared_ptr<AST> thenAst = ast->child(1);
02595 
02596       out << "if (";
02597       if (ast->astType == at_unless) out << "!(";
02598       TOC(errStream, uoc, testAst, out, IDname, decls,
02599           ast, 0, flags);
02600       if (ast->astType == at_unless) out << ")";
02601       out << ") {" << endl;
02602       out.more();
02603       TOC(errStream, uoc, thenAst, out, IDname, decls,
02604           ast, 1, flags);
02605       if (thenAst->astType != at_letStar)
02606         out << ";";
02607       out << endl;
02608       out.less();
02609       out << "}" << endl;
02610       break;
02611     }
02612 
02613   case at_letStar:
02614   case at_letrec:
02615   case at_let:
02616     {
02617       //++out;
02618       TOC(errStream, uoc, ast->child(0), out, IDname, decls,
02619           ast, 0, flags);
02620 
02621       shared_ptr<AST> lExpr = ast->child(1);
02622       if (lExpr->astType == at_typeAnnotation)
02623         lExpr = lExpr->child(0);
02624 
02625       switch(lExpr->astType) {
02626       case at_ident:
02627       case at_boolLiteral:
02628       case at_charLiteral:
02629       case at_intLiteral:
02630       case at_floatLiteral:
02631       case at_stringLiteral:
02632         break;
02633         
02634       default:
02635         // The only thing I expect here is due to a GrandLet        
02636         TOC(errStream, uoc, ast->child(1), out, IDname, decls,
02637             ast, 1, flags);
02638         out << ";" << endl;        
02639         break;
02640       }
02641       //--out;
02642       break;
02643     }
02644 
02645   case at_letbindings:
02646     {
02647       for (size_t i=0; i < ast->children.size(); i++)
02648         TOC(errStream, uoc, ast->child(i), out, IDname, decls,
02649             ast, i, flags);
02650       break;
02651     }
02652 
02653   case at_letbinding:
02654     {
02655       assert(ast->child(0)->astType == at_identPattern);
02656       shared_ptr<AST> ident = ast->child(0)->child(0);
02657       if ((ast->flags & LB_IS_DUMMY) == 0) {        
02658         if ((ast->flags & LB_POSTPONED) == 0)
02659           out << CMangle(ident) << " = ";
02660       }
02661 
02662       TOC(errStream, uoc, ast->child(1), out, CMangle(ident),
02663           decls, ast, 1, flags);
02664       if (((ast->flags & LB_IS_DUMMY) == 0) &&
02665          ((ast->flags & LB_POSTPONED) == 0))
02666         out << ";" << endl;
02667       break;
02668     }
02669   }
02670   return errorFree;
02671 }
02672 
02673 static bool
02674 alreadyEmitted(shared_ptr<Type> t,
02675                const set<string>& theSet)
02676 {
02677   std::string nm = CMangle(t->mangledString(true));
02678   return (theSet.find(nm) != theSet.end());
02679 }
02680 
02681 static void
02682 emit_arr_vec_fn_types(shared_ptr<Type> candidate,
02683                       INOstream &out,
02684                       set<string>& arrSet,
02685                       set<string>& arrByrefSet,
02686                       set<string>& vecSet,
02687                       set<string>& fnSet)
02688 {
02689   shared_ptr<Type> t = candidate->getBareType();
02690   if (t->mark & MARK_EMIT_ARR_VEC_FN_TYPES)
02691     return;
02692 
02693   t->mark |= MARK_EMIT_ARR_VEC_FN_TYPES;
02694 
02695   for (size_t i=0; i<t->typeArgs.size(); i++)
02696     emit_arr_vec_fn_types(t->TypeArg(i), out,
02697                           arrSet, arrByrefSet, vecSet, fnSet);
02698 
02699   for (size_t i=0; i<t->components.size(); i++)
02700     emit_arr_vec_fn_types(t->CompType(i), out,
02701                              arrSet, arrByrefSet, vecSet, fnSet);
02702 
02703   switch(t->typeTag) {
02704   case ty_array:
02705     {
02706       if (alreadyEmitted(t, arrSet))
02707         break;
02708 
02709       assert(t->arrLen->len != 0);
02710 
02711       arrSet.insert(CMangle(t->mangledString(true)));
02712       //emitted = true;
02713       //std::cerr << "Emitted: " << CMangle(t->mangledString(true))
02714       //          << " for " << t->asString()
02715       //           << std::endl;
02716 
02717       shared_ptr<Type> et = t->Base()->getBareType();
02718       out << "/* Typedef in anticipation of the array type:"
02719           << endl
02720           << " * Sexpr: " << t->asSexprString() << endl
02721           << " * Block: " << t->asBlockString() << endl
02722           << " */" << endl;
02723         
02724       out << "typedef struct {" << endl;
02725       out.more();
02726 
02727       out << toCtype(et) << " elem[" << t->arrLen->len << "];" << endl;
02728       out.less();
02729       out << "} " << CMangle(t->mangledString(true))
02730           << ";" << endl << endl;
02731       break;
02732     }
02733 
02734   case ty_array_ref:
02735     {
02736       if (alreadyEmitted(t, arrByrefSet))
02737         break;
02738 
02739       arrByrefSet.insert(CMangle(t->mangledString(true)));
02740       //emitted = true;
02741       //std::cerr << "Emitted: " << CMangle(t->mangledString(true))
02742       //          << " for " << t->asString()
02743       //           << std::endl;
02744 
02745       shared_ptr<Type> et = t->Base()->getBareType();
02746       out << "/* Typedef in anticipation of the arrayByRef type:"
02747           << endl
02748           << " * Sexpr: " << t->asSexprString() << endl
02749           << " * Block: " << t->asBlockString() << endl
02750           << " */" << endl;
02751         
02752       out << "typedef struct {" << endl;
02753       out.more();
02754       
02755       out << "bitc_word_t length;" << endl;
02756       out << toCtype(et) << " *elem;" << endl;
02757       out.less();
02758       out << "} " << CMangle(t->mangledString(true))
02759           << ";" << endl << endl;
02760       break;
02761     }
02762 
02763   case ty_vector:
02764     {
02765       if (alreadyEmitted(t, vecSet))
02766         break;
02767 
02768       vecSet.insert(CMangle(t->mangledString(true)));
02769 
02770       shared_ptr<Type> et = t->Base()->getBareType();
02771       out << "/* Typedef in anticipation of the vector type:"
02772           << endl
02773           << " * Sexpr: " << t->asSexprString() << endl
02774           << " * Block: " << t->asBlockString() << endl
02775           << " */" << endl;
02776 
02777       out << "typedef struct {" << endl;
02778       out.more();
02779 
02780       out << "bitc_word_t length;" << endl;
02781       out << toCtype(et) << " *elem;" << endl;
02782       out.less();
02783       out << "} " << CMangle(t->mangledString(true))
02784           << ";" << endl << endl;
02785       break;
02786     }
02787 
02788   case ty_fn:
02789     {
02790       if (alreadyEmitted(t, fnSet))
02791         break;
02792 
02793       std::string fnName = t->mangledString(true);
02794       fnSet.insert(CMangle(fnName));
02795       out << "/* Typedef in anticipation of the function (pointer) type:"
02796           << endl
02797           << " * Sexpr: " << t->asSexprString() << endl
02798           << " * Block: " << t->asBlockString() << endl
02799           << " */" << endl;
02800       out << "typedef ";
02801       emit_fnxn_type(out, fnName, t, true);
02802       out << ";" << endl << endl;
02803       break;
02804     }
02805 
02806   default:
02807     {
02808       break;
02809     }
02810   }
02811 
02812   t->mark &= ~MARK_EMIT_ARR_VEC_FN_TYPES;
02813 }
02814 
02815 
02816 static void
02817 emit_arr_vec_fn_types(shared_ptr<AST> ast,
02818                       INOstream &out,
02819                       set<string>& arrSet,
02820                       set<string>& arrByrefSet,
02821                       set<string>& vecSet,
02822                       set<string>& fnSet)
02823 {
02824   if (ast->symType)
02825     emit_arr_vec_fn_types(ast->symType, out,
02826                              arrSet, arrByrefSet, vecSet, fnSet);
02827 
02828 
02829   for (size_t c = 0; c < ast->children.size(); c++)
02830     emit_arr_vec_fn_types(ast->child(c), out,
02831                              arrSet, arrByrefSet, vecSet, fnSet);
02832 }
02833 
02834 
02835 static bool
02836 TypesTOC(std::ostream& errStream,
02837          shared_ptr<UocInfo> uoc,
02838          INOstream &out,
02839          set<string> &decls,
02840          unsigned long flags)
02841 {
02842   bool errFree = true;
02843   shared_ptr<AST> mod = uoc->uocAst;
02844   set<string> arrSet;
02845   set<string> arrByrefSet;
02846   set<string> vecSet;
02847   set<string> fnSet;
02848 
02849   for (size_t c=0; (c < mod->children.size()); c++) {
02850     shared_ptr<AST> ast = mod->child(c);
02851 
02852     switch(ast->astType) {
02853     case at_declstruct:
02854     case at_declunion:
02855       {        
02856         
02857         //out << "#line " << ast->loc.line
02858         //    << " \"" << *(ast->loc.path) << "\""
02859         //    << std::endl;
02860 
02861         out << "////////////////////////////////////////" << endl;
02862         out.setPostindent("// ");
02863         out << ast->loc << endl
02864             << ast->asString(pp_Raw) << endl;
02865         out.setPostindent("");
02866         out << "////////////////////////////////////////" << endl;
02867 
02868         CHKERR(errFree, toc(errStream, uoc, ast, out, "", decls,
02869                             mod, c, flags));
02870         out << endl;        
02871         break;
02872       }
02873 
02874     case at_defstruct:
02875     case at_defunion:
02876       {
02877 
02878         //out << "#line " << ast->loc.line
02879         //    << " \"" << *(ast->loc.path) << "\""
02880         //    << std::endl;
02881 
02882         emit_arr_vec_fn_types(ast, out, arrSet, arrByrefSet,  
02883                               vecSet, fnSet);
02884 
02885         out << "////////////////////////////////////////" << endl;
02886         out.setPostindent("// ");
02887         out << ast->loc << endl
02888             << ast->asString(pp_Raw) << endl;
02889         out.setPostindent("");
02890         out << "////////////////////////////////////////" << endl;
02891 
02892         shared_ptr<AST> ident = ast->child(0);
02893         if (decls.find(CMangle(ident)) == decls.end()) {
02894           decls.insert(CMangle(ident));
02895         
02896           out << "/* Forward declaration */" << endl;
02897           out << "typedef ";
02898           out << ((ast->astType == at_defstruct) ? "struct " : "union ");
02899           out << TY_PFX << CMangle(ident) << " "
02900               << TY_PFX << CMangle(ident) << ";" << endl;
02901           out << endl;
02902         }
02903         
02904         CHKERR(errFree, toc(errStream, uoc, ast, out, "", decls,
02905                             mod, c, flags));
02906         out << endl << endl;
02907         break;
02908       }
02909 
02910     case at_defexception:
02911       {
02912 
02913         //out << "#line " << ast->loc.line
02914         //    << " \"" << *(ast->loc.path) << "\""
02915         //    << std::endl;
02916         
02917         emit_arr_vec_fn_types(ast, out, arrSet, arrByrefSet, 
02918                               vecSet, fnSet);
02919 
02920         out << "////////////////////////////////////////" << endl;
02921         out.setPostindent("// ");
02922         out << ast->loc << endl
02923             << ast->asString(pp_Raw) << endl;
02924         out.setPostindent("");
02925         out << "////////////////////////////////////////" << endl;
02926 
02927         CHKERR(errFree, toc(errStream, uoc, ast, out, "", decls,
02928                             mod, c, flags));
02929         out << endl << endl;
02930 
02931         break;
02932       }
02933 
02934     case at_proclaim:
02935     case at_recdef:
02936     case at_define:
02937       {
02938         emit_arr_vec_fn_types(ast, out, arrSet, arrByrefSet, 
02939                               vecSet, fnSet);
02940         break;
02941       }
02942 
02943     default:
02944       {
02945         break;
02946       }
02947     }
02948   }
02949 
02950   return errFree;
02951 }
02952 
02953 static bool
02954 emitInitProc(std::ostream& errStream, shared_ptr<AST> ast,
02955              shared_ptr<UocInfo> uoc,
02956              INOstream &out, INOstream &initStream,
02957              set<string> &decls,
02958              unsigned long flags)
02959 {
02960   bool answer = true;
02961   bool errorFree = true;
02962   assert(ast->astType == at_define || ast->astType == at_recdef);
02963   out << "static "
02964       << toCtype(ast->getID()->symType)
02965       << endl
02966       << "__init" << ast->ID << "()" << endl
02967       << "{" << endl;
02968   out.more();
02969 
02970   shared_ptr<AST> id = ast->child(0)->child(0);
02971   shared_ptr<AST> body = ast->child(1);
02972   shared_ptr<AST> ret;
02973   assert(body->astType == at_container);
02974   if (body->child(1)->astType == at_letStar) {
02975     TOC(errStream, uoc, body, out, CMangle(id), decls, ast, 1, flags);
02976     out << ";" << endl;
02977 
02978     ret = FEXPR(body->child(1));        
02979   }
02980   else {
02981     ret = body->child(1); // trivial return
02982   }
02983   assert(ret);
02984   out <<  "return ";
02985   TOC(errStream, uoc, ret, out, CMangle(id), decls, ast, 1, flags);        
02986   out << ";" << endl;
02987   out.less();
02988   out << "}" << endl;
02989 
02990   initStream << CMangle(ast->getID()) << " = ";
02991   initStream << "__init" << ast->ID << "();" << endl;        
02992   return errorFree;
02993 }
02994 
02995 static bool
02996 EmitGlobalInitializers(std::ostream& errStream,
02997                        shared_ptr<UocInfo> uoc,
02998                        INOstream &out,
02999                        set<string> &decls,
03000                        unsigned long flags)
03001 {
03002   bool errFree = true;
03003   stringstream is;
03004   INOstream initStream(is);
03005 
03006   initStream.more();
03007 
03008   shared_ptr<AST> mod = uoc->uocAst;
03009   for (size_t c = 0; c < mod->children.size(); c++) {
03010     shared_ptr<AST> ast = mod->child(c);
03011 
03012     switch(ast->astType) {
03013     case at_define:
03014     case at_recdef:
03015       {
03016         // Later, we might consider:
03017         //initStream << "#line " << ast->loc.line
03018         //    << " \"" << *(ast->loc.path) << "\""
03019         //    << std::endl;
03020 
03021         out << "////////////////////////////////////////" << endl;
03022         out.setPostindent("// ");
03023         out << ast->loc << endl
03024             << ast->asString(pp_Raw) << endl;
03025         out.setPostindent("");
03026         out << "////////////////////////////////////////" << endl;
03027         
03028         shared_ptr<AST> id = ast->getID();
03029         shared_ptr<AST> label = GC_NULL;
03030         bool wrapperNeeded = false;
03031 
03032         // Case 0: Immutable functions that are not of the form
03033         //           (define f (lambda (...) ... ))
03034         //           These may be cases like
03035         //           (define plus +)
03036         //           (define f (let ((x 2)) (lambda ... )))
03037         // In this case too, we must emit a label. We emit the
03038         // actual function as a pointer, initialize it as applicable
03039         // (trivial or through initialization procedure), and finally
03040         // emit a wrapper function as a label.
03041         if ((id->symType->isFnxn()) && (!id->symType->isMutable()) &&
03042             (ast->child(1)->astType != at_lambda)) {
03043           wrapperNeeded = true;
03044           label = AST::make(id);
03045           ast->rename(id, WFN_PFX + id->s);
03046         }
03047         
03048         if (ast->flags & DEF_IS_TRIVIAL_INIT) {
03049           // Case 1: marked trivial initializer,
03050           //         including immutable functions that are of the form
03051           //         (define f (lambda (...) ... ))
03052           // Header-Mode is taken care of by TOC()
03053           CHKERR(errFree, toc(errStream, uoc, ast, out, "", decls,
03054                               mod, c, flags));
03055         }
03056         else if (ast->child(1)->astType == at_lambda) {        
03057           assert(!id->symType->isMutable()); // Immutable lambda
03058                         // definitions are marked DEF_IS_TRIVIAL_INIT        
03059           // Case 2: Mutable functions that are of the form
03060           //         (define f (lambda (...) ... ))
03061           // We emit a label and a pointer. First we must emit a
03062           // declaration for the (mutable) pointer, then the label
03063           // (full function), and finally, initialize the pointer.
03064         
03065           shared_ptr<AST> ptr = AST::make(id);
03066           id->s = MFN_PFX + id->s;
03067           out << "extern " << decl(ptr) << ";" << endl;
03068           CHKERR(errFree, toc(errStream, uoc, ast, out, "", decls,
03069                               mod, c, flags));        
03070           out << decl(ptr) << " = " << CMangle(id)
03071               << ";" << endl << endl;
03072           id->s = ptr->s; // just in case ...
03073         }        
03074         else {
03075           // case 3: Non-trivial initialization value
03076           //         Needs an initialization procedure
03077         
03078           // This is actually the definition, but the value
03079           // will be initialized later from main()
03080           declare(out, ast->getID());
03081         
03082           // Emit a procedure that will initialize this value
03083           CHKERR(errFree, emitInitProc(errStream, ast, uoc, out,
03084                                        initStream, decls, flags));
03085         }
03086         
03087         if (wrapperNeeded) {
03088           shared_ptr<Type> fnType = id->symType->getBareType();
03089           shared_ptr<Type> ret = fnType->Ret();
03090           shared_ptr<Type> args = fnType->Args()->getBareType();
03091         
03092           emit_fnxn_type(out, label->s, id->symType);
03093           out << endl;
03094           out << "{" << endl;
03095           out.more();
03096         
03097           if (!isUnitType(ret))
03098             out << "return ";
03099 
03100           out << CMangle(id);
03101           out << "(";
03102           for (size_t i=0; i < args->components.size(); i++) {
03103             shared_ptr<Type> arg = args->CompType(i);
03104             if (isUnitType(arg))
03105               continue;
03106 
03107             if (i > 0)
03108               out << ", ";
03109         
03110             out << "arg" << i;
03111           }
03112           out << ");" << endl;
03113 
03114           out.less();
03115           out << "}" << endl << endl;        
03116         } else {
03117         }
03118         
03119         break;
03120       }
03121 
03122     case at_proclaim:
03123       {
03124         //initStream << "#line " << ast->loc.line
03125         //    << " \"" << *(ast->loc.path) << "\""
03126         //    << std::endl;
03127 
03128         out << "////////////////////////////////////////" << endl;
03129         out.setPostindent("// ");
03130         out << ast->loc << endl
03131             << ast->asString(pp_Raw) << endl;
03132         out.setPostindent("");
03133         out << "////////////////////////////////////////" << endl;
03134         
03135         CHKERR(errFree, toc(errStream, uoc, ast, out, "", decls,
03136                             mod, c, flags));
03137         break;
03138       }
03139 
03140     default:
03141       {
03142         break;
03143       }
03144     }
03145     out << endl << endl;
03146   }
03147 
03148   initStream.less();
03149 
03150   // Making this unconditional simplifies things, and it does not
03151   // really hurt us.
03152   out << "////////////////////////////////////////" << endl;
03153   out.setPostindent("// ");
03154   out << "The Initializer";
03155   out.setPostindent("");
03156   out << "////////////////////////////////////////" << endl;
03157   if (UocInfo::mainIsDefined)
03158     out << "static " ;
03159   out << "void"                                      << endl
03160       << "bitc_init_globals()"                       << endl
03161       << "{" << endl;
03162   out << is.str();
03163   out << "}" << endl;
03164   out << endl;
03165 
03166 
03167   return errFree;
03168 }
03169 
03170 static bool
03171 EmitMain(INOstream &out)
03172 {
03173   bool errFree = true;
03174 
03175   out << "////////////////////////////////////////" << endl;
03176   out.setPostindent("// ");
03177   out << "The main procedure";
03178   out.setPostindent("");
03179   out << "////////////////////////////////////////" << endl;
03180 
03181   out << "int"                                       << endl
03182       << "main(int argc, char*argv[])"               << endl
03183       << "{"                                         << endl;
03184   out.more();
03185   out << "int result;" << endl;
03186   out << "int i;" << endl << endl;
03187 
03188   out.less();
03189   out << "#if defined(__linux__)" << endl;
03190   out.more();
03191   out << "int my_personality = personality(-1);" << endl;
03192   out << "my_personality |= 0x0400000; /* READ_IMPLIES_EXEC */" << endl;
03193   out << "personality(my_personality);" << endl;
03194   out.less();
03195   out << "#endif" << endl;
03196   out.more();
03197 
03198   out << "GC_INIT();" << endl;
03199   out << endl;
03200   out << "result = setjmp(firstJB);" << endl
03201       << "if (!result) {" << endl;
03202   out.more();
03203 
03204   out << "bitc_init_globals();" << endl;
03205 
03206   out << "TY_VECTOR_OF_STRINGS *argVec = " << endl;
03207   out.more();
03208   out << "(TY_VECTOR_OF_STRINGS*) GC_ALLOC(sizeof(TY_VECTOR_OF_STRINGS));"
03209       << endl;
03210   out.less();
03211 
03212   out << "argVec->length = argc;" << endl
03213       << "argVec->elem = " << endl;
03214   out.more();
03215   out << "(bitc_string_t **) GC_ALLOC(sizeof(bitc_string_t *) * argc);"
03216       << endl;
03217   out.less();
03218   out << "for (i = 0; i < argc; i++)" << endl;
03219   out.more();
03220   out << "argVec->elem[i] = mkStringLiteral(argv[i]);" << endl;
03221   out.less();
03222   out << endl;
03223 
03224   out << "return bitc_main(argVec)"
03225       << ";" << endl;
03226 
03227   out.less();
03228   out << "}" << endl;
03229   out << "else {" << endl;
03230   out.more();
03231   out << "printf(\"Uncaught %s exception raised at %s:%d\\n\", "
03232       << "curException->__name, curException->__fileName, curException->__line);" << endl
03233       << "exit(1);" << endl;
03234   out.less();
03235   out << "}" << endl;
03236   out.less();
03237   out  << "}"  << endl;
03238 
03239   return errFree;
03240 }
03241 
03242 static bool
03243 ValuesTOH(std::ostream& errStream,
03244           shared_ptr<UocInfo> uoc,
03245           INOstream &out,
03246           set<string> &decls,
03247           unsigned long flags)
03248 {
03249   bool errFree = true;
03250 
03251   shared_ptr<AST> mod = uoc->uocAst;
03252   for (size_t c = 0; c < mod->children.size(); c++) {
03253     shared_ptr<AST> ast = mod->child(c);
03254     switch(ast->astType) {
03255     case at_proclaim:
03256       {
03257         if (ast->getID()->flags & DEF_IS_EXTERNAL) {
03258           out << "////////////////////////////////////////" << endl;
03259           out.setPostindent("// ");
03260           out << ast->loc << endl
03261               << ast->asString(pp_Raw) << endl;
03262           out.setPostindent("");
03263           out << "////////////////////////////////////////" << endl;
03264 
03265           CHKERR(errFree, toc(errStream, uoc, ast, out, "", decls,
03266                               mod, c, flags));
03267           out << endl;
03268         }
03269         break;
03270       }
03271     default:
03272       {
03273         break;
03274       }
03275     }
03276   }
03277   return errFree;
03278 }
03279 
03280 bool
03281 GenerateCoutput(std::ostream &errStream, INOstream &out,
03282                 unsigned long flags, shared_ptr<UocInfo> uoc)
03283 {
03284   bool errFree = true;
03285 
03286   assert(uoc);
03287   set<string> decls;
03288 
03289   out << "/////////////////////////////////////////////" << endl;
03290   out.setPostindent("// ");
03291   out << "   This code was automatically generated by "  << endl
03292       << "   BitC compiler version " << Version()        << endl
03293       << endl
03294       << "        !!!     DO NOT EDIT     !!!   "        << endl
03295       << "         !!  uness you are sure !!  "          << endl;
03296   out.setPostindent("");
03297   out << "/////////////////////////////////////////////" << endl;
03298 
03299   //  ifstream runtime(BITCCDIR"/runtime.h");
03300 
03301   // if (!runtime.is_open()) {
03302   //    errStream << BITCCDIR"/runtime.h cannot be found"
03303   //              << endl;
03304   // return false;
03305   //}
03306 
03307   //string s;
03308   //while (!runtime.eof()) {
03309   //  getline(runtime, s);
03310   //  out << s << endl;
03311   // }
03312   //runtime.close();
03313 
03314   out << "#include <bitc/runtime.h>" << endl << endl;
03315 
03316   out << "#if defined(__linux__)" << endl;
03317   out << "#include <sys/personality.h>" << endl;
03318   out << "#endif" << endl << endl;
03319 
03320   if ((flags & TOC_HEADER_MODE) == 0) {
03321     out << "jmp_buf firstJB;" << endl << endl;
03322     out << "jmp_buf *curCatchBlock = &firstJB;" << endl;
03323     out << "bitc_exception_t *curException;" << endl << endl;
03324   }
03325 
03326   CHKERR(errFree, TypesTOC(errStream, uoc, out, decls, flags));
03327 
03328   if (flags & TOC_HEADER_MODE) {
03329     CHKERR(errFree, ValuesTOH(errStream, uoc, out, decls, flags));
03330   }
03331   else {
03332     // If there are *any* entry points, emit the procedure that
03333     // handles global initialization so that it can be called:
03334     if (!Options::entryPts.empty())
03335       CHKERR(errFree, EmitGlobalInitializers(errStream, uoc, out,
03336                                              decls, flags));
03337 
03338     // If bitc.main:main is an entry point, emit the wrapping main
03339     // procedure that calls the global initializers and processes the
03340     // argument vector.
03341     if (UocInfo::mainIsDefined)
03342       EmitMain(out);
03343   }
03344 
03345   return errFree;
03346 }
03347 
03348 bool
03349 EmitHeader(std::ostream &optStream, std::ostream &errStream,
03350            shared_ptr<UocInfo> uoc)
03351 {
03352   std::ofstream out(Options::outputFileName.c_str(),
03353                     std::ios_base::out|std::ios_base::trunc);
03354 
03355   if (!out.is_open())
03356     errStream << "Couldn't open output file \""
03357               << Options::outputFileName
03358               << "\" -- "
03359               << strerror(errno)
03360               << endl;
03361 
03362   INOstream ino_out(out);
03363   bool result = GenerateCoutput(errStream, ino_out,
03364                                 TOC_HEADER_MODE, uoc);
03365   out.close();
03366   return result;
03367 }
03368 
03369 bool
03370 EmitC(std::ostream &optStream, std::ostream &errStream,
03371       shared_ptr<UocInfo> uoc)
03372 {
03373   std::ofstream out(Options::outputFileName.c_str(),
03374                     std::ios_base::out|std::ios_base::trunc);
03375   if (!out.is_open())
03376     errStream << "Couldn't open output file \""
03377               << Options::outputFileName
03378               << "\" -- "
03379               << strerror(errno)
03380               << endl;
03381 
03382   INOstream ino_out(out);
03383   bool result = GenerateCoutput(errStream, ino_out, 0, uoc);
03384   out.close();
03385   return result;
03386 }
03387 
03388 bool
03389 EmitExe(std::ostream &optStream, std::ostream &errStream,
03390         shared_ptr<UocInfo> uoc)
03391 {
03392   std::ofstream csrc("bitc.out.c",
03393                      std::ios_base::out|std::ios_base::trunc);
03394 
03395   if (!csrc.is_open()) {
03396     errStream << "Couldn't open auxiliary file \""
03397               << "bitc.out.c"
03398               << "\" -- "
03399               << strerror(errno)
03400               << "\n";
03401     return false;
03402   }
03403 
03404   INOstream out(csrc);
03405   bool result = GenerateCoutput(errStream, out, 0, uoc);
03406   csrc.close();
03407 
03408   if (!result)
03409     return false;
03410 
03411   int status;
03412 
03413   /* First GCC invocation is to compile the .c file into a .o file: */
03414   {
03415     stringstream opt;
03416     opt << STD_CC_CMD << " -c ";
03417 
03418     for (size_t i = 0; i < Options::CompilePreOptionsGCC.size(); i++)
03419       opt << " " << Options::CompilePreOptionsGCC[i];
03420 
03421     opt << " -o bitc.out.o";
03422     opt << " bitc.out.c";
03423 
03424     if (Options::verbose)
03425       std::cerr  << opt.str() << std::endl;
03426 
03427     status = ::system(opt.str().c_str());
03428     if (WEXITSTATUS(status))
03429       goto done;
03430   }
03431 
03432   {
03433     stringstream opt;
03434     opt << "gcc";
03435 
03436     for (size_t i = 0; i < Options::LinkPreOptionsGCC.size(); i++)
03437       opt << " " << Options::LinkPreOptionsGCC[i];
03438 
03439     opt << " bitc.out.o";
03440 
03441     for (size_t i = 0; i < Options::LinkPostOptionsGCC.size(); i++)
03442       opt << " " << Options::LinkPostOptionsGCC[i];
03443 
03444     if (Options::useStdLib)
03445       opt << " -lbitc";
03446 
03447     if (Options::noGC)
03448       opt << " -lbitc-no-gc";
03449     else
03450       opt << " -lgc";
03451 
03452     if (Options::verbose)
03453       std::cerr  << opt.str() << std::endl;
03454 
03455     status = ::system(opt.str().c_str());
03456   }
03457 
03458  done:
03459   filesystem::remove("bitc.out.c");
03460   filesystem::remove("bitc.out.o");
03461 
03462   return WEXITSTATUS(status) ? false : true;
03463 }
03464 

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