basix_doc 0.1
/Users/mourrain/Devel/mmx/basix/src/cpp_printer.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : cpp_printer.cpp
00004 * DESCRIPTION: C++ tree printer
00005 * COPYRIGHT  : (C) 2000  Joris van der Hoeven, 2007  Gregoire Lecerf
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #include <basix/basix-config.hpp>
00014 #if defined (BASIX_HAVE_CXXABI_H)
00015 #include <cxxabi.h>
00016 #endif
00017 #include <basix/cpp_syntax.hpp>
00018 #include <basix/list.hpp>
00019 #include <basix/table.hpp>
00020 #include <basix/literal.hpp>
00021 #include <basix/compound.hpp>
00022 
00023 namespace mmx {
00024 
00025 generic CPP_APPLY (".()");
00026 generic CPP_ACCESS (".[]");
00027 generic CPP_ALIAS_TYPE ("Alias");
00028 generic CPP_AND ("and");
00029 generic CPP_ARRAY_TYPE ("Array");
00030 generic CPP_ARROW ("->");
00031 generic CPP_ASSIGN (":=");
00032 generic CPP_BEGIN ("begin");
00033 generic CPP_BITWISE_AND ("/\\");
00034 generic CPP_BITWISE_OR ("\\/");
00035 generic CPP_BITWISE_XOR ("xor");
00036 generic CPP_BOOL_TYPE ("Boolean");
00037 generic CPP_BRACKETS ("()");
00038 generic CPP_BREAK ("break");
00039 generic CPP_CAST (":>");
00040 generic CPP_CATCH ("catch");
00041 generic CPP_CHAR_TYPE ("Char");
00042 generic CPP_CLASS_TYPE ("Type");
00043 generic CPP_COMMA (",");
00044 generic CPP_COMPLEMENT ("~");
00045 generic CPP_CONST ("const");
00046 generic CPP_CONST_METHOD ("const_method");
00047 generic CPP_CONSTRUCT ("construct");
00048 generic CPP_CONSTRUCTOR ("constructor");
00049 generic CPP_CONTINUE ("continue");
00050 generic CPP_DEFINE ("==");
00051 generic CPP_DELETE ("delete");
00052 generic CPP_DESTRUCTOR ("destructor");
00053 generic CPP_DO ("do");
00054 generic CPP_DOT (".");
00055 generic CPP_ELSE ("else");
00056 generic CPP_EQUAL ("=");
00057 generic CPP_EXIT ("exit");
00058 generic CPP_EXTERN ("extern");
00059 generic CPP_EXTERN_C ("extern_C");
00060 generic CPP_FOR ("for");
00061 generic CPP_FRIEND ("friend");
00062 generic CPP_FUNCTION_TYPE ("Function");
00063 generic CPP_GTR (">");
00064 generic CPP_GTREQ (">=");
00065 generic CPP_GTRGTR (">>");
00066 generic CPP_GTRGTREQ (">>=");
00067 generic CPP_IF ("if");
00068 generic CPP_INHERIT ("inherit");
00069 generic CPP_INITIALIZE ("initialize");
00070 generic CPP_INLINE ("inline");
00071 generic CPP_INT_TYPE ("Int");
00072 generic CPP_LESS ("<");
00073 generic CPP_LESSEQ ("<=");
00074 generic CPP_LESSLESS ("<<");
00075 generic CPP_LESSLESSEQ ("<<=");
00076 generic CPP_MACRO ("cpp_macro");
00077 generic CPP_MINUS ("-");
00078 generic CPP_MINUS_ASSIGN ("-=");
00079 generic CPP_MMX_APPLICATION_TYPE ("Mmx_application");
00080 generic CPP_MOD ("%");
00081 generic CPP_MOD_ASSIGN ("%=");
00082 generic CPP_NAMESPACE ("namespace");
00083 generic CPP_NEW ("new");
00084 generic CPP_NOT ("!");
00085 generic CPP_OR ("or");
00086 generic CPP_OVER ("/");
00087 generic CPP_OVER_ASSIGN ("/=");
00088 generic CPP_PLUS ("+");
00089 generic CPP_PLUS_ASSIGN ("+=");
00090 generic CPP_POINTER_TYPE ("Pointer");
00091 generic CPP_POSTDEC (".--");
00092 generic CPP_POSTINC (".++");
00093 generic CPP_POWER ("^");
00094 generic CPP_PREDEC ("--.");
00095 generic CPP_PREINC ("++.");
00096 generic CPP_PUBLIC ("public");
00097 generic CPP_RETURN ("return");
00098 generic CPP_SCOPE ("::");
00099 generic CPP_SEMICOLON (";");
00100 generic CPP_SPECIALIZE ("specialize");
00101 generic CPP_STATIC ("static");
00102 generic CPP_STRING_TYPE ("String");
00103 generic CPP_STRUCT ("struct");
00104 generic CPP_SWITCH ("switch");
00105 generic CPP_TEMPLATE ("template");
00106 generic CPP_THROW ("raise");
00107 generic CPP_TIMES ("*");
00108 generic CPP_TIMES_ASSIGN ("*=");
00109 generic CPP_TRY ("try");
00110 generic CPP_TYPE (":");
00111 generic CPP_TYPEDEF ("typedef");
00112 generic CPP_TYPE_CONSTRUCTOR ("type_constructor");
00113 generic CPP_UNALIAS ("unalias");
00114 generic CPP_UNEQUAL ("!=");
00115 generic CPP_UNFUNCTION ("unfunction");
00116 generic CPP_UNPOINTER ("unpointer");
00117 generic CPP_USING ("using");
00118 generic CPP_VERBATIM ("verbatim");
00119 generic CPP_VIRTUAL ("virtual");
00120 generic CPP_VOID_TYPE ("Void");
00121 generic CPP_WHILE ("while");
00122 generic CPP_XOR ("^^");
00123 
00124 /******************************************************************************
00125 * Useful symbols and subroutines
00126 ******************************************************************************/
00127 
00128 inline generic
00129 cAr (const vector<generic>& a) {
00130   if (N(a) == 0)
00131     return generic ();
00132   return a[N(a)-1];
00133 }
00134 
00135 inline vector<generic>
00136 cDr (const vector<generic>& a) {
00137   if (N(a) == 0)
00138     return a;
00139   return range (a,0,N(a)-1);
00140 }
00141 
00142 #define SET_OPNAME(var, val) \
00143   t [literal_to_string (var)] = val; \
00144   t [string ("operator ") * val] = val;
00145 
00146 static table<string, string>
00147 opname_table () {
00148   table<string, string> t;
00149   SET_OPNAME (CPP_PLUS, "+")
00150   SET_OPNAME (CPP_MINUS, "-");
00151   SET_OPNAME (CPP_TIMES, "*");
00152   SET_OPNAME (CPP_OVER, "/");
00153   SET_OPNAME (CPP_MOD, "%");
00154   SET_OPNAME (CPP_AND, "&&");
00155   SET_OPNAME (CPP_OR, "||");
00156   SET_OPNAME (CPP_NOT, "!");
00157   SET_OPNAME (CPP_BITWISE_AND, "&");
00158   SET_OPNAME (CPP_BITWISE_OR, "|");
00159   SET_OPNAME (CPP_BITWISE_XOR, "^");
00160   SET_OPNAME (CPP_ASSIGN, "=");
00161   SET_OPNAME (CPP_LESS, "<");
00162   SET_OPNAME (CPP_GTR, ">");
00163   SET_OPNAME (CPP_PLUS_ASSIGN, "+=");
00164   SET_OPNAME (CPP_MINUS_ASSIGN, "-=");
00165   SET_OPNAME (CPP_TIMES_ASSIGN, "*=");
00166   SET_OPNAME (CPP_OVER_ASSIGN, "/=");
00167   SET_OPNAME (CPP_MOD_ASSIGN, "%=");
00168   SET_OPNAME (CPP_LESSLESS, "<<");
00169   SET_OPNAME (CPP_LESSLESSEQ, "<<=");
00170   SET_OPNAME (CPP_GTRGTR, ">>");
00171   SET_OPNAME (CPP_GTRGTREQ, ">>=");
00172   SET_OPNAME (CPP_EQUAL, "==");
00173   SET_OPNAME (CPP_UNEQUAL, "!=");
00174   SET_OPNAME (CPP_LESSEQ, "<=");
00175   SET_OPNAME (CPP_GTREQ, ">=");
00176   SET_OPNAME (CPP_PREINC, "++");
00177   SET_OPNAME (CPP_PREDEC, "--");
00178   SET_OPNAME (CPP_ACCESS, "[]");
00179   SET_OPNAME (CPP_COMPLEMENT, "~");
00180   SET_OPNAME (CPP_ARROW, "->");
00181   return t;
00182 }
00183 
00184 /******************************************************************************
00185 * Printing to strings
00186 ******************************************************************************/
00187 
00188 enum print_controls { LF, INDENT, UNINDENT };
00189 
00190 static nat indentation_level= 0;
00191 
00192 static string&
00193 operator << (string& out, print_controls pc) {
00194   switch (pc) {
00195   case LF:
00196     out << "\n";
00197     for (nat i=0; i<indentation_level; i++) out << "  ";
00198     break;
00199   case INDENT:
00200     indentation_level++;
00201     out << "  ";
00202     break;
00203   case UNINDENT:
00204     indentation_level--;
00205     if (N(out) >= 2 && out[N(out)-2] == ' ' && out[N(out)-1] == ' ')
00206       inside (out) -> resize (N(out) - 2);
00207     break;
00208   }
00209   return out;
00210 }
00211 
00212 static string&
00213 operator << (string& out, const char* s) {
00214   return out << string (s);
00215 }
00216 
00217 static string&
00218 operator << (string& out, const generic& g) {
00219   if (is<string> (g)) return out << as<string> (g);
00220   if (is<literal> (g)) return out << (*(as<literal> (g)));
00221   mmerr << g << ": " << type_name (g) << "\n";
00222   assert (false);
00223   return out;
00224 }
00225 
00226 /******************************************************************************
00227 * The cpp printer class
00228 ******************************************************************************/
00229 
00230 class cpp_printer {
00231 private:
00232   string        out;
00233   list<generic> sl;
00234   bool          lf_flag;
00235   bool          lf_done;
00236 
00237 private:
00238   void pp_begin (const generic& g);
00239   void pp_instr (const generic& g);
00240   void pp_init (const generic& g);
00241 
00242   void pp_decl (const generic& var, bool large= true);
00243   void pp_decl (const generic& var, const generic& type, bool large);
00244   void pp_type (const generic& g);
00245   void pp_funarg (const generic& g);
00246   void pp_funargs (const generic& g);
00247 
00248   void pp_expr (const generic& g);
00249   void pp_exprs (const generic& g);
00250   void pp_comma (const generic& g);
00251   void pp_assign (const generic& g);
00252 
00253   void pp_cond (const generic& g);
00254   void pp_seqor (const generic& g);
00255   void pp_seqand (const generic& g);
00256   void pp_or (const generic& g);
00257   void pp_xor (const generic& g);
00258   void pp_and (const generic& g);
00259   void pp_eq (const generic& g);
00260   void pp_rel (const generic& g);
00261 
00262   void pp_shift (const generic& g);
00263   void pp_lshift (const generic& g);
00264   void pp_rshift (const generic& g);
00265   void pp_add (const generic& g);
00266   void pp_mult (const generic& g);
00267 
00268   void pp_unary (const generic& g);
00269   void pp_postfix (const generic& g);
00270   void pp_primary (const generic& g);
00271     
00272 public:
00273   inline cpp_printer (): out ("") { indentation_level= 0; }
00274   inline ~cpp_printer () {}
00275 
00276   void pp (const generic& g);
00277   friend string as_cpp (const generic& g);
00278 };
00279 
00280 /******************************************************************************
00281 * Required routines for generic structures
00282 ******************************************************************************/
00283 
00284 inline syntactic
00285 flatten (const cpp_printer& p) {
00286   return "#cpp_printer<>";
00287 }
00288 
00289 inline nat
00290 hash (const cpp_printer& p) {
00291   return 0;
00292 }
00293 
00294 /******************************************************************************
00295 * ABI support for name unmangling
00296 ******************************************************************************/
00297 
00298 #if defined (BASIX_HAVE_CXXABI_H)
00299 
00300 string cpp_demangle(const char* name) {
00301   size_t size= 4096;
00302   char* buf= (char*) malloc (size);
00303   int status;
00304   char* res= abi::__cxa_demangle (name, buf, &size, &status);
00305   string ans (res); free ((void*) res);
00306   ASSERT (status==0, "invalid C++ type name");
00307   return ans;
00308 }
00309 
00310 #else
00311 
00312 string cpp_demangle(const char* name) {
00313   static bool first= true;
00314   if (first) {
00315     mmerr << "Warning: C++ name unmangling is not available\n";
00316     first= false;
00317   }
00318   return string (name);
00319 }
00320 
00321 #endif
00322 
00323 /******************************************************************************
00324 * Instructions
00325 ******************************************************************************/
00326 
00327 void
00328 cpp_printer::pp_instr (const generic& g) {
00329   if (is_func (g, CPP_VERBATIM, 1) && is<string> (g[1])) {
00330     string s = as<string> (g[1]);
00331     int i, n = N(s);
00332     for (i=0; i<n; i++)
00333       if (s[i] == '\n') out << LF;
00334       else out << s[i];
00335   }
00336   else if (is_func (g, CPP_NAMESPACE, 2)) {
00337     out << "namespace " << g[1] << " {" << LF << INDENT;
00338     pp_begin (g[2]);
00339     out << UNINDENT << "}" << LF;
00340   }
00341   else if (is_func (g, CPP_INITIALIZE)) {
00342     pp_init (g);
00343     generic last= cAr (compound_to_vector (g));
00344     if (is_func (last, CPP_BEGIN)) pp_instr (last);
00345     else pp_instr (gen (CPP_BEGIN, last));
00346   }
00347   else if (is_func (g, CPP_BEGIN)) {
00348     out << "{" << LF << INDENT;
00349     pp_begin (g);
00350     out << UNINDENT << "}" << LF;
00351   }
00352   else if (is_func (g, CPP_IF, 2)) {
00353     out << "if (";
00354     pp_expr (g[1]);
00355     out << ") ";
00356     if (is_func (g[2], CPP_IF)) pp_instr (gen (CPP_BEGIN, g[2]));
00357     else pp_instr (g[2]);
00358   }
00359   else if (is_func (g, CPP_IF, 3)) {
00360     out << "if (";
00361     pp_expr (g[1]);
00362     out << ") ";
00363     if (is_func (g[2], CPP_IF, 2)) pp_instr (gen (CPP_BEGIN, g[2]));
00364     else pp_instr (g[2]);
00365     out << "else ";
00366     pp_instr (g[3]);
00367   }
00368   else if (is_func (g, CPP_WHILE, 2)) {
00369     out << "while (";
00370     pp_expr (g[1]);
00371     out << ") ";
00372     pp_instr (g[2]);
00373   }
00374   else if (is_func (g, CPP_DO, 2)) {
00375     out << "do ";
00376     pp_instr (g[1]);
00377     out << "while (";
00378     pp_expr (g[2]);
00379     out << ");";
00380   }
00381   else if (is_func (g, CPP_FOR, 4)) {
00382     out << "for (";
00383     pp_expr (g[1]);
00384     out << "; ";
00385     pp_expr (g[2]);
00386     out << "; ";
00387     pp_expr (g[3]);
00388     out << ") ";
00389     pp_instr (g[4]);
00390   }
00391   else if (is_func (g, CPP_BREAK, 0))
00392     out << "break;" << LF;
00393   else if (is_func (g, CPP_CONTINUE, 0))
00394     out << "continue;" << LF;
00395   else if (is_func (g, CPP_RETURN, 0))
00396     out << "return;" << LF;
00397   else if (is_func (g, CPP_RETURN, 1)) {
00398     out << "return ";
00399     pp_expr (g[1]);
00400     out << ";" << LF;
00401   }
00402   else if (is_func (g, CPP_THROW, 1)) {
00403     out << "throw ";
00404     pp_expr (g[1]);
00405     out << ";" << LF;
00406   }
00407   else if (is_func (g, CPP_TRY) && N(g) >= 2) {
00408     out << "try ";
00409     pp_instr (is_func (g[1], CPP_BEGIN)? g[1]: gen (CPP_BEGIN, g[1]));
00410     for (nat i=2; i<N(g); i++) pp_instr (g[i]);
00411   }
00412   else if (is_func (g, CPP_CATCH, 2)) {
00413     out << "catch (";
00414     pp_decl (g[1], false);
00415     out << ") ";
00416     pp_instr (g[2]);
00417   }
00418   else if (is_func (g, CPP_EXTERN_C, 1)) {
00419     out << "extern \"C\" ";
00420     pp (g[1]);
00421   }
00422   else pp_decl (g);
00423 }
00424 
00425 void
00426 cpp_printer::pp_init (const generic& g) {
00427   vector<generic> l= cDr (cdr (compound_to_vector (g)));
00428   iterator<generic> i = iterate (l);
00429   bool first= true;
00430   for ( ; busy (i); ++i) {
00431     if (first) out << ": ";
00432     else out << ", ";
00433     pp_expr (*i);
00434     first= false;
00435   }
00436 }
00437 
00438 void
00439 cpp_printer::pp_begin (const generic& g) {
00440   if (is_func (g, CPP_BEGIN) || is_func (g, CPP_STRUCT)) {
00441     lf_flag= false;
00442     lf_done= true;
00443     for (nat i=1; i<N(g); i++) {
00444       if (lf_flag) { out << LF; lf_flag= false; lf_done= true; }
00445       pp_instr (g[i]);
00446       lf_done= false;
00447     }
00448   }
00449   else pp_instr (g);
00450 }
00451 
00452 /******************************************************************************
00453 * Declarations
00454 ******************************************************************************/
00455 
00456 void
00457 cpp_printer::pp_decl (const generic& var, const generic& type, bool large) {
00458   // prefixes
00459   if (is_func (type, CPP_CONST, 1)) {
00460     out << "const ";
00461     pp_decl (var, type[1], large);
00462   }
00463   else if (is_func (type, CPP_CONST_METHOD, 1)) {
00464     pp_decl (var, type[1], large);
00465     out << " const";
00466   }
00467   else if (is_func (type, CPP_EXTERN, 1)) {
00468     out << "extern ";
00469     pp_decl (var, type[1], large);
00470   }
00471   else if (is_func (type, CPP_EXTERN, 2)) {
00472     out << "extern " << type[1] << " ";
00473     pp_decl (var, type[2], large);
00474   }
00475   else if (is_func (type, CPP_INLINE, 1)) {
00476     out << "inline ";
00477     pp_decl (var, type[1], large);
00478   }
00479   else if (is_func (type, CPP_FRIEND, 1)) {
00480     out << "friend ";
00481     pp_decl (var, type[1], large);
00482   }
00483   else if (is_func (type, CPP_STATIC, 1)) {
00484     out << "static ";
00485     pp_decl (var, type[1], large);
00486   }
00487   else if (is_func (type, CPP_VIRTUAL, 1)) {
00488     out << "virtual ";
00489     pp_decl (var, type[1], large);
00490   }
00491   else if (is_func (type, CPP_TEMPLATE)) {
00492     vector<generic> x= cDr (cdr (compound_to_vector (type)));
00493     out << "template<";
00494     bool first = true;
00495     iterator<generic> i;
00496     for (i = iterate (x); busy(i); ++i) {
00497       if (!first) out << ", ";
00498       pp_funarg (*i);
00499       first = false;
00500     }
00501     out << "> ";
00502     pp_decl (var, cAr (compound_to_vector (type)), large);
00503   }
00504 
00505   // rewriting into C++ form
00506   else if (is_func (type, CPP_ALIAS_TYPE, 1))
00507     pp_decl (gen (CPP_UNALIAS, var), type[1], large);
00508   else if (is_func (type, CPP_POINTER_TYPE, 1))
00509     pp_decl (gen (CPP_UNPOINTER, var), type[1], large);
00510   else if (is_func (type, CPP_ARRAY_TYPE)) {
00511     vector<generic> unfun= vec<generic> (CPP_ACCESS, var);
00512     vector<generic> args = cdr (cdr (compound_to_vector (type)));
00513     pp_decl (vector_to_compound (append (unfun, args)), type[1], large);
00514   }
00515   else if (is_func (type, CPP_FUNCTION_TYPE)) {
00516     vector<generic> unfun= vec<generic> (CPP_UNFUNCTION, var);
00517     vector<generic> args = cdr (cdr (compound_to_vector (type)));
00518     pp_decl (vector_to_compound (append (unfun, args)), type[1], large);
00519   }
00520   else if (is_func (type, CPP_CONSTRUCTOR)) {
00521     vector<generic> unfun= vec<generic> (CPP_UNFUNCTION, var);
00522     vector<generic> args = cdr (compound_to_vector (type));
00523     pp_decl (vector_to_compound (append (unfun, args)), "", large);
00524   }
00525   else if (is_func (type, CPP_DESTRUCTOR, 0))
00526     pp_decl (gen (CPP_UNFUNCTION, var), "~", large);
00527   else if (is_func (type, CPP_INHERIT)) {
00528     out << "struct " << var << ": ";
00529     iterator<generic> i;
00530     bool first = true;
00531     for (i = iterate (cdr (compound_to_vector (type))); busy(i); ++i) {
00532       if (!first) out << ", ";
00533       pp_type (*i);
00534       first = false;
00535     }
00536   }
00537 
00538   // normal declarations
00539   else if (type == "~") {
00540     if (is_func (var, CPP_UNFUNCTION, 1) && is_func (var[1], CPP_SCOPE, 2)) {
00541       generic v= var[1];
00542       ASSERT (!is_func (v[2], CPP_SCOPE, 2), "unimplemented nested scope");
00543       pp_type (v[1]);
00544       out << "::~";
00545       pp_type (v[2]);
00546       out << " ()";
00547     }
00548     else {
00549       out << "~";
00550       pp_expr (var);
00551     }
00552   }
00553   else {
00554     pp_type (type);
00555     if (type == "");
00556     else if (large && (type != CPP_CLASS_TYPE)) out << LF;
00557     else out << " ";
00558     pp_expr (var);
00559   }
00560 }
00561 
00562 static bool
00563 is_function_type (const generic& g) {
00564   return
00565     is_func (g, CPP_FUNCTION_TYPE) ||
00566     (is_func (g, CPP_INLINE, 1) && is_function_type (g[1])) ||
00567     (is_func (g, CPP_STATIC, 1) && is_function_type (g[1]));
00568 }
00569 
00570 void
00571 cpp_printer::pp_decl (const generic& g, bool large) {
00572   if (is_func (g, CPP_TYPEDEF, 2)) {
00573     out << "typedef ";
00574     pp_decl (gen (CPP_TYPE, g[1], g[2]));
00575   }
00576   else if (is_func (g, CPP_DEFINE, 2) || is_func (g, CPP_ASSIGN, 2)) {
00577     bool large2= false;
00578     bool emptyb= false;
00579     if (is_func (g[1], CPP_TYPE, 2)) {
00580       // fix functions bodies which are not of the kind CPP_BEGIN
00581       if (is_function_type (g[1][2]) && !is_func (g[2], CPP_BEGIN)) {
00582         pp_decl (gen (g[0], g[1], gen (CPP_BEGIN, g[2])), large);
00583         return;
00584       }
00585 
00586       large2= is_func (g[2], CPP_INITIALIZE);
00587       large2 |= is_func (g[2], CPP_BEGIN);
00588       large2 |= is_func (g[2], CPP_STRUCT);
00589       emptyb |= is_func (g[2], CPP_BEGIN, 0);
00590       emptyb |= is_func (g[2], CPP_INITIALIZE) &&
00591         is_func (g[2][N(g[2])-1], CPP_BEGIN, 0);
00592       if (large && large2 && (!lf_done) && (!emptyb)) out << LF;
00593       if (is_func (g[2], CPP_CONSTRUCT)) {
00594         vector<generic> var=
00595           cons (g[1][1], cdr (compound_to_vector (g[2])));
00596         if (is_func (g, CPP_DEFINE, 2))
00597           pp_decl (vector_to_compound (var), gen (CPP_CONST, g[1][2]), large2);
00598         else pp_decl (vector_to_compound (var), g[1][2], large2);
00599       }
00600       else {
00601         if (is_func (g, CPP_DEFINE, 2) && (!large2))
00602           pp_decl (g[1][1], gen (CPP_CONST, g[1][2]), large2);
00603         else pp_decl (g[1][1], g[1][2], large2);
00604       }
00605     }
00606     else pp_cond (g[1]);
00607     if (large && large2) {
00608       generic h= g[2];
00609       if (is_func (h, CPP_INITIALIZE)) {
00610         pp_init (h);
00611         generic last= cAr (compound_to_vector (h));
00612         if (is_func (last, CPP_BEGIN)) h= last;
00613         else h= gen (CPP_BEGIN, last);
00614       }
00615       if (emptyb) {
00616         out << " {";
00617         pp_begin (h);
00618         out << "}";
00619         out << LF;
00620         lf_flag= false;
00621       }
00622       else {
00623         out << " {" << LF << INDENT;
00624         pp_begin (h);
00625         out << UNINDENT << "}";
00626         if (is_func (h, CPP_STRUCT)) out << ";";
00627         out << LF;
00628         lf_flag= true;
00629       }
00630     }
00631     else {
00632       if (!is_func (g[2], CPP_CONSTRUCT)) {
00633         out << " = ";
00634         pp_expr (g[2]);
00635       }
00636       if (large) out << ";" << LF;
00637     }
00638   }
00639   else if (is_func (g, CPP_TYPE, 2)) {
00640     pp_decl (g[1], g[2], false);
00641     if (large) out << ";" << LF;
00642   }
00643   else if (is_func (g, CPP_USING, 1)) {
00644     out << "using ";
00645     pp_expr (g[1]);
00646     out << ";" << LF;
00647   }
00648   else {
00649     pp_expr (g);
00650     out << ";" << LF;
00651   }
00652 }
00653 
00654 /******************************************************************************
00655 * Function arguments in function declarations
00656 ******************************************************************************/
00657 
00658 void
00659 cpp_printer::pp_type (const generic& g) {
00660   if (is_func (g, CPP_ALIAS_TYPE, 1)) {
00661     pp_type (g[1]);
00662     out << "&";
00663   }
00664   else if (is_func (g, CPP_POINTER_TYPE, 1)) {
00665     pp_type (g[1]);
00666     out << "*";
00667   }
00668   else if (is_func (g, CPP_SCOPE, 2)) {
00669     pp_type (g[1]);
00670     out << "::";
00671     pp_type (g[2]);
00672   }
00673   else if (is_func (g, CPP_CONST, 1)) {
00674     out << "const ";
00675     pp_type (g[1]);
00676   }
00677   else if (is_func (g, CPP_CONST_METHOD, 1)) {
00678     pp_type (g[1]);
00679     out << " const";
00680   }
00681   else if (is_func (g, CPP_PUBLIC, 1)) {
00682     out << "public ";
00683     pp_type (g[1]);
00684   }
00685   else if (is_func (g, CPP_SPECIALIZE)) {
00686     generic fun= g[1];
00687     bool macro_flag= is_func (fun, CPP_MACRO, 1);
00688     if (macro_flag) fun= fun[1];
00689     pp_postfix (fun);
00690     if (macro_flag) out << "(";
00691     else out << "<";
00692     pp_funargs (cdr (cdr (g)));
00693     if (N(g) > 2) out << " ";
00694     if (macro_flag) out << ")";
00695     else out << ">";
00696   }
00697   else if (is<compound> (g)) {
00698     vector<generic> l= compound_to_vector (g);
00699     generic fun= car (l);
00700     bool macro_flag= is_func (fun, CPP_MACRO, 1);
00701     if (macro_flag) fun= fun[1];
00702     pp_type (fun);
00703     l= cdr (l);
00704     if (macro_flag) out << "(";
00705     else out << "<";
00706     while (N (l) != 0) {
00707       pp_type (car (l));
00708       if (N(cdr (l)) !=0 && is<compound> (car (l)))
00709         out << " ";
00710       if (N (l) != 1) out << ", ";
00711       else if (is<compound> (l[0])) out << " ";
00712       l= cdr (l);
00713     }
00714     if (macro_flag) out << ")";
00715     else out << ">";
00716   }
00717   else if (g == CPP_CLASS_TYPE) out << "struct";
00718   else if (g == CPP_VOID_TYPE) out << "void";
00719   else if (g == CPP_BOOL_TYPE) out << "bool";
00720   else if (g == CPP_CHAR_TYPE) out << "char";
00721   else if (g == CPP_INT_TYPE) out << "int";
00722   else if (g == CPP_STRING_TYPE) out << "string";
00723   else out << g;
00724 }
00725 
00726 void
00727 cpp_printer::pp_funarg (const generic& g) {
00728   if (is_func (g, CPP_TYPE, 2) && (g[2] == CPP_CLASS_TYPE))
00729     pp_decl (g[1], CPP_CLASS_TYPE, false);
00730   else if (is_func (g, CPP_TYPE, 2))
00731     pp_decl (g[1], g[2], false);
00732   else if (is_func (g, CPP_DEFINE, 2) || is_func (g, CPP_ASSIGN, 2))
00733     pp_decl (g, false);
00734   else pp_type (g);
00735 }
00736 
00737 void
00738 cpp_printer::pp_funargs (const generic& g) {
00739   if (N(g) == 1) pp_funarg (car (g));
00740   if (N(g) <= 1) return;
00741   pp_funarg (car (g));
00742   out << ", ";
00743   pp_funargs (cdr (g));
00744 }
00745 
00746 /******************************************************************************
00747 * Expressions
00748 ******************************************************************************/
00749 
00750 void
00751 cpp_printer::pp_expr (const generic& g) {
00752   if (is_func (g, "$text", 1) || is_func (g, "$math", 1))
00753     pp_expr (g[1]);
00754   else pp_comma (g);
00755 }
00756 
00757 void
00758 cpp_printer::pp_exprs (const generic& g) {
00759   if (N(g) == 1) pp_expr (car (g));
00760   if (N(g) <= 1) return;
00761   pp_expr (car (g));
00762   out << ", ";
00763   pp_exprs (cdr (g));
00764 }
00765 
00766 void
00767 cpp_printer::pp_comma (const generic& g) {
00768   if (is_func (g, CPP_BEGIN)) {
00769     if (N(g) == 1);
00770     else if (N(g) == 2) pp_comma (g[1]);
00771     else for (nat i=1; i<N(g); i++) {
00772       if (i>1) out << ", ";
00773       pp_comma (g[i]);
00774     }
00775   }
00776   else pp_assign (g);
00777 }
00778 
00779 /******************************************************************************
00780 * Assignments
00781 ******************************************************************************/
00782 
00783 void
00784 cpp_printer::pp_assign (const generic& g) {
00785   if (is_func (g, CPP_ASSIGN, 2)) {
00786     pp_cond (g[1]);
00787     out << " = ";
00788     pp_assign (g[2]);
00789   }
00790   else if (is_func (g, CPP_PLUS_ASSIGN, 2)) {
00791     pp_cond (g[1]);
00792     out << " += ";
00793     pp_assign (g[2]);
00794   }
00795   else if (is_func (g, CPP_MINUS_ASSIGN, 2)) {
00796     pp_cond (g[1]);
00797     out << " -= ";
00798     pp_assign (g[2]);
00799   }
00800   else if (is_func (g, CPP_TIMES_ASSIGN, 2)) {
00801     pp_cond (g[1]);
00802     out << " *= ";
00803     pp_assign (g[2]);
00804   }
00805   else if (is_func (g, CPP_OVER_ASSIGN, 2)) {
00806     pp_cond (g[1]);
00807     out << " /= ";
00808     pp_assign (g[2]);
00809   }
00810   else if (is_func (g, CPP_MOD_ASSIGN, 2)) {
00811     pp_cond (g[1]);
00812     out << " %= ";
00813     pp_assign (g[2]);
00814   }
00815   else if (is_func (g, CPP_LESSLESSEQ, 2)) {
00816     pp_cond (g[1]);
00817     out << " <<= ";
00818     pp_assign (g[2]);
00819   }
00820   else if (is_func (g, CPP_GTRGTREQ, 2)) {
00821     pp_cond (g[1]);
00822     out << " >>= ";
00823     pp_assign (g[2]);
00824   }
00825   else pp_cond (g);
00826 }
00827 
00828 /******************************************************************************
00829 * Conditional expressions
00830 ******************************************************************************/
00831 
00832 void
00833 cpp_printer::pp_cond (const generic& g) {
00834   if (is_func (g, CPP_IF, 3)) {
00835     pp_seqor (g[1]);
00836     out << " ? ";
00837     pp_seqor (g[2]);
00838     out << " : ";
00839     pp_seqor (g[3]);
00840   }
00841   else pp_seqor (g);
00842 }
00843 
00844 /******************************************************************************
00845 * Logical expressions
00846 ******************************************************************************/
00847 
00848 void
00849 cpp_printer::pp_seqor (const generic& g) {
00850   if (is_func (g, CPP_OR, 2)) {
00851     pp_seqor (g[1]);
00852     out << " || ";
00853     pp_seqor (g[2]);
00854   }
00855   else pp_seqand (g);
00856 }
00857 
00858 void
00859 cpp_printer::pp_seqand (const generic& g) {
00860   if (is_func (g, CPP_AND, 2)) {
00861     pp_seqand (g[1]);
00862     out << " && ";
00863     pp_seqand (g[2]);
00864   }
00865   else pp_or (g);
00866 }
00867 
00868 void
00869 cpp_printer::pp_or (const generic& g) {
00870   if (is_func (g, CPP_BITWISE_OR, 2)) {
00871     pp_or (g[1]);
00872     out << " | ";
00873     pp_or (g[2]);
00874   }
00875   else pp_xor (g);
00876 }
00877 
00878 void
00879 cpp_printer::pp_xor (const generic& g) {
00880   if (is_func (g, CPP_BITWISE_XOR, 2)) {
00881     pp_xor (g[1]);
00882     out << " ^ ";
00883     pp_xor (g[2]);
00884   }
00885   else pp_and (g);
00886 }
00887 
00888 void
00889 cpp_printer::pp_and (const generic& g) {
00890   if (is_func (g, CPP_BITWISE_AND, 2)) {
00891     pp_and (g[1]);
00892     out << " & ";
00893     pp_and (g[2]);
00894   }
00895   else pp_eq (g);
00896 }
00897 
00898 /******************************************************************************
00899 * Relational expressions
00900 ******************************************************************************/
00901 
00902 void
00903 cpp_printer::pp_eq (const generic& g) {
00904   if (is_func (g, CPP_EQUAL, 2)) {
00905     pp_rel (g[1]);
00906     out << " == ";
00907     pp_rel (g[2]);
00908   }
00909   else if (is_func (g, CPP_UNEQUAL, 2)) {
00910     pp_rel (g[1]);
00911     out << " != ";
00912     pp_rel (g[2]);
00913   }
00914   else pp_rel (g);
00915 }
00916 
00917 void
00918 cpp_printer::pp_rel (const generic& g) {
00919   if (is_func (g, CPP_LESS, 2)) {
00920     pp_shift (g[1]);
00921     out << " < ";
00922     pp_shift (g[2]);
00923   }
00924   else if (is_func (g, CPP_LESSEQ, 2)) {
00925     pp_shift (g[1]);
00926     out << " <= ";
00927     pp_shift (g[2]);
00928   }
00929   else if (is_func (g, CPP_GTR, 2)) {
00930     pp_shift (g[1]);
00931     out << " > ";
00932     pp_shift (g[2]);
00933   }
00934   else if (is_func (g, CPP_GTREQ, 2)) {
00935     pp_shift (g[1]);
00936     out << " >= ";
00937     pp_shift (g[2]);
00938   }
00939   else pp_shift (g);
00940 }
00941 
00942 /******************************************************************************
00943 * Arithmetic expressions
00944 ******************************************************************************/
00945 
00946 void
00947 cpp_printer::pp_shift (const generic& g) {
00948   if (is_func (g, CPP_LESSLESS, 2)) {
00949     pp_lshift (g[1]);
00950     out << " << ";
00951     pp_add (g[2]);
00952   }
00953   else if (is_func (g, CPP_GTRGTR, 2)) {
00954     pp_add (g[1]);
00955     out << " >> ";
00956     pp_rshift (g[2]);
00957   }
00958   else pp_add (g);
00959 }
00960 
00961 void
00962 cpp_printer::pp_lshift (const generic& g) {
00963   if (is_func (g, CPP_LESSLESS, 2)) {
00964     pp_lshift (g[1]);
00965     out << " << ";
00966     pp_add (g[2]);
00967   }
00968   else pp_add (g);
00969 }
00970 
00971 void
00972 cpp_printer::pp_rshift (const generic& g) {
00973   if (is_func (g, CPP_GTRGTR, 2)) {
00974     pp_add (g[1]);
00975     out << " >> ";
00976     pp_rshift (g[2]);
00977   }
00978   else pp_add (g);
00979 }
00980 
00981 void
00982 cpp_printer::pp_add (const generic& g) {
00983   if (is_func (g, CPP_PLUS, 2)) {
00984     pp_add (g[1]);
00985     out << " + ";
00986     pp_add (g[2]);
00987   }
00988   else if (is_func (g, CPP_MINUS, 2)) {
00989     pp_add (g[1]);
00990     out << " - ";
00991     pp_mult (g[2]);
00992   }
00993   else pp_mult (g);
00994 }
00995 
00996 void
00997 cpp_printer::pp_mult (const generic& g) {
00998   if (is_func (g, CPP_TIMES, 2)) {
00999     pp_mult (g[1]);
01000     out << " * ";
01001     pp_mult (g[2]);
01002   }
01003   else if (is_func (g, CPP_OVER, 2)) {
01004     pp_mult (g[1]);
01005     out << " / ";
01006     pp_unary (g[2]);
01007   }
01008   else if (is_func (g, CPP_MOD, 2)) {
01009     pp_mult (g[1]);
01010     out << " % ";
01011     pp_unary (g[2]);
01012   }
01013   else pp_unary (g);
01014 }
01015 
01016 /******************************************************************************
01017 * Unary, postfix and primary expressions
01018 ******************************************************************************/
01019 
01020 void
01021 cpp_printer::pp_unary (const generic& g) {
01022   if (is_func (g, CPP_PREINC, 1)) {
01023     out << "++";
01024     pp_unary (g[1]);
01025   }
01026   else if (is_func (g, CPP_PREDEC, 1)) {
01027     out << "--";
01028     pp_unary (g[1]);
01029   }
01030   else if (is_func (g, CPP_TIMES, 1) || is_func (g, CPP_UNPOINTER, 1)) {
01031     out << "*";
01032     pp_unary (g[1]);
01033   }
01034   else if (is_func (g, CPP_UNALIAS, 1)) {
01035     out << "&";
01036     pp_unary (g[1]);
01037   }
01038   else if (is_func (g, CPP_PLUS, 1)) {
01039     out << "+";
01040     pp_unary (g[1]);
01041   }
01042   else if (is_func (g, CPP_MINUS, 1)) {
01043     out << "-";
01044     pp_unary (g[1]);
01045   }
01046   else if (is_func (g, CPP_NOT, 1)) {
01047     out << "!";
01048     pp_unary (g[1]);
01049   }
01050   else if (is_func (g, CPP_COMPLEMENT, 1)) {
01051     out << "~";
01052     pp_unary (g[1]);
01053   }
01054   else if (is_func (g, CPP_DELETE, 1)) {
01055     out << "delete ";
01056     pp_expr (g[1]);
01057   }
01058   else if (is_func (g, CPP_NEW)) {
01059     out << "new ";
01060     pp_type (g[1]);
01061     out << " (";
01062     pp_exprs (cdr (cdr (g)));
01063     out << ")";
01064   }
01065   else if (is_func (g, CPP_CAST)) {
01066     out << "((";
01067     pp_type (g[2]);
01068     out << ") ";
01069     pp_expr (g[1]);
01070     out << ")";
01071   }
01072   else pp_postfix (g);
01073 }
01074 
01075 /******************************************************************************
01076 * Postfix expressions
01077 ******************************************************************************/
01078 
01079 static bool
01080 is_applicable (const generic& g) {
01081   if (is<literal> (g)) {
01082     string s= *as<literal> (g);
01083     if (N(s) == 0) return false;
01084     nat i;
01085     for (i=0; i<N(s); i++)
01086       if (((s[i]<'0') || (s[i]>'9')) &&
01087           ((s[i]<'a') || (s[i]>'z')) &&
01088           ((s[i]<'A') || (s[i]>'Z')) &&
01089           ((s[i]<'_') || (s[i]>'_')))
01090         return false;
01091     return
01092       s != CPP_IF && s != CPP_AND && s != CPP_OR && s != CPP_XOR &&
01093       s != CPP_UNALIAS && s != CPP_UNPOINTER;
01094   }
01095   else if (is_func (g, CPP_SPECIALIZE) && N(g)>=2 && is_applicable (g[1]))
01096     return true;
01097   else if (is_func (g, CPP_TYPE_CONSTRUCTOR, 1))
01098     return true;
01099   else return false;
01100 }
01101 
01102 void
01103 cpp_printer::pp_postfix (const generic& g) {
01104   if (is_func (g, CPP_SCOPE, 2)) {
01105     pp_type (g[1]);
01106     out << "::";
01107     pp_postfix (g[2]);
01108   }
01109   else if (is_func (g, CPP_DOT, 2)) {
01110     pp_postfix (g[1]);
01111     out << ".";
01112     pp_primary (g[2]);
01113   }
01114   else if (is_func (g, CPP_ARROW, 2)) {
01115     pp_postfix (g[1]);
01116     out << "->";
01117     pp_primary (g[2]);
01118   }
01119   else if (is_func (g, CPP_POSTINC, 1)) {
01120     pp_postfix (g[1]);
01121     out << "++";
01122   }
01123   else if (is_func (g, CPP_POSTDEC, 1)) {
01124     pp_postfix (g[1]);
01125     out << "--";
01126   }
01127   else if (is_func (g, CPP_APPLY)) {
01128     pp_postfix (g[1]);
01129     out << " (";
01130     pp_exprs (cdr (cdr (g)));
01131     out << ")";
01132   }
01133   else if (is_func (g, CPP_UNFUNCTION)) {
01134     pp_postfix (g[1]);
01135     out << " (";
01136     pp_funargs (cdr (cdr (g)));
01137     out << ")";
01138   }
01139   else if (is_func (g, CPP_SPECIALIZE)) {
01140     generic fun= g[1];
01141     bool macro_flag= is_func (fun, CPP_MACRO, 1);
01142     if (macro_flag) fun= fun[1];
01143     pp_postfix (fun);
01144     if (macro_flag) out << "(";
01145     else out << "<";
01146     pp_funargs (cdr (cdr (g)));
01147     if (N(g) > 2) out << " ";
01148     if (macro_flag) out << ")";
01149     else out << ">";
01150   }
01151   else if (is_func (g, CPP_TYPE_CONSTRUCTOR, 1)) {
01152     generic tp= g[1];
01153     pp_type (tp);
01154   }
01155   else if (is_func (g, CPP_ACCESS)) {
01156     pp_postfix (g[1]);
01157     out << "[";
01158     pp_exprs (cdr (cdr (g)));
01159     out << "]";
01160   }
01161   else if (is_func (g, CPP_POWER, 2)) {
01162     out << "pow (";
01163     pp_exprs (cdr (g));
01164     out << ")";
01165   }
01166   else if (((N(g) > 0) && is_applicable (g[0])) ||
01167            ((!is_nil (sl)) && (car (sl) == g))) {
01168     pp_postfix  (car (g));
01169     out << " (";
01170     pp_exprs (cdr (g));
01171     out << ")";
01172   }
01173   else pp_primary (g);
01174 }
01175 
01176 /******************************************************************************
01177 * Primary expressions
01178 ******************************************************************************/
01179 
01180 void
01181 cpp_printer::pp_primary (const generic& g) {
01182   static table<string, string> t (opname_table ());
01183 
01184   if (is<string> (g)) { ERROR ("invalid primary symbol"); }
01185   //else if (is<string> (g) && (t->contains (as<string> (g))))
01186   //out << string ("operator ") * t [as<string> (g)];
01187   else if (g == CPP_POWER) out << "pow";
01188   else if (is<literal> (g)) {
01189     string s= *as<literal> (g);
01190     if (t->contains (s)) out << (string ("operator ") * t [s]);
01191     else out << s;
01192   }
01193   else if (N(g) == 0) out << g;
01194   else if (is_func (g, CPP_BRACKETS, 1)) {
01195     out << "(";
01196     pp_expr (g[1]);
01197     out << ")";
01198   }
01199   else {
01200     out << "(";
01201     sl= cons (g, sl);
01202     pp_expr (g);
01203     sl= cdr (sl);
01204     out << ")";
01205   }
01206 }
01207 
01208 /******************************************************************************
01209 * Interface
01210 ******************************************************************************/
01211 
01212 void
01213 cpp_printer::pp (const generic& g) {
01214   pp_begin (g);
01215 }
01216 
01217 string
01218 as_cpp (const generic& g) {
01219   cpp_printer pp;
01220   pp.pp (g);
01221   while (N (pp.out) > 0 && pp.out [N (pp.out) - 1] == '\n')
01222     inside (pp.out) -> resize (N (pp.out) - 1);
01223   return pp.out;
01224 }
01225 
01226 string
01227 flatten_as_cpp (const generic& g) {
01228   generic f= as_generic (flatten (g));
01229   return as_cpp (f);
01230 }
01231 
01232 } // namespace mmx
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines