basix_doc 0.1
/Users/mourrain/Devel/mmx/basix/src/mmx_printer.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : mmx_printer.cpp
00004 * DESCRIPTION: Printing as mathemagix expressions
00005 * COPYRIGHT  : (C) 2000  Joris van der Hoeven
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/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 * The mmx_printer class
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 * Printing to strings
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 * Concatenation
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 * Helper routines
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 * Predicates
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_INTERN) ||
00325       is_func (g, GEN_METHOD) ||
00326       is_func (g, GEN_EXTERN) ||
00327       is_func (g, GEN_MUTABLE) ||
00328       is_func (g, GEN_CONSTANT) ||
00329       is_func (g, GEN_PUBLIC) ||
00330       is_func (g, GEN_PRIVATE);
00331   if (N(g) == 3 && is_C0 (g[2]))
00332     return
00333       is_func (g, GEN_FORALL) ||
00334       is_func (g, GEN_EXISTS) ||
00335       is_func (g, GEN_ASSUME) ||
00336       is_func (g, GEN_PENALTY) ||
00337       is_func (g, GEN_DEFINE) ||
00338       is_func (g, GEN_ASSIGN) ||
00339       is_func (g, GEN_DEFINE_MACRO) ||
00340       is_func (g, GEN_ASSIGN_MACRO) ||
00341       is_func (g, GEN_PLUS_ASSIGN) ||
00342       is_func (g, GEN_MINUS_ASSIGN) ||
00343       is_func (g, GEN_TIMES_ASSIGN) ||
00344       is_func (g, GEN_OVER_ASSIGN) ||
00345       is_func (g, GEN_LESSLESSEQ) ||
00346       is_func (g, GEN_GTRGTREQ);
00347   if (N(g) == 4 && is_C0 (g[3]))
00348     return
00349       is_func (g, GEN_FOREIGN);
00350   return false;
00351 }
00352 
00353 static bool
00354 is_applicable (const generic& g) {
00355   if (is<literal> (g)) {
00356     const string s= literal_to_string (g);
00357     if (N(s)==0) return false;
00358     for (nat i=0; i<N(s); i++)
00359       if (s[i] == '.') {
00360         if (i != 0 || N(s) == 1) return false; }
00361       else if (((s[i]<'0') || (s[i]>'9')) &&
00362                ((s[i]<'a') || (s[i]>'z')) &&
00363                ((s[i]<'A') || (s[i]>'Z')) &&
00364                ((s[i]!='_') && (s[i]!='?') && (s[i]!='$')))
00365         return false;
00366       else if (s[i] == '$') return true;
00367   }
00368   return
00369     g != GEN_SEQAND && g != GEN_SEQOR && g != GEN_XOR &&
00370     g != GEN_LAMBDA && g != GEN_MACRO &&
00371     g != GEN_COERCE && g != GEN_COERCE_TYPE;
00372 }
00373 
00374 /******************************************************************************
00375 * Commands
00376 ******************************************************************************/
00377 
00378 static generic
00379 un_try_catch (const generic& g) {
00380   vector<generic> v;
00381   if (is_func (g[1], GEN_BEGIN)) v << cdr (compound_to_vector (g[1]));
00382   else v << g[1];
00383   for (nat i=2; i<N(g); i++) v << g[i];
00384   return gen (g[0], gen (GEN_BEGIN, v));
00385 }
00386 
00387 generic
00388 mmx_printer::pp_C0 (const generic& g, bool large) {
00389   if (is_func (g, GEN_BEGIN)) {
00390     if (N(g) == 1) return concat (pp_verb ("{"), pp_verb ("}"));
00391     vector<generic> v, w;
00392     v << pp_verb ("{") << pp_lf ();
00393     for (nat i=1; i<N(g); i++)
00394       w << pp_C0 (g[i], true);
00395     v << indented (w);
00396     v << pp_verb ("}");
00397     if (large) v << pp_lf ();
00398     return concat (v);
00399   }
00400   else if (is_func (g, GEN_IF, 2)) {
00401     generic t= g[2];
00402     if (is_func (g[2], GEN_IF)) t= gen (GEN_BEGIN, g[2]);
00403     return concat (keyword ("if", pp_E0 (g[1])),
00404                    pp_spc (),
00405                    keyword ("then", pp_C0 (t, large)));
00406   }
00407   else if (is_func (g, GEN_IF, 3)) {
00408     generic t= g[2];
00409     if (is_func (g[2], GEN_IF)) t= gen (GEN_BEGIN, g[2]);
00410     bool large2= is_C0 (t);
00411     return concat (vec (keyword ("if", pp_E0 (g[1])),
00412                         pp_spc (),
00413                         keyword ("then", pp_C0 (t, large2)),
00414                         large2? concat (): pp_spc (),
00415                         keyword ("else", pp_C0 (g[3], large))));
00416   }
00417   else if (is_func (g, GEN_LOOP))
00418     return concat (pp_Conds (g), keyword ("loop", pp_C0 (g[N(g)-1], large)));
00419   else if (is_func (g, GEN_TRY))
00420     return keyword ("try", pp_C0 (un_try_catch (g) [1], large));
00421   else if (is_func (g, GEN_DEFINE, 2) && is_func (g[1], GEN_CATCH))
00422     return concat (pp_F0 (g[1]), pp_spc (), pp_C0 (g[2], large));
00423   else if (is_func (g, GEN_RETURN, 1))
00424     return keyword ("return", pp_C0 (g[1], large));
00425   else if (g == GEN_RETURN)
00426     return concat (keyword ("return"), pp_sep (large));
00427   else if (g == GEN_BREAK)
00428     return concat (keyword ("break"), pp_sep (large));
00429   else if (g == GEN_CONTINUE)
00430     return concat (keyword ("continue"), pp_sep (large));
00431   else if (is_func (g, GEN_INTERN, 1) ||
00432            is_func (g, GEN_METHOD, 1) ||
00433            is_func (g, GEN_EXTERN, 1) ||
00434            is_func (g, GEN_CONSTANT, 1) ||
00435            is_func (g, GEN_MUTABLE, 1) ||
00436            is_func (g, GEN_PUBLIC, 1) ||
00437            is_func (g, GEN_PRIVATE, 1))
00438     return keyword (g[0], pp_C0 (g[1], large));
00439   else if (is_func (g, GEN_FOREIGN, 3))
00440     return keyword (g[0], keyword (g[1], keyword (g[2], pp_C0 (g[3], large))));
00441   else if (is_func (g, GEN_FORALL, 2) ||
00442            is_func (g, GEN_EXISTS, 2) ||
00443            is_func (g, GEN_ASSUME, 2) ||
00444            is_func (g, GEN_PENALTY, 2))
00445     return operate (keyword (g[0], bracket ("(", pp_E0 (g[1]), ")")),
00446                     pp_C0 (g[2], large));
00447   else if (is_func (g, GEN_CLASS, 1) ||
00448            is_func (g, GEN_MODULE, 1) ||
00449            is_func (g, GEN_CATEGORY, 1))
00450     return concat (keyword (g[0], pp_F0 (g[1])), pp_sep (large));
00451   else if (is_func (g, GEN_CLASS, 2) ||
00452            is_func (g, GEN_MODULE, 2) ||
00453            is_func (g, GEN_CATEGORY, 2))
00454     return keyword (g[0], infix (pp_F0 (g[1]), "==", pp_C0 (g[2], large)));
00455   else if (is_func (g, GEN_DEFINE, 2) ||
00456            is_func (g, GEN_ASSIGN, 2) ||
00457            is_func (g, GEN_DEFINE_MACRO, 2) ||
00458            is_func (g, GEN_ASSIGN_MACRO, 2) ||
00459            is_func (g, GEN_PLUS_ASSIGN, 2) ||
00460            is_func (g, GEN_MINUS_ASSIGN, 2) ||
00461            is_func (g, GEN_TIMES_ASSIGN, 2) ||
00462            is_func (g, GEN_OVER_ASSIGN, 2) ||
00463            is_func (g, GEN_LESSLESSEQ, 2) ||
00464            is_func (g, GEN_GTRGTREQ, 2))
00465     return infix (pp_F0 (g[1]), g[0], pp_C0 (g[2], large));
00466   else if (is_func (g, GEN_LAMBDA) || is_func (g, GEN_MACRO)) {
00467     if (new_lambda_style) {
00468       vector<generic> v= compound_to_vector (g);
00469       generic t= gen (GEN_TUPLE, range (v, 1, N(v) - 1));
00470       generic b= g[N(g)-1];
00471       if (is_func (b, GEN_TYPE, 2)) { t= gen (GEN_TYPE, t, b[2]); b= b[1]; }
00472       return concat (keyword (g[0], pp_E0 (t)),
00473                      pp_spc (),
00474                      keyword ("do", pp_C0 (b, large)));
00475     }
00476     else {
00477       generic a= pp_E0 (g[1]);
00478       if (N(g) == 4) a= infix (a, ":", pp_E0 (g[3]));
00479       return concat (keyword (g[0], a),
00480                      pp_spc (),
00481                      keyword ("do", pp_C0 (g[2], large)));
00482     }
00483   }
00484   else return concat (pp_E1 (g), pp_sep (large));
00485 }
00486 
00487 /******************************************************************************
00488 * Special programming constructs
00489 ******************************************************************************/
00490 
00491 generic
00492 mmx_printer::pp_Conds (const generic& conds) {
00493   vector<generic> v;
00494   for (nat i=1; i<N(conds)-1; i++) {
00495     generic g= conds[i];
00496     if (is_func (g, GEN_FOR, 1) ||
00497         is_func (g, GEN_WHILE, 1) ||
00498         is_func (g, GEN_UNTIL, 1) ||
00499         is_func (g, GEN_STEP, 1))
00500       v << keyword (g[0], pp_E0 (g[1])) << pp_spc ();
00501   }
00502   return concat (v);
00503 }
00504 
00505 /******************************************************************************
00506 * Tuples
00507 ******************************************************************************/
00508 
00509 generic
00510 mmx_printer::pp_where (const generic& g) {
00511   return infix (pp_E0 (g[1]), g[0], pp_E0s (g, 2));
00512 }
00513 
00514 generic
00515 mmx_printer::pp_E0s (const generic& g, nat start) {
00516   nat n= N (g);
00517   if (start >= n) return concat ();
00518   else if (is_func (g[start], GEN_WHERE) && start==n-1)
00519     return pp_where (g[start]);
00520   else if (is_func (g[start], GEN_VWHERE) && start==n-1)
00521     return pp_where (g[start]);
00522   else {
00523     bool vertical= false;
00524     for (nat i=start; i<n; i++)
00525       vertical= vertical || is_func (g[i], GEN_ROW);
00526     vector<generic> v;
00527     for (nat i=start; i<n; i++)
00528       v << pp_E0 (g[i]);
00529     if (vertical) return vlist (v);
00530     else return hlist (v);
00531   }
00532 }
00533 
00534 /******************************************************************************
00535 * Expressions
00536 ******************************************************************************/
00537 
00538 generic
00539 mmx_printer::pp_E0 (const generic& g) {
00540   if (is_func (g, GEN_FORALL, 2) ||
00541       is_func (g, GEN_EXISTS, 2) ||
00542       is_func (g, GEN_ASSUME, 2) ||
00543       is_func (g, GEN_PENALTY, 2))
00544     return operate (keyword (g[0], bracket ("(", pp_E0 (g[1]), ")")),
00545                     pp_E0 (g[2]));
00546   else if (is_func (g, GEN_DEFINE, 2) ||
00547            is_func (g, GEN_ASSIGN, 2) ||
00548            is_func (g, GEN_DEFINE_MACRO, 2) ||
00549            is_func (g, GEN_ASSIGN_MACRO, 2) ||
00550            is_func (g, GEN_PLUS_ASSIGN, 2) ||
00551            is_func (g, GEN_MINUS_ASSIGN, 2) ||
00552            is_func (g, GEN_TIMES_ASSIGN, 2) ||
00553            is_func (g, GEN_OVER_ASSIGN, 2) ||
00554            is_func (g, GEN_LESSLESSEQ, 2) ||
00555            is_func (g, GEN_GTRGTREQ, 2))
00556     return infix (pp_F0 (g[1]), g[0], pp_E0 (g[2]));
00557   else return pp_E1 (g);
00558 }
00559 
00560 generic
00561 mmx_printer::pp_E1 (const generic& g) {
00562   if (is_func (g, GEN_LAMBDA) || is_func (g, GEN_MACRO)) {
00563     if (new_lambda_style) {
00564       vector<generic> v= compound_to_vector (g);
00565       generic t= gen (GEN_TUPLE, range (v, 1, N(v) - 1));
00566       generic b= g[N(g)-1];
00567       if (is_func (b, GEN_TYPE, 2)) { t= gen (GEN_TYPE, t, b[2]); b= b[1]; }
00568       generic d= (is_C0 (b)? pp_C0 (b): pp_E0 (b));
00569       return concat (keyword (g[0], pp_E0 (t)), pp_spc (), keyword ("do", d));
00570     }
00571     else {
00572       generic a= pp_E0 (g[1]);
00573       if (N(g) == 4) a= infix (a, ":", pp_E0 (g[3]));
00574       generic b= (is_C0 (g[2])? pp_C0 (g[2]): pp_E0 (g[2]));
00575       return concat (keyword (g[0], a), pp_spc (), keyword ("do", b));
00576     }
00577   }
00578   else if (is_func (g, GEN_MAPSTO, 2))
00579     return infix (pp_E2 (g[1]), g[0], pp_E2 (g[2]));
00580   else return pp_E2 (g);
00581 }
00582 
00583 generic
00584 mmx_printer::pp_E2 (const generic& g) {
00585   if (is_func (g, GEN_LESSLESS, 2))
00586     return infix (pp_Lflux (g[1]), g[0], pp_F0 (g[2]));
00587   else if (is_func (g, GEN_GTRGTR, 2))
00588     return infix (pp_F0 (g[1]), g[0], pp_Rflux (g[2]));
00589   else return pp_F0 (g);
00590 }
00591 
00592 generic
00593 mmx_printer::pp_Lflux (const generic& g) {
00594   if (is_func (g, GEN_LESSLESS, 2))
00595     return infix (pp_Lflux (g[1]), g[0], pp_F0 (g[2]));
00596   else return pp_F0 (g);
00597 }
00598 
00599 generic
00600 mmx_printer::pp_Rflux (const generic& g) {
00601   if (is_func (g, GEN_GTRGTR, 2))
00602     return infix (pp_F0 (g[1]), g[0], pp_Rflux (g[2]));
00603   else return pp_F0 (g);
00604 }
00605 
00606 /******************************************************************************
00607 * Formulas
00608 ******************************************************************************/
00609 
00610 generic
00611 mmx_printer::pp_F0 (const generic& g) {
00612   if (is_func (g, GEN_IMPLIES, 2) ||
00613       is_func (g, GEN_EQUIV, 2))
00614     return infix (pp_F1 (g[1]), g[0], pp_F1 (g[2]));
00615   else return pp_F1 (g);
00616 }
00617 
00618 generic
00619 mmx_printer::pp_F1 (const generic& g) {
00620   if (is_func (g, GEN_SEQOR, 2))
00621     return infix (pp_Seqors (g[1]), g[0], pp_Seqors (g[2]));
00622   else if (is_func (g, GEN_OR, 2))
00623     return infix (pp_Ors (g[1]), g[0], pp_Ors (g[2]));
00624   else if (is_func (g, GEN_XOR, 2))
00625     return infix (pp_Xors (g[1]), g[0], pp_Xors (g[2]));
00626   else return pp_F2 (g);
00627 }
00628 
00629 generic
00630 mmx_printer::pp_Seqors (const generic& g) {
00631   if (is_func (g, GEN_SEQOR, 2))
00632     return infix (pp_Seqors (g[1]), g[0], pp_Seqors (g[2]));
00633   else return pp_F2 (g);
00634 }
00635 
00636 generic
00637 mmx_printer::pp_Ors (const generic& g) {
00638   if (is_func (g, GEN_OR, 2))
00639     return infix (pp_Ors (g[1]), g[0], pp_Ors (g[2]));
00640   else return pp_F2 (g);
00641 }
00642 
00643 generic
00644 mmx_printer::pp_Xors (const generic& g) {
00645   if (is_func (g, GEN_XOR, 2))
00646     return infix (pp_Xors (g[1]), g[0], pp_Xors (g[2]));
00647   else return pp_F2 (g);
00648 }
00649 
00650 generic
00651 mmx_printer::pp_F2 (const generic& g) {
00652   if (is_func (g, GEN_AND, 2))
00653     return infix (pp_Ands (g[1]), g[0], pp_Ands (g[2]));
00654   else if (is_func (g, GEN_SEQAND, 2))
00655     return infix (pp_Seqands (g[1]), g[0], pp_Seqands (g[2]));
00656   else return pp_F3 (g);
00657 }
00658 
00659 generic
00660 mmx_printer::pp_Seqands (const generic& g) {
00661   if (is_func (g, GEN_SEQAND, 2))
00662     return infix (pp_Seqands (g[1]), g[0], pp_Seqands (g[2]));
00663   else return pp_F3 (g);
00664 }
00665 
00666 generic
00667 mmx_printer::pp_Ands (const generic& g) {
00668   if (is_func (g, GEN_AND, 2) || is_func (g, GEN_SEQAND, 2))
00669     return infix (pp_Ands (g[1]), g[0], pp_Ands (g[2]));
00670   else return pp_F3 (g);
00671 }
00672 
00673 generic
00674 mmx_printer::pp_F3 (const generic& g) {
00675   if (is_func (g, GEN_EQUAL, 2) ||
00676       is_func (g, GEN_UNEQUAL, 2) ||
00677       is_func (g, GEN_LESS, 2) ||
00678       is_func (g, GEN_LESSEQ, 2) ||
00679       is_func (g, GEN_GTR, 2) ||
00680       is_func (g, GEN_GTREQ, 2))
00681     return infix (pp_T0 (g[1]), g[0], pp_T0 (g[2]));
00682   else if (is_func (g, GEN_TYPE, 2))
00683     return infix (pp_T0 (g[1]), g[0], pp_T0 (g[2]));
00684   else if (is_func (g, GEN_IN, 2) && is_func (g[1], GEN_TYPE, 2))
00685     return infix (pp_F3 (g[1]), g[0], pp_T0 (g[2]));
00686   else if (is_func (g, GEN_IN, 2))
00687     return infix (pp_T0 (g[1]), g[0], pp_T0 (g[2]));
00688   else return pp_T0 (g);
00689 }
00690 
00691 /******************************************************************************
00692 * Terms
00693 ******************************************************************************/
00694 
00695 generic
00696 mmx_printer::pp_T0 (const generic& g) {
00697   if (is_func (g, GEN_TRANSTYPE, 2) ||
00698       is_func (g, GEN_CONVERTS, 2))
00699     return infix (pp_T0 (g[1]), g[0], pp_T1 (g[2]));
00700   else if ((is_func (g, GEN_COERCE, 2) ||
00701             (is_func (g, GEN_COERCE_TYPE) && N(g) > 2)) &&
00702            mmx_abbreviate_coerce) {
00703     // FIXME: this temporary hack avoids us to print huge type names
00704     generic op= GEN_TRANSTYPE;
00705     if (is_func (g, GEN_COERCE_TYPE)) op= "::>";
00706     if (is_func (g, GEN_COERCE_TYPE, 3)) op= ":+>";
00707     return infix (pp_T0 (g[1]), op, pp_T1 (g[2]));
00708   }
00709   else return pp_T1 (g);
00710 }
00711 
00712 generic
00713 mmx_printer::pp_T1 (const generic& g) {
00714   if (is_func (g, GEN_INTO, 2) ||
00715       is_func (g, GEN_MAPSTO, 2))
00716     return infix (pp_T2 (g[1]), g[0], pp_T2 (g[2]));
00717   else return pp_T2 (g);
00718 }
00719 
00720 generic
00721 mmx_printer::pp_T2 (const generic& g) {
00722   if (is_func (g, GEN_RANGE, 2) ||
00723       is_func (g, GEN_SCOPE, 2))
00724     return infix (pp_T3 (g[1]), g[0], pp_T3 (g[2]));
00725   else if (is_func (g, GEN_TO, 2))
00726     return infix (pp_T3 (g[1]), g[0], pp_T3 (g[2]));
00727   else if (is_func (g, GEN_DOWNTO, 2))
00728     return infix (pp_T3 (g[1]), g[0], pp_T3 (g[2]));
00729   else return pp_T3 (g);
00730 }
00731 
00732 static void
00733 collect (vector<generic>& v, const generic& g, nat depth) {
00734   if (depth >= 16384) v << g;
00735   else if (is_func (g, GEN_PLUS, 2)) {
00736     collect (v, g[1], depth+1);
00737     collect (v, g[2], depth+1);
00738   }
00739   else if (is_func (g, GEN_MINUS, 2)) {
00740     collect (v, g[1], depth+1);
00741     v << gen (GEN_MINUS, g[2]);
00742   }
00743   else v << g;
00744 }
00745 
00746 static vector<generic>
00747 collect (const generic& g) {
00748   vector<generic> v;
00749   collect (v, g, 0);
00750   vector<generic> w;
00751   for (nat i=0; i<N(v); i++)
00752     if (is_func (v[i], GEN_PLUS, 2) || is_func (v[i], GEN_MINUS, 2))
00753       w << collect (v[i]);
00754     else w << v[i];
00755   return w;
00756 }
00757 
00758 generic
00759 mmx_printer::pp_T3 (const generic& g) {
00760   if (is_func (g, GEN_PLUS, 2) || is_func (g, GEN_MINUS, 2)) {
00761     vector<generic> v= collect (g);
00762     for (nat i=0; i<N(v); i++)
00763       if (is_func (v[i], GEN_MINUS, 1))
00764         v[i]= gen (GEN_MINUS, pp_T4 (v[i][1]));
00765       else v[i]= pp_T3 (v[i]);
00766     return bigop (GEN_PLUS, v);
00767   }
00768   else return pp_T4 (g);
00769 }
00770 
00771 generic
00772 mmx_printer::pp_T4 (const generic& g) {
00773   if (is_func (g, GEN_TIMES, 2) ||
00774       is_func (g, GEN_COMPOSE, 2) ||
00775       is_func (g, GEN_APPEND, 2))
00776     return infix (pp_T4 (g[1]), g[0], pp_T4 (g[2]));
00777   else if (is_func (g, GEN_OVER, 2) ||
00778            is_func (g, GEN_SIZE, 2) ||
00779            is_func (g, "%", 2) ||
00780            is_func (g, "&", 2))
00781     return infix (pp_T4 (g[1]), g[0], pp_T5 (g[2]));
00782   else if (is_func (g, GEN_DIV, 2))
00783     return infix (pp_T4 (g[1]), "div", pp_T5 (g[2]));
00784   else if (is_func (g, GEN_QUO, 2))
00785     return infix (pp_T4 (g[1]), "quo", pp_T5 (g[2]));
00786   else if (is_func (g, GEN_REM, 2))
00787     return infix (pp_T4 (g[1]), "rem", pp_T5 (g[2]));
00788   else if (is_func (g, GEN_MOD, 2))
00789     return infix (pp_T4 (g[1]), "mod", pp_T5 (g[2]));
00790   else return pp_T5 (g);
00791 }
00792 
00793 generic
00794 mmx_printer::pp_T5 (const generic& g) {
00795   if (is_func (g, GEN_MINUS, 1))
00796     return prefix (g[0], pp_R0 (g[1]));
00797   else if (is_func (g, GEN_EXPLODE, 1) ||
00798            is_func (g, GEN_SIZE, 1) ||
00799            is_func (g, "%", 1) ||
00800            is_func (g, "&", 1) ||
00801            is_func (g, GEN_NOT, 1))
00802     return prefix (g[0], pp_T5 (g[1]));
00803   else if (is<literal> (g) && g != GEN_MINUS &&
00804            starts (literal_to_string (g), "-"))
00805     return pp_verb (literal_to_string (g));
00806   else return pp_R0 (g);
00807 }
00808 
00809 /******************************************************************************
00810 * Radicals
00811 ******************************************************************************/
00812 
00813 generic
00814 mmx_printer::pp_R0 (const generic& g) {
00815   return pp_R1 (g);
00816 }
00817 
00818 generic
00819 mmx_printer::pp_R1 (const generic& g) {
00820   if (is_func (g, GEN_POWER, 2) || is_func (g, GEN_FILL, 2))
00821     return infix (pp_R2 (g[1]), g[0], pp_R2 (g[2]));
00822   else return pp_R2 (g);
00823 }
00824 
00825 generic
00826 mmx_printer::pp_R2 (const generic& g) {
00827   if (is_func (g, GEN_FACTORIAL, 1))
00828     return postfix (pp_R2 (g[1]), "!");
00829   else if (is_func (g, GEN_PRIME, 1))
00830     return postfix (pp_R2 (g[1]), "'");
00831   else if (is_func (g, GEN_BACKPRIME, 1))
00832     return postfix (pp_R2 (g[1]), "`");
00833   else if (is_func (g, GEN_STAR, 1))
00834     return postfix (pp_R2 (g[1]), "*");
00835   else if (is_func (g, GEN_HAT, 1))
00836     return postfix (pp_R2 (g[1]), "^");
00837   else if (is_func (g, GEN_TILDA, 1))
00838     return postfix (pp_R2 (g[1]), "~");
00839   else if (is_func (g, GEN_QUOTE, 1) || is_func (g, GEN_BACKQUOTE, 1)) {
00840     if (is<literal> (g[1])) // this test should be further improved
00841       return prefix (g[0], pp_verb (literal_to_string (g[1])));
00842     else if (is_func (g[1], GEN_QUOTE, 1) || is_func (g[1], GEN_BACKQUOTE, 1))
00843       return prefix (g[0], pp_E0 (g[1]));
00844     else return prefix (g[0], bracket ("(", pp_E0 (g[1]), ")"));
00845   }
00846   else if (N(g) == 2 &&
00847            is<literal> (g[0]) &&
00848            starts (literal_to_string (g[0]), "."))
00849     return concat (pp_R2 (g[1]), pp_verb (literal_to_string (g[0])));
00850   else if (is_func (g, GEN_ACCESS))
00851     return operate (pp_R2 (g[1]), bracket ("[", pp_E0s (g, 2), "]"));
00852   else if ((is<compound> (g) && is_applicable (g[0])) ||
00853            (!is_nil (gl) && exact_eq (read_car (gl), g))) {
00854     if (is<literal> (g)) return pp_verb (literal_to_string (g));
00855       else if (is<literal> (g[0])) {
00856       string op= literal_to_string (g[0]);
00857       if (starts (op, "$") || starts (op, "tm$")) {
00858         vector<generic> v= vec<generic> (g[0]);
00859         for (nat i=1; i<N(g); i++) v << pp_E0 (g[i]);
00860         return vector_to_compound (v);
00861       }
00862     }
00863     return operate (pp_R2 (g[0]), bracket ("(", pp_E0s (g, 1), ")"));
00864   }
00865   else return pp_R3 (g);
00866 }
00867 
00868 generic
00869 mmx_printer::pp_R3 (const generic& g) {
00870   if (is<literal> (g) && !starts (literal_to_string (g), "-"))
00871     return pp_verb (literal_to_string (g));
00872   else if (is_func (g, GEN_SQTUPLE))
00873     return bracket ("[", pp_E0s (g, 1), "]");
00874   else if (is_func (g, GEN_TUPLE))
00875     return bracket ("(", pp_E0s (g, 1), ")");
00876   else if (is_func (g, GEN_ROW))
00877     return pp_E0s (g, 1);
00878   else if (is_func (g, GEN_WHERE) || is_func (g, GEN_VWHERE))
00879     return bracket ("(", pp_where (g), ")");
00880   else {
00881     gl= cons (g, gl);
00882     generic r= pp_E0 (g);
00883     gl= read_cdr (gl);
00884     return bracket ("(", r, ")");
00885   }
00886 }
00887 
00888 /******************************************************************************
00889 * Interface
00890 ******************************************************************************/
00891 
00892 generic
00893 print_mmx (const generic& g) {
00894   vector<generic> v;
00895   mmx_printer pp;
00896   if (is_func (g, GEN_BEGIN))
00897     for (nat i=1; i<N(g); i++)
00898       v << pp.pp_C0 (g[i], i<N(g)-1);
00899   else if (is_C0 (g)) v << pp.pp_C0 (g);
00900   else v << pp.pp_E0 (g);
00901   return concat (v);
00902 }
00903 
00904 string
00905 as_mmx (const generic& g) {
00906   return serialize (print_mmx (g));
00907 }
00908 
00909 string
00910 flatten_as_mmx (const generic& g) {
00911   generic f= as_generic (flatten (g));
00912   return as_mmx (f);
00913 }
00914 
00915 string
00916 output_as_mmx (const generic& g) {
00917   if (math_mode) {
00918     string r;
00919     r << DATA_BEGIN << "scheme:";
00920     r << flatten_as_texmacs_scheme (g);
00921     r << DATA_END;
00922     return r;
00923   }
00924   else {
00925     generic f= as_generic (flatten (g));
00926     return as_mmx (f);
00927   }
00928 }
00929 
00930 string
00931 string_as_mmx (const string& s) {
00932   //if (math_mode) { ... }
00933   return s;
00934 }
00935 
00936 } // namespace mmx
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines