1 ///////////////////////////////////////////////////////////////////////////////
2 // Pretty printing generator.
3 ///////////////////////////////////////////////////////////////////////////////
10 ///////////////////////////////////////////////////////////////////////////////
11 // Generate a pretty printer for a given type.
12 ///////////////////////////////////////////////////////////////////////////////
13 void DatatypeCompiler::gen_pretty_printer(Bool extern_def, Ty ty, Tys tys)
14 { match (deref_all(ty))
15 { ty as TYCONty(DATATYPEtycon { id, unit, arg, terms, qualifiers ... }, _):
17 pr ("%^%/%^// Pretty printer for type %T%^%/"
18 "%^ostream& operator << (ostream&, %t);"
19 "%^ostream& pretty_print(ostream&, %t, int = 0, int = 0);\n\n",
22 pr ("%^%/%^// Pretty printer for type %T%^%/"
23 "%^ostream& pretty_print(ostream& _f_, %t, int _tab_, int _prec_)"
27 int arity = unit + arg;
29 if (arity > 1) pr ("%^switch (%U(_x_)) {%+", ty);
31 for (int i = 0; i < arity; i++)
33 { term as ONEcons { ty, name, print_formats, cons_ty ... }:
34 { Ty t = ty == NOty ? NOty : apply_ty(cons_ty,tys);
35 if (arity > 1) pr ("%^case %*: %+", term, true);
36 if (print_formats != #[])
37 gen_formated_printer(term, t, print_formats);
39 gen_default_printer(term, t);
40 if (arity > 1) pr ("%^break;%-");
46 if (arity > 1) pr ("%-%^}");
50 pr ("%^ostream& operator << (ostream& _f_, %t)"
51 "%^{ return pretty_print(_f_,_x_); }\n\n",
58 ///////////////////////////////////////////////////////////////////////////////
59 // Method to print one type component.
60 ///////////////////////////////////////////////////////////////////////////////
61 void make_printer (DatatypeCompiler& C, Ty ty, Exp e)
62 { match (deref_all(ty))
63 { TYCONty(ARRAYtycon (bound as ! NOexp),tys):
64 { C.pr ("%^{ int _i_;%+"
66 "%^for (_i_ = 0; _i_ < %e; _i_++) {%+", bound);
67 make_printer(C,tys->#1,INDEXexp(e,IDexp("_i_")));
68 C.pr ("%^if (_i_ < %e - 1) _f_ << \", \";", bound);
75 { if (has_qual(QUALprintable, ty)) {
76 C.pr("%^pretty_print(_f_, %e, _tab_, _prec_);", e);
78 C.pr("%^_f_ << %e;", e);
84 ///////////////////////////////////////////////////////////////////////////////
85 // Generate a pretty printer according to the format string.
86 ///////////////////////////////////////////////////////////////////////////////
87 void DatatypeCompiler::gen_formated_printer(Cons term, Ty ty, PrintFormats fmt)
92 { NOty: { ty_list = #[]; }
93 | TYCONty(TUPLEtycon, tys): { ty_list = tys; }
94 | TYCONty(RECORDtycon(labs,_), tys): { ty_list = tys; lab_list = labs; }
95 | ty: { ty_list = #[ ty ]; }
98 int arity = length(ty_list);
103 Exp e = select(IDexp("_x_"), term);
105 for_each (PrintFormat, f, fmt)
107 { PFint i: // print the ith element
108 { if (lab_list != #[])
109 error("%Lformat #%i used on constructor %s%T\n",
112 for (t = ty_list, j = 1; t; t = t->#2, j++)
114 make_printer(*this, t->#1, DOTexp(e,index_of(i))); break;
117 error("%Lcomponent #%i not found in constructor %s%T\n",
120 | PFlabel l: // print label l
121 { if (lab_list == #[])
122 error("%Lformat #%s used on non-record constructor %s%T\n",
125 for (ls = lab_list, t = ty_list; ls && t; t = t->#2, ls = ls->#2)
127 make_printer(*this, t->#1, DOTexp(e,l)); break;
130 error("%Lcomponent %s not found in constructor %s%T\n",
133 | PFstring s: { pr ("%^_f_ << %s;", s); }
136 error ("%Lillegal format '_' on constructor %s%T\n",
140 if (arity == 1 && labs == #[]) exp = e;
141 else if (labs) exp = DOTexp(e,labs->#1);
142 else exp = DOTexp(e,index_of(index));
143 make_printer(*this, tys->#1, exp);
145 if (labs) labs = labs->#2;
150 { pr ("%^_tab_ += 3;"
152 "%^PrettyPrinter::print_tabs(_f_,_tab_);");
155 { pr ("%^_tab_ -= 3;"
157 "%^PrettyPrinter::print_tabs(_f_,_tab_);");
160 { pr ("%^_f_ << '\\n';"
161 "%^PrettyPrinter::print_tabs(_f_,_tab_);");
164 { error ("%Lillegal print format '%c' in constructor %s%T\n",
165 (int)c, term->name, ty);
171 ///////////////////////////////////////////////////////////////////////////////
172 // Generate a pretty printer using the default format
173 ///////////////////////////////////////////////////////////////////////////////
174 void DatatypeCompiler::gen_default_printer(Cons term, Ty ty)
175 { if (term->name[0] == '"')
176 pr ("%^_f_ << %s;", term->name);
178 pr ("%^_f_ << \"%s\";", term->name);
179 Exp e = select(IDexp("_x_"), term);
180 if (is_array_constructor(term->name))
181 ty = TYCONty(ARRAYtycon(ARROWexp(IDexp("_x_"),"len()")), #[ty]);
182 match (deref_all(ty))
184 | TYCONty(TUPLEtycon, tys):
185 { pr ("%^_f_ << '(';");
187 for(Tys t = tys; t; t = t->#2)
188 { make_printer(*this, t->#1, DOTexp(e,index_of(i)));
189 if (t->#2) pr ("%^_f_ << \", \";");
192 pr ("%^_f_ << ')';");
194 | TYCONty(RECORDtycon(labs,_), tys):
195 { pr ("%^_f_ << '{';");
197 for(l = labs, t = tys; t; l = l->#2, t = t->#2)
198 { pr ("%^_f_ << \"%s = \";", l->#1);
199 make_printer(*this, t->#1, DOTexp(e,l->#1));
200 if (t->#2) pr ("%^_f_ << \", \";");
202 pr ("%^_f_ << '}';");
204 | ty: { pr ("%^_f_ << '(';");
205 make_printer(*this, ty, e);
206 pr ("%^_f_ << ')';");