00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 #include <basix/list.hpp>
00014 #include <basix/literal.hpp>
00015 #include <basix/compound.hpp>
00016 #include <basix/mmx_syntax.hpp>
00017 #include <basix/math_syntax.hpp>
00018 namespace mmx {
00019 
00020 #define DATA_BEGIN   ((char) 2)
00021 #define DATA_END     ((char) 5)
00022 
00023 bool mmx_abbreviate_coerce= true;
00024 
00025 
00026 
00027 
00028 
00029 class mmx_printer {
00030 MMX_ALLOCATORS
00031 private:
00032   list<generic> gl;
00033 
00034 private:
00035   generic pp_verb (const string& s);
00036   generic pp_spc ();
00037   generic pp_lf ();
00038   generic pp_sep (bool large);
00039 
00040   generic pp_C0 (const generic& g, bool large= false);
00041   generic pp_Conds (const generic& conds);
00042 
00043   generic pp_where (const generic& g);
00044   generic pp_E0s (const generic& g, nat start);
00045 
00046   generic pp_E1 (const generic& g);
00047   generic pp_E2 (const generic& g);
00048   generic pp_Lflux (const generic& g);
00049   generic pp_Rflux (const generic& g);
00050 
00051   generic pp_F0 (const generic& g);
00052   generic pp_Seqors (const generic& g);
00053   generic pp_Ors (const generic& g);
00054   generic pp_Xors (const generic& g);
00055   generic pp_F1 (const generic& g);
00056   generic pp_Seqands (const generic& g);
00057   generic pp_Ands (const generic& g);
00058   generic pp_F2 (const generic& g);
00059   generic pp_F3 (const generic& g);
00060 
00061   generic pp_T0 (const generic& g);
00062   generic pp_T1 (const generic& g);
00063   generic pp_T2 (const generic& g);
00064   generic pp_T3 (const generic& g);
00065   generic pp_T4 (const generic& g);
00066   generic pp_T5 (const generic& g);
00067 
00068   generic pp_R0 (const generic& g);
00069   generic pp_R1 (const generic& g);
00070   generic pp_R2 (const generic& g);
00071   generic pp_R3 (const generic& g);
00072 
00073 public:
00074   inline mmx_printer () {}
00075   inline ~mmx_printer () {}
00076 
00077   generic pp_E0 (const generic& g);
00078   friend generic print_mmx (const generic& g);
00079 };
00080 
00081 
00082 
00083 
00084 
00085 enum print_controls { LF, INDENT, VARINDENT, UNINDENT };
00086 
00087 static nat indentation_level= 0;
00088 
00089 static string&
00090 operator << (string& out, print_controls pc) {
00091   switch (pc) {
00092   case LF:
00093     out << "\n";
00094     for (nat i=0; i<indentation_level; i++) out << "  ";
00095     break;
00096   case INDENT:
00097     indentation_level++;
00098     out << "  ";
00099     break;
00100   case VARINDENT:
00101     indentation_level++;
00102     break;
00103   case UNINDENT:
00104     indentation_level--;
00105     if (N(out) >= 2 && out[N(out)-2] == ' ' && out[N(out)-1] == ' ')
00106       inside (out) -> resize (N(out) - 2);
00107     break;
00108   }
00109   return out;
00110 }
00111 
00112 
00113 
00114 
00115 
00116 inline generic concat (const vector<generic>& v) {
00117   return gen ("$concat", v); }
00118 inline generic concat () {
00119   return gen ("$concat"); }
00120 inline generic concat (const generic& g1, const generic& g2) {
00121   return gen ("$concat", g1, g2); }
00122 inline generic concat (const generic& g1, const generic& g2,
00123                        const generic& g3) {
00124   return gen ("$concat", g1, g2, g3); }
00125 inline generic concat (const generic& g1, const generic& g2,
00126                        const generic& g3, const generic& g4) {
00127   return gen ("$concat", g1, g2, g3, g4); }
00128   
00129 inline generic infix (const generic& g, const generic& op, const generic& h) {
00130   return gen ("$infix", g, op, h); }
00131 inline generic bigop (const generic& op, const vector<generic>& v) {
00132   return gen ("$bigop", cons (op, v)); }
00133 inline generic bracket (const generic& l, const generic& g, const generic& r) {
00134   return gen ("$bracket", l, g, r); }
00135 inline generic postfix (const generic& g, const generic& op) {
00136   return gen ("$postfix", g, op); }
00137 inline generic prefix (const generic& op, const generic& g) {
00138   return gen ("$prefix", op, g); }
00139 inline generic operate (const generic& g, const generic& h) {
00140   return gen ("$operate", g, h); }
00141 inline generic keyword (const generic& g) {
00142   return gen ("$keyword", g); }
00143 inline generic keyword (const generic& op, const generic& g) {
00144   return gen ("$keyword", op, g); }
00145 inline generic hlist (const vector<generic>& v) {
00146   return gen ("$hlist", v); }
00147 inline generic vlist (const vector<generic>& v) {
00148   return gen ("$vlist", v); }
00149 inline generic indented (const vector<generic>& v) {
00150   return gen ("$indent", v); }
00151 
00152 static inline void
00153 init (table<generic,generic>& t, const generic& key, const generic& val) {
00154   t[key]= val;
00155 }
00156 
00157 static table<generic,generic>
00158 mmx_symbol_table () {
00159   table<generic,generic> t;
00160   init (t, "mathcatalan", "K");
00161   init (t, "partial", "d");
00162   init (t, "derivative", "D");
00163   init (t, "matheuler", "gamma");
00164   init (t, "mathd", "d");
00165   init (t, "mathe", "e");
00166   init (t, "mathi", "i");
00167   init (t, "mathpi", "pi");
00168   return t;
00169 }
00170 
00171 static void
00172 serialize (string& s, const generic& g) {
00173   if (is<literal> (g)) {
00174     static table<generic,generic> t= mmx_symbol_table ();
00175     if (contains (t, g)) s << literal_to_string (t[g]);
00176     else if (g == "$spc") s << " ";
00177     else if (g == "$lf") s << LF;
00178     else if (g == "$cr");
00179     else s << literal_to_string (g);
00180   }
00181   else if (is_func (g, "$concat") ||
00182            is_func (g, "$bracket") ||
00183            is_func (g, "$prefix") ||
00184            is_func (g, "$postfix"))
00185     for (nat i=1; i<N(g); i++)
00186       serialize (s, g[i]);
00187   else if (is_func (g, "$infix", 3)) {
00188     serialize (s, g[1]);
00189     if (g[2] != "^" && g[2] != "^^") s << " ";
00190     serialize (s, g[2]);
00191     if (g[2] != "^" && g[2] != "^^") s << " ";
00192     serialize (s, g[3]); 
00193   }
00194   else if (is_func (g, "$bigop") && N(g) >= 3) {
00195     if (g[1] == GEN_PLUS && is_func (g[2], GEN_MINUS, 1)) {
00196       s << "-";
00197       serialize (s, g[2][1]);
00198     }
00199     else serialize (s, g[2]);
00200     for (nat i=3; i<N(g); i++) {
00201       if (g[1] == GEN_PLUS && is_func (g[i], GEN_MINUS, 1)) {
00202         s << " " << "-" << " ";
00203         serialize (s, g[i][1]);
00204       }
00205       else {
00206         s << " ";
00207         serialize (s, g[1]);
00208         s << " ";
00209         serialize (s, g[i]);
00210       }
00211     }
00212   }
00213   else if (is_func (g, "$keyword", 1))
00214     serialize (s, g[1]);
00215   else if (is_func (g, "$operate", 2) ||
00216            is_func (g, "$keyword", 2)) {
00217     serialize (s, g[1]);
00218     s << " ";
00219     serialize (s, g[2]);
00220   }
00221   else if (is_func (g, "$hlist") ||
00222            is_func (g, "$vlist")) {
00223     if (N(g) == 1) return;
00224     serialize (s, g[1]);
00225     for (nat i=2; i<N(g); i++) {
00226       if (g[0] == "$hlist") s << ", ";
00227       else s << "; ";
00228       serialize (s, g[i]);
00229     }
00230   }
00231   else if (is_func (g, "$indent")) {
00232     s << INDENT;
00233     for (nat i=1; i<N(g); i++)
00234       serialize (s, g[i]);
00235     s << UNINDENT;
00236   }
00237   else if (is_func (g, "$varindent")) {
00238     serialize (s, g[1]);
00239     s << VARINDENT;
00240     for (nat i=2; i<N(g); i++)
00241       serialize (s, g[i]);
00242     s << UNINDENT;
00243   }
00244   else if (is_func (g, "$text", 1))
00245     serialize (s, g[1]);
00246   else if (is_func (g, "$math", 1))
00247     serialize (s, g[1]);
00248   else if (is_func (g, "$dynamic", 2)) {
00249     s << "< ";
00250     serialize (s, g[1]);
00251     s << " | ";
00252     serialize (s, g[2]);
00253     s << " >";
00254   }
00255   else if (is<compound> (g) && is<literal> (g[0]) &&
00256            starts (as_string (as<literal> (g[0])), "tm$")) {
00257     generic h= texmacs_expand (g);
00258     serialize (s, h);
00259   }
00260   else {
00261     serialize (s, g[0]);
00262     s << " (";
00263     for (nat i=1; i<N(g); i++) {
00264       if (i != 1) s << ", ";
00265       serialize (s, g[i]);
00266     }
00267     s << ")";
00268   }
00269 }
00270 
00271 static string
00272 serialize (const generic& g) {
00273   string s;
00274   serialize (s, g);
00275   return s;
00276 }
00277 
00278 
00279 
00280 
00281 
00282 generic
00283 mmx_printer::pp_verb (const string& s) {
00284   return generic (s);
00285 }
00286 
00287 generic
00288 mmx_printer::pp_spc () {
00289   return generic ("$spc");
00290 }
00291 
00292 generic
00293 mmx_printer::pp_lf () {
00294   return generic ("$lf");
00295 }
00296 
00297 generic
00298 mmx_printer::pp_sep (bool large) {
00299   if (large) return concat (pp_verb (";"), pp_lf ());
00300   else return concat ();
00301 }
00302 
00303 
00304 
00305 
00306 
00307 static bool
00308 is_C0 (const generic& g) {
00309   if (is_func (g, GEN_BEGIN) ||
00310       is_func (g, GEN_IF) ||
00311       is_func (g, GEN_LOOP) ||
00312       is_func (g, GEN_BREAK) ||
00313       is_func (g, GEN_CONTINUE) ||
00314       is_func (g, GEN_TRY) ||
00315       is_func (g, GEN_LAMBDA) ||
00316       is_func (g, GEN_MACRO) ||
00317       is_func (g, GEN_RETURN) ||
00318       is_func (g, GEN_CLASS) ||
00319       is_func (g, GEN_MODULE) ||
00320       is_func (g, GEN_CATEGORY))
00321     return true;
00322   if (N(g) == 2 && is_C0 (g[1]))
00323     return
00324       is_func (g, GEN_AUTOFOLD) ||
00325       is_func (g, GEN_INLINE) ||
00326       is_func (g, GEN_INTERN) ||
00327       is_func (g, GEN_METHOD) ||
00328       is_func (g, GEN_EXTERN) ||
00329       is_func (g, GEN_MUTABLE) ||
00330       is_func (g, GEN_CONSTANT) ||
00331       is_func (g, GEN_OUTLINE) ||
00332       is_func (g, GEN_PUBLIC) ||
00333       is_func (g, GEN_PRIVATE);
00334   if (N(g) == 3 && is_C0 (g[2]))
00335     return
00336       is_func (g, GEN_FORALL) ||
00337       is_func (g, GEN_EXISTS) ||
00338       is_func (g, GEN_ASSUME) ||
00339       is_func (g, GEN_PENALTY) ||
00340       is_func (g, GEN_DEFINE) ||
00341       is_func (g, GEN_ASSIGN) ||
00342       is_func (g, GEN_DEFINE_MACRO) ||
00343       is_func (g, GEN_ASSIGN_MACRO) ||
00344       is_func (g, GEN_PLUS_ASSIGN) ||
00345       is_func (g, GEN_MINUS_ASSIGN) ||
00346       is_func (g, GEN_TIMES_ASSIGN) ||
00347       is_func (g, GEN_OVER_ASSIGN) ||
00348       is_func (g, GEN_LESSLESSEQ) ||
00349       is_func (g, GEN_GTRGTREQ);
00350   if (N(g) == 4 && is_C0 (g[3]))
00351     return
00352       is_func (g, GEN_FOREIGN);
00353   return false;
00354 }
00355 
00356 static bool
00357 is_applicable (const generic& g) {
00358   if (is<literal> (g)) {
00359     const string s= literal_to_string (g);
00360     if (N(s)==0) return false;
00361     for (nat i=0; i<N(s); i++)
00362       if (s[i] == '.') {
00363         if (i != 0 || N(s) == 1) return false; }
00364       else if (((s[i]<'0') || (s[i]>'9')) &&
00365                ((s[i]<'a') || (s[i]>'z')) &&
00366                ((s[i]<'A') || (s[i]>'Z')) &&
00367                ((s[i]!='_') && (s[i]!='?') && (s[i]!='$')))
00368         return false;
00369       else if (s[i] == '$') return true;
00370   }
00371   return
00372     g != GEN_SEQAND && g != GEN_SEQOR && g != GEN_XOR &&
00373     g != GEN_LAMBDA && g != GEN_MACRO &&
00374     g != GEN_COERCE && g != GEN_COERCE_TYPE;
00375 }
00376 
00377 
00378 
00379 
00380 
00381 static generic
00382 un_try_catch (const generic& g) {
00383   vector<generic> v;
00384   if (is_func (g[1], GEN_BEGIN)) v << cdr (compound_to_vector (g[1]));
00385   else v << g[1];
00386   for (nat i=2; i<N(g); i++) v << g[i];
00387   return gen (g[0], gen (GEN_BEGIN, v));
00388 }
00389 
00390 generic
00391 mmx_printer::pp_C0 (const generic& g, bool large) {
00392   if (is_func (g, GEN_BEGIN)) {
00393     vector<generic> v;
00394     if (N(g) == 1)
00395       v << pp_verb ("{") << pp_verb ("}");
00396     else {
00397       vector<generic> w;
00398       v << pp_verb ("{") << pp_lf ();
00399       for (nat i=1; i<N(g); i++)
00400         w << pp_C0 (g[i], true);
00401       v << indented (w);
00402       v << pp_verb ("}");
00403     }
00404     if (large) v << pp_lf ();
00405     return concat (v);
00406   }
00407   else if (is_func (g, GEN_IF, 2)) {
00408     generic t= g[2];
00409     if (is_func (g[2], GEN_IF)) t= gen (GEN_BEGIN, g[2]);
00410     return concat (keyword ("if", pp_E0 (g[1])),
00411                    pp_spc (),
00412                    keyword ("then", pp_C0 (t, large)));
00413   }
00414   else if (is_func (g, GEN_IF, 3)) {
00415     generic t= g[2];
00416     if (is_func (g[2], GEN_IF)) t= gen (GEN_BEGIN, g[2]);
00417     bool large2= is_C0 (t);
00418     return concat (vec (keyword ("if", pp_E0 (g[1])),
00419                         pp_spc (),
00420                         keyword ("then", pp_C0 (t, large2)),
00421                         large2? concat (): pp_spc (),
00422                         keyword ("else", pp_C0 (g[3], large))));
00423   }
00424   else if (is_func (g, GEN_MATCH)) {
00425     generic b= cons (GEN_BEGIN, cdr (cdr (g)));
00426     return concat (keyword ("match", pp_E0 (g[1])),
00427                    pp_spc (),
00428                    keyword ("with", pp_C0 (b, large)));    
00429   }
00430   else if (is_func (g, GEN_CASE) && N(g) >= 3) {
00431     vector<generic> v;
00432     for (nat i=2; i<N(g); i++)
00433       v << pp_E1 (g[i]);
00434     return concat (keyword ("case", hlist (v)),
00435                    pp_spc (),
00436                    keyword ("do", pp_C0 (g[1], large)));
00437   }
00438   else if (is_func (g, GEN_LOOP))
00439     return concat (pp_Conds (g), keyword ("loop", pp_C0 (g[N(g)-1], large)));
00440   else if (is_func (g, GEN_TRY))
00441     return keyword ("try", pp_C0 (un_try_catch (g) [1], large));
00442   else if (is_func (g, GEN_DEFINE, 2) && is_func (g[1], GEN_CATCH))
00443     return concat (pp_F0 (g[1]), pp_spc (), pp_C0 (g[2], large));
00444   else if (is_func (g, GEN_RETURN, 1))
00445     return keyword ("return", pp_C0 (g[1], large));
00446   else if (g == GEN_RETURN)
00447     return concat (keyword ("return"), pp_sep (large));
00448   else if (g == GEN_BREAK)
00449     return concat (keyword ("break"), pp_sep (large));
00450   else if (g == GEN_CONTINUE)
00451     return concat (keyword ("continue"), pp_sep (large));
00452   else if (is_func (g, GEN_AUTOFOLD, 1) ||
00453            is_func (g, GEN_INLINE, 1) ||
00454            is_func (g, GEN_INTERN, 1) ||
00455            is_func (g, GEN_METHOD, 1) ||
00456            is_func (g, GEN_EXTERN, 1) ||
00457            is_func (g, GEN_CONSTANT, 1) ||
00458            is_func (g, GEN_MUTABLE, 1) ||
00459            is_func (g, GEN_OUTLINE, 1) ||
00460            is_func (g, GEN_PUBLIC, 1) ||
00461            is_func (g, GEN_PRIVATE, 1))
00462     return keyword (g[0], pp_C0 (g[1], large));
00463   else if (is_func (g, GEN_FOREIGN, 3))
00464     return keyword (g[0], keyword (g[1], keyword (g[2], pp_C0 (g[3], large))));
00465   else if (is_func (g, GEN_FORALL, 2) ||
00466            is_func (g, GEN_EXISTS, 2) ||
00467            is_func (g, GEN_ASSUME, 2) ||
00468            is_func (g, GEN_PENALTY, 2))
00469     return operate (keyword (g[0], bracket ("(", pp_E0 (g[1]), ")")),
00470                     pp_C0 (g[2], large));
00471   else if (is_func (g, GEN_CLASS, 1) ||
00472            is_func (g, GEN_MODULE, 1) ||
00473            is_func (g, GEN_CATEGORY, 1))
00474     return concat (keyword (g[0], pp_F0 (g[1])), pp_sep (large));
00475   else if (is_func (g, GEN_CLASS, 2) ||
00476            is_func (g, GEN_MODULE, 2) ||
00477            is_func (g, GEN_CATEGORY, 2))
00478     return keyword (g[0], infix (pp_F0 (g[1]), "==", pp_C0 (g[2], large)));
00479   else if (is_func (g, GEN_DEFINE, 2) ||
00480            is_func (g, GEN_ASSIGN, 2) ||
00481            is_func (g, GEN_DEFINE_MACRO, 2) ||
00482            is_func (g, GEN_ASSIGN_MACRO, 2) ||
00483            is_func (g, GEN_PLUS_ASSIGN, 2) ||
00484            is_func (g, GEN_MINUS_ASSIGN, 2) ||
00485            is_func (g, GEN_TIMES_ASSIGN, 2) ||
00486            is_func (g, GEN_OVER_ASSIGN, 2) ||
00487            is_func (g, GEN_LESSLESSEQ, 2) ||
00488            is_func (g, GEN_GTRGTREQ, 2))
00489     return infix (pp_F0 (g[1]), g[0], pp_C0 (g[2], large));
00490   else if (is_func (g, GEN_PREFER, 2))
00491     return keyword ("prefer", infix (pp_F0 (g[1]), "to",
00492                                      pp_C0 (g[2], large)));
00493   else if (is_func (g, GEN_LAMBDA) || is_func (g, GEN_MACRO)) {
00494     if (new_lambda_style) {
00495       vector<generic> v= compound_to_vector (g);
00496       generic t= gen (GEN_TUPLE, range (v, 1, N(v) - 1));
00497       generic b= g[N(g)-1];
00498       if (is_func (b, GEN_TYPE, 2)) { t= gen (GEN_TYPE, t, b[2]); b= b[1]; }
00499       return concat (keyword (g[0], pp_E0 (t)),
00500                      pp_spc (),
00501                      keyword ("do", pp_C0 (b, large)));
00502     }
00503     else {
00504       generic a= pp_E0 (g[1]);
00505       if (N(g) == 4) a= infix (a, ":", pp_E0 (g[3]));
00506       return concat (keyword (g[0], a),
00507                      pp_spc (),
00508                      keyword ("do", pp_C0 (g[2], large)));
00509     }
00510   }
00511   else return concat (pp_E1 (g), pp_sep (large));
00512 }
00513 
00514 
00515 
00516 
00517 
00518 generic
00519 mmx_printer::pp_Conds (const generic& conds) {
00520   vector<generic> v;
00521   for (nat i=1; i<N(conds)-1; i++) {
00522     generic g= conds[i];
00523     if (is_func (g, GEN_FOR, 1) ||
00524         is_func (g, GEN_WHILE, 1) ||
00525         is_func (g, GEN_UNTIL, 1) ||
00526         is_func (g, GEN_STEP, 1))
00527       v << keyword (g[0], pp_E0 (g[1])) << pp_spc ();
00528   }
00529   return concat (v);
00530 }
00531 
00532 
00533 
00534 
00535 
00536 generic
00537 mmx_printer::pp_where (const generic& g) {
00538   return infix (pp_E0 (g[1]), g[0], pp_E0s (g, 2));
00539 }
00540 
00541 generic
00542 mmx_printer::pp_E0s (const generic& g, nat start) {
00543   nat n= N (g);
00544   if (start >= n) return concat ();
00545   else if (is_func (g[start], GEN_WHERE) && start==n-1)
00546     return pp_where (g[start]);
00547   else if (is_func (g[start], GEN_VWHERE) && start==n-1)
00548     return pp_where (g[start]);
00549   else {
00550     bool vertical= false;
00551     for (nat i=start; i<n; i++)
00552       vertical= vertical || is_func (g[i], GEN_ROW);
00553     vector<generic> v;
00554     for (nat i=start; i<n; i++)
00555       v << pp_E0 (g[i]);
00556     if (vertical) return vlist (v);
00557     else return hlist (v);
00558   }
00559 }
00560 
00561 
00562 
00563 
00564 
00565 generic
00566 mmx_printer::pp_E0 (const generic& g) {
00567   if (is_func (g, GEN_FORALL, 2) ||
00568       is_func (g, GEN_EXISTS, 2) ||
00569       is_func (g, GEN_ASSUME, 2) ||
00570       is_func (g, GEN_PENALTY, 2))
00571     return operate (keyword (g[0], bracket ("(", pp_E0 (g[1]), ")")),
00572                     pp_E0 (g[2]));
00573   else if (is_func (g, GEN_DEFINE, 2) ||
00574            is_func (g, GEN_ASSIGN, 2) ||
00575            is_func (g, GEN_DEFINE_MACRO, 2) ||
00576            is_func (g, GEN_ASSIGN_MACRO, 2) ||
00577            is_func (g, GEN_PLUS_ASSIGN, 2) ||
00578            is_func (g, GEN_MINUS_ASSIGN, 2) ||
00579            is_func (g, GEN_TIMES_ASSIGN, 2) ||
00580            is_func (g, GEN_OVER_ASSIGN, 2) ||
00581            is_func (g, GEN_LESSLESSEQ, 2) ||
00582            is_func (g, GEN_GTRGTREQ, 2))
00583     return infix (pp_F0 (g[1]), g[0], pp_E0 (g[2]));
00584   else return pp_E1 (g);
00585 }
00586 
00587 generic
00588 mmx_printer::pp_E1 (const generic& g) {
00589   if (is_func (g, GEN_LAMBDA) || is_func (g, GEN_MACRO)) {
00590     if (new_lambda_style) {
00591       vector<generic> v= compound_to_vector (g);
00592       generic t= gen (GEN_TUPLE, range (v, 1, N(v) - 1));
00593       generic b= g[N(g)-1];
00594       if (is_func (b, GEN_TYPE, 2)) { t= gen (GEN_TYPE, t, b[2]); b= b[1]; }
00595       generic d= (is_C0 (b)? pp_C0 (b): pp_E0 (b));
00596       return concat (keyword (g[0], pp_E0 (t)), pp_spc (), keyword ("do", d));
00597     }
00598     else {
00599       generic a= pp_E0 (g[1]);
00600       if (N(g) == 4) a= infix (a, ":", pp_E0 (g[3]));
00601       generic b= (is_C0 (g[2])? pp_C0 (g[2]): pp_E0 (g[2]));
00602       return concat (keyword (g[0], a), pp_spc (), keyword ("do", b));
00603     }
00604   }
00605   else if (is_func (g, GEN_MAPSTO, 2))
00606     return infix (pp_E2 (g[1]), g[0], pp_E2 (g[2]));
00607   else return pp_E2 (g);
00608 }
00609 
00610 generic
00611 mmx_printer::pp_E2 (const generic& g) {
00612   if (is_func (g, GEN_LESSLESS, 2))
00613     return infix (pp_Lflux (g[1]), g[0], pp_F0 (g[2]));
00614   else if (is_func (g, GEN_GTRGTR, 2))
00615     return infix (pp_F0 (g[1]), g[0], pp_Rflux (g[2]));
00616   else return pp_F0 (g);
00617 }
00618 
00619 generic
00620 mmx_printer::pp_Lflux (const generic& g) {
00621   if (is_func (g, GEN_LESSLESS, 2))
00622     return infix (pp_Lflux (g[1]), g[0], pp_F0 (g[2]));
00623   else return pp_F0 (g);
00624 }
00625 
00626 generic
00627 mmx_printer::pp_Rflux (const generic& g) {
00628   if (is_func (g, GEN_GTRGTR, 2))
00629     return infix (pp_F0 (g[1]), g[0], pp_Rflux (g[2]));
00630   else return pp_F0 (g);
00631 }
00632 
00633 
00634 
00635 
00636 
00637 generic
00638 mmx_printer::pp_F0 (const generic& g) {
00639   if (is_func (g, GEN_IMPLIES, 2) ||
00640       is_func (g, GEN_EQUIV, 2))
00641     return infix (pp_F1 (g[1]), g[0], pp_F1 (g[2]));
00642   else return pp_F1 (g);
00643 }
00644 
00645 generic
00646 mmx_printer::pp_F1 (const generic& g) {
00647   if (is_func (g, GEN_SEQOR, 2))
00648     return infix (pp_Seqors (g[1]), g[0], pp_Seqors (g[2]));
00649   else if (is_func (g, GEN_OR, 2))
00650     return infix (pp_Ors (g[1]), g[0], pp_Ors (g[2]));
00651   else if (is_func (g, GEN_XOR, 2))
00652     return infix (pp_Xors (g[1]), g[0], pp_Xors (g[2]));
00653   else return pp_F2 (g);
00654 }
00655 
00656 generic
00657 mmx_printer::pp_Seqors (const generic& g) {
00658   if (is_func (g, GEN_SEQOR, 2))
00659     return infix (pp_Seqors (g[1]), g[0], pp_Seqors (g[2]));
00660   else return pp_F2 (g);
00661 }
00662 
00663 generic
00664 mmx_printer::pp_Ors (const generic& g) {
00665   if (is_func (g, GEN_OR, 2))
00666     return infix (pp_Ors (g[1]), g[0], pp_Ors (g[2]));
00667   else return pp_F2 (g);
00668 }
00669 
00670 generic
00671 mmx_printer::pp_Xors (const generic& g) {
00672   if (is_func (g, GEN_XOR, 2))
00673     return infix (pp_Xors (g[1]), g[0], pp_Xors (g[2]));
00674   else return pp_F2 (g);
00675 }
00676 
00677 generic
00678 mmx_printer::pp_F2 (const generic& g) {
00679   if (is_func (g, GEN_AND, 2))
00680     return infix (pp_Ands (g[1]), g[0], pp_Ands (g[2]));
00681   else if (is_func (g, GEN_SEQAND, 2))
00682     return infix (pp_Seqands (g[1]), g[0], pp_Seqands (g[2]));
00683   else return pp_F3 (g);
00684 }
00685 
00686 generic
00687 mmx_printer::pp_Seqands (const generic& g) {
00688   if (is_func (g, GEN_SEQAND, 2))
00689     return infix (pp_Seqands (g[1]), g[0], pp_Seqands (g[2]));
00690   else return pp_F3 (g);
00691 }
00692 
00693 generic
00694 mmx_printer::pp_Ands (const generic& g) {
00695   if (is_func (g, GEN_AND, 2) || is_func (g, GEN_SEQAND, 2))
00696     return infix (pp_Ands (g[1]), g[0], pp_Ands (g[2]));
00697   else return pp_F3 (g);
00698 }
00699 
00700 generic
00701 mmx_printer::pp_F3 (const generic& g) {
00702   if (is_func (g, GEN_EQUAL, 2) ||
00703       is_func (g, GEN_UNEQUAL, 2) ||
00704       is_func (g, GEN_LESS, 2) ||
00705       is_func (g, GEN_LESSEQ, 2) ||
00706       is_func (g, GEN_GTR, 2) ||
00707       is_func (g, GEN_GTREQ, 2))
00708     return infix (pp_T0 (g[1]), g[0], pp_T0 (g[2]));
00709   else if (is_func (g, GEN_TYPE, 2))
00710     return infix (pp_T0 (g[1]), g[0], pp_T0 (g[2]));
00711   else if (is_func (g, GEN_IN, 2) && is_func (g[1], GEN_TYPE, 2))
00712     return infix (pp_F3 (g[1]), g[0], pp_T0 (g[2]));
00713   else if (is_func (g, GEN_IN, 2))
00714     return infix (pp_T0 (g[1]), g[0], pp_T0 (g[2]));
00715   else return pp_T0 (g);
00716 }
00717 
00718 
00719 
00720 
00721 
00722 generic
00723 mmx_printer::pp_T0 (const generic& g) {
00724   if (is_func (g, GEN_VARTYPE, 2) ||
00725       is_func (g, GEN_TRANSTYPE, 2) ||
00726       is_func (g, GEN_VARTRANSTYPE, 2))
00727     return infix (pp_T0 (g[1]), g[0], pp_T1 (g[2]));
00728   else if ((is_func (g, GEN_COERCE, 2) ||
00729             (is_func (g, GEN_COERCE_TYPE) && N(g) > 2)) &&
00730            mmx_abbreviate_coerce) {
00731     
00732     if (is_func (g, GEN_COERCE_TYPE) && g[2] == "Class")
00733       return postfix (pp_T0 (g[1]), " [C]");
00734     
00735     
00736     
00737 
00738     generic op= GEN_TRANSTYPE;
00739     if (is_func (g, GEN_COERCE_TYPE)) op= "::>";
00740     if (is_func (g, GEN_COERCE_TYPE) && N(g) >= 4) {
00741       if (is_func (g[3], "ABBREVIATE", 1) && is<literal> (g[3][1])) {
00742         string s= ":" * literal_to_string (g[3][1]) * ">";
00743         op= s;
00744       }
00745       else if (g[3] == generic ("HYPOTHESIS")) op= ":!>";
00746       else if (g[3] == generic ("ALTER")) op= "::>";
00747       else if (N(g) >= 5 && is_func (g[4], "#")) {
00748         ASSERT (is<literal> (g[4][2]), "literal expected");
00749         op= ":+" * literal_to_string (g[4][2]) * "+>";
00750       }
00751       
00752       else op= ":+>";
00753     }
00754     return infix (pp_T0 (g[1]), op, pp_T1 (g[2]));
00755   }
00756   else return pp_T1 (g);
00757 }
00758 
00759 generic
00760 mmx_printer::pp_T1 (const generic& g) {
00761   if (is_func (g, GEN_INTO, 2) ||
00762       is_func (g, GEN_MAPSTO, 2) ||
00763       is_func (g, GEN_CONVERTS, 2))
00764     return infix (pp_T2 (g[1]), g[0], pp_T2 (g[2]));
00765   else return pp_T2 (g);
00766 }
00767 
00768 generic
00769 mmx_printer::pp_T2 (const generic& g) {
00770   if (is_func (g, GEN_RANGE, 2))
00771     return infix (pp_T3 (g[1]), g[0], pp_T3 (g[2]));
00772   else if (is_func (g, GEN_TO, 2))
00773     return infix (pp_T3 (g[1]), g[0], pp_T3 (g[2]));
00774   else if (is_func (g, GEN_DOWNTO, 2))
00775     return infix (pp_T3 (g[1]), g[0], pp_T3 (g[2]));
00776   else return pp_T3 (g);
00777 }
00778 
00779 static void
00780 collect (vector<generic>& v, const generic& g, nat depth) {
00781   if (depth >= 16384) v << g;
00782   else if (is_func (g, GEN_PLUS, 2)) {
00783     collect (v, g[1], depth+1);
00784     collect (v, g[2], depth+1);
00785   }
00786   else if (is_func (g, GEN_MINUS, 2)) {
00787     collect (v, g[1], depth+1);
00788     v << gen (GEN_MINUS, g[2]);
00789   }
00790   else v << g;
00791 }
00792 
00793 static vector<generic>
00794 collect (const generic& g) {
00795   vector<generic> v;
00796   collect (v, g, 0);
00797   vector<generic> w;
00798   for (nat i=0; i<N(v); i++)
00799     if (is_func (v[i], GEN_PLUS, 2) || is_func (v[i], GEN_MINUS, 2))
00800       w << collect (v[i]);
00801     else w << v[i];
00802   return w;
00803 }
00804 
00805 generic
00806 mmx_printer::pp_T3 (const generic& g) {
00807   if (is_func (g, GEN_PLUS, 2) || is_func (g, GEN_MINUS, 2)) {
00808     vector<generic> v= collect (g);
00809     for (nat i=0; i<N(v); i++)
00810       if (is_func (v[i], GEN_MINUS, 1))
00811         v[i]= gen (GEN_MINUS, pp_T4 (v[i][1]));
00812       else v[i]= pp_T3 (v[i]);
00813     return bigop (GEN_PLUS, v);
00814   }
00815   else return pp_T4 (g);
00816 }
00817 
00818 generic
00819 mmx_printer::pp_T4 (const generic& g) {
00820   if (is_func (g, GEN_TIMES, 2) ||
00821       is_func (g, GEN_COMPOSE, 2) ||
00822       is_func (g, GEN_APPEND, 2))
00823     return infix (pp_T4 (g[1]), g[0], pp_T4 (g[2]));
00824   else if (is_func (g, GEN_OVER, 2) ||
00825            is_func (g, GEN_SIZE, 2) ||
00826            is_func (g, "%", 2) ||
00827            is_func (g, "&", 2))
00828     return infix (pp_T4 (g[1]), g[0], pp_T5 (g[2]));
00829   else if (is_func (g, GEN_DIV, 2))
00830     return infix (pp_T4 (g[1]), "div", pp_T5 (g[2]));
00831   else if (is_func (g, GEN_QUO, 2))
00832     return infix (pp_T4 (g[1]), "quo", pp_T5 (g[2]));
00833   else if (is_func (g, GEN_REM, 2))
00834     return infix (pp_T4 (g[1]), "rem", pp_T5 (g[2]));
00835   else if (is_func (g, GEN_MOD, 2))
00836     return infix (pp_T4 (g[1]), "mod", pp_T5 (g[2]));
00837   else return pp_T5 (g);
00838 }
00839 
00840 generic
00841 mmx_printer::pp_T5 (const generic& g) {
00842   if (is_func (g, GEN_MINUS, 1))
00843     return prefix (g[0], pp_R0 (g[1]));
00844   else if (is_func (g, GEN_EXPLODE, 1) ||
00845            is_func (g, GEN_SIZE, 1) ||
00846            is_func (g, "%", 1) ||
00847            is_func (g, "&", 1) ||
00848            is_func (g, GEN_NOT, 1))
00849     return prefix (g[0], pp_T5 (g[1]));
00850   else if (is<literal> (g) && g != GEN_MINUS &&
00851            starts (literal_to_string (g), "-"))
00852     return pp_verb (literal_to_string (g));
00853   else return pp_R0 (g);
00854 }
00855 
00856 
00857 
00858 
00859 
00860 generic
00861 mmx_printer::pp_R0 (const generic& g) {
00862   return pp_R1 (g);
00863 }
00864 
00865 generic
00866 mmx_printer::pp_R1 (const generic& g) {
00867   if (is_func (g, GEN_POWER, 2) || is_func (g, GEN_FILL, 2))
00868     return infix (pp_R2 (g[1]), g[0], pp_R2 (g[2]));
00869   else return pp_R2 (g);
00870 }
00871 
00872 generic
00873 mmx_printer::pp_R2 (const generic& g) {
00874   if (is_func (g, GEN_FACTORIAL, 1))
00875     return postfix (pp_R2 (g[1]), "!");
00876   else if (is_func (g, GEN_PRIME, 1))
00877     return postfix (pp_R2 (g[1]), "'");
00878   else if (is_func (g, GEN_BACKPRIME, 1))
00879     return postfix (pp_R2 (g[1]), "`");
00880   else if (is_func (g, GEN_STAR, 1))
00881     return postfix (pp_R2 (g[1]), "*");
00882   else if (is_func (g, GEN_HAT, 1))
00883     return postfix (pp_R2 (g[1]), "^");
00884   else if (is_func (g, GEN_TILDA, 1))
00885     return postfix (pp_R2 (g[1]), "~");
00886   else if (is_func (g, GEN_QUOTE, 1) || is_func (g, GEN_BACKQUOTE, 1)) {
00887     if (is<literal> (g[1])) 
00888       return prefix (g[0], pp_verb (literal_to_string (g[1])));
00889     else if (is_func (g[1], GEN_QUOTE, 1) || is_func (g[1], GEN_BACKQUOTE, 1))
00890       return prefix (g[0], pp_E0 (g[1]));
00891     else return prefix (g[0], bracket ("(", pp_E0 (g[1]), ")"));
00892   }
00893   else if (N(g) == 2 &&
00894            is<literal> (g[0]) &&
00895            starts (literal_to_string (g[0]), "."))
00896     return concat (pp_R2 (g[1]), pp_verb (literal_to_string (g[0])));
00897   else if (is_func (g, GEN_ACCESS))
00898     return operate (pp_R2 (g[1]), bracket ("[", pp_E0s (g, 2), "]"));
00899   else if (is_func (g, GEN_LITERAL_FLOATING, 1) && is<literal> (g[1]))
00900     return pp_verb (literal_to_string (g[1]));
00901   else if (is_func (g, GEN_LITERAL_INTEGER, 1) && is<literal> (g[1]))
00902     return pp_verb (literal_to_string (g[1]));
00903   else if (is_func (g, GEN_LITERAL_STRING, 1) && is<literal> (g[1]))
00904     return pp_verb (literal_to_string (g[1]));
00905   else if ((is<compound> (g) && is_applicable (g[0])) ||
00906            (!is_nil (gl) && exact_eq (read_car (gl), g))) {
00907     if (is<literal> (g)) return pp_verb (literal_to_string (g));
00908     else if (is<literal> (g[0])) {
00909       string op= literal_to_string (g[0]);
00910       if (starts (op, "$") || starts (op, "tm$")) {
00911         vector<generic> v= vec<generic> (g[0]);
00912         for (nat i=1; i<N(g); i++) v << pp_E0 (g[i]);
00913         return vector_to_compound (v);
00914       }
00915     }
00916     if (is_func (g, GEN_PARTIAL, 1) && is<literal> (g[1]))
00917         return operate (pp_R2 (g[0]), pp_E0s (g, 1));
00918     if (N(g) == 2 && is_func (g[0], GEN_POWER, 2) &&
00919         exact_eq (g[0][1], GEN_PARTIAL) && is<literal> (g[1]))
00920       return operate (pp_R1 (g[0]), pp_E0s (g, 1));
00921     return operate (pp_R2 (g[0]), bracket ("(", pp_E0s (g, 1), ")"));
00922   }
00923   else return pp_R3 (g);
00924 }
00925 
00926 generic
00927 mmx_printer::pp_R3 (const generic& g) {
00928   if (is<literal> (g) && !starts (literal_to_string (g), "-"))
00929     return pp_verb (literal_to_string (g));
00930   else if (is_func (g, GEN_SQTUPLE))
00931     return bracket ("[", pp_E0s (g, 1), "]");
00932   else if (is_func (g, GEN_TUPLE))
00933     return bracket ("(", pp_E0s (g, 1), ")");
00934   else if (is_func (g, GEN_ROW))
00935     return pp_E0s (g, 1);
00936   else if (is_func (g, GEN_WHERE) || is_func (g, GEN_VWHERE))
00937     return bracket ("(", pp_where (g), ")");
00938   else {
00939     gl= cons (g, gl);
00940     generic r= pp_E0 (g);
00941     gl= read_cdr (gl);
00942     return bracket ("(", r, ")");
00943   }
00944 }
00945 
00946 
00947 
00948 
00949 
00950 generic
00951 print_mmx (const generic& g) {
00952   vector<generic> v;
00953   mmx_printer pp;
00954   if (is_func (g, GEN_BEGIN))
00955     for (nat i=1; i<N(g); i++)
00956       v << pp.pp_C0 (g[i], i<N(g)-1);
00957   else if (is_C0 (g)) v << pp.pp_C0 (g);
00958   else v << pp.pp_E0 (g);
00959   return concat (v);
00960 }
00961 
00962 string
00963 as_mmx (const generic& g) {
00964   return serialize (print_mmx (g));
00965 }
00966 
00967 string
00968 flatten_as_mmx (const generic& g) {
00969   generic f= as_generic (flatten (g));
00970   return as_mmx (f);
00971 }
00972 
00973 string
00974 output_as_mmx (const generic& g) {
00975   if (math_mode) {
00976     string r;
00977     r << DATA_BEGIN << "scheme:";
00978     r << flatten_as_texmacs_scheme (g);
00979     r << DATA_END;
00980     return r;
00981   }
00982   else {
00983     generic f= as_generic (flatten (g));
00984     return as_mmx (f);
00985   }
00986 }
00987 
00988 string
00989 string_as_mmx (const string& s) {
00990   
00991   return s;
00992 }
00993 
00994 }