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