not needed
[prop.git] / prop-src / printing.pcc
blob8f0227a0f7b96156a08ffbcb260f7a665225920b
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 //  This file implements various pretty printing and formating routines.
4 //
5 ///////////////////////////////////////////////////////////////////////////////
7 #include <iostream>
8 #include <strstream>
9 #include <AD/contain/bitset.h>
10 #include <AD/strings/charesc.h>
11 #include <AD/strings/quark.h>
12 #include <stdio.h>
13 #include <ctype.h>
14 #include "ir.ph"
15 #include "ast.ph"
16 #include "matchcom.ph"
17 #include "type.h"
18 #include "options.h"
19 #include "list.h"
20 #include "graphtype.h"
22 ///////////////////////////////////////////////////////////////////////////////
24 //  Flags controlling printing formats of types.
26 ///////////////////////////////////////////////////////////////////////////////
27 Bool      pretty_print_ty      = true;
28 Bool      pretty_print_pattern = false;
29 Bool      pretty_print_exp     = false;
30 Bool      print_semantic_stack = false;
31 Bool      print_inner_action   = false;
32 Bool      print_default_value  = true;
33 Id        ty_id                = 0;
34 Parameter ty_parameter         = TYformal;
36 ///////////////////////////////////////////////////////////////////////////////
38 //  Print an identifier list 
40 ///////////////////////////////////////////////////////////////////////////////
41 std::ostream& operator << (std::ostream& f, Ids vars)
42 {  for(Ids vs = vars; vs; vs = vs->#2)
43    {  f << vs->#1; if (vs->#2) f << ", "; }
44    return f;
47 ///////////////////////////////////////////////////////////////////////////////
49 //  Print a scope
51 ///////////////////////////////////////////////////////////////////////////////
52 std::ostream& operator << (std::ostream& f, Scope s)
53 {  match (s)  
54    {  case PUBLICscope:    f << "public";
55       case PROTECTEDscope: f << "protected"; 
56       case PRIVATEscope:   f << "private"; 
57    }
58    return f;
61 ///////////////////////////////////////////////////////////////////////////////
62 //  Return the label for an tuple element index
63 ///////////////////////////////////////////////////////////////////////////////
64 Id index_of(int i,Id prefix) 
65 {  if (prefix == 0) prefix = "";
66    return Quark(Quark(prefix,"_"),i); 
69 ///////////////////////////////////////////////////////////////////////////////
71 //  Print a persistent id.
73 ///////////////////////////////////////////////////////////////////////////////
74 std::ostream& operator << (std::ostream& f, Pid pid)
75 {  match (pid)
76    {  PERSISTid id:  { f << id; }
77    |  PERSISTnone:   // skip
78    }
79    return f;
82 ///////////////////////////////////////////////////////////////////////////////
84 //  Print a literal.
86 ///////////////////////////////////////////////////////////////////////////////
87 std::ostream& operator << (std::ostream& f, Literal l)
88 {  match (l)
89    {  INTlit    i:  { f << i; }
90    |  BOOLlit   b:  { f << (b ? "true" : "false"); }
91    |  CHARlit   c:  { char b[32]; print_char(b,c); f << '\'' << b << '\''; }
92    |  REALlit   r:  
93       {  // use sprintf due to library problems in libg++ 2.5.8 on Linux
94          char buf[256];
95          sprintf(buf,"%lf", r);
96          f << buf; 
97          // ostrstream S(buf,sizeof(buf));
98          // std::ostream& S2 = S;
99          // S2 << r << ends;
100          // f << S.str(); 
101       }
102    |  STRINGlit s:  { f << s; }
103    |  REGEXPlit re: { f << re; }
104    |  QUARKlit q:   { if (pretty_print_pattern) f << '#' << q;
105                       else f << MatchCompiler::quark_name(q); 
106                     }
107    |  BIGINTlit n:  { if (pretty_print_pattern) f << "#" << n;
108                       else f << n; 
109                     }
110    }
111    return f;
114 ///////////////////////////////////////////////////////////////////////////////
116 //  Print type list.
118 ///////////////////////////////////////////////////////////////////////////////
119 std::ostream& operator << (std::ostream& f, Tys tys)
120 {  for(Tys t = tys; t; t = t->#2) {  
121       f << t->#1; 
122       if (t->#2 != #[]) f << ", "; 
123    }
124    return f;
127 ///////////////////////////////////////////////////////////////////////////////
129 //  Print type variables (i.e. template actual arguments)
131 ///////////////////////////////////////////////////////////////////////////////
132 void print_tyvars(std::ostream& f, Tys tys, Bool is_datatype)
133 {  if (tys != #[]) 
134       if (is_datatype) f << "(" << tys << ")";
135       else             f << '<' << tys << "> ";
138 ///////////////////////////////////////////////////////////////////////////////
140 //  Print type variables (i.e. formal template arguments)
142 ///////////////////////////////////////////////////////////////////////////////
143 void print_tyvars(std::ostream& f, TyVars tyvars, char open, char close, Bool header)
144 {  if (tyvars != #[]) {
145       if (header) f << "template ";
146       f << open;
147       for(TyVars t = tyvars; t; t = t->#2) {
148          if (header) f << "class ";
149          f << t->#1;
150          if (t->#2) f << ", ";
151       }
152       f << close;
153       if (header) f << ' ';
154    }
157 ///////////////////////////////////////////////////////////////////////////////
159 //  Print a tuple type.
161 ///////////////////////////////////////////////////////////////////////////////
162 void print_tuple(std::ostream& f, Tys tys)
163 {  if (pretty_print_ty) {
164       f << '(' << tys << ')';
165    } else {
166       f << "struct {";
167       int i = 1;
168       for (Tys t = tys; t; t = t->#2) {
169          ty_id = index_of(i);
170          f << t->#1 << "; ";
171          ty_id = #[];
172       }
173       f << "} ";
174    }
177 ///////////////////////////////////////////////////////////////////////////////
179 //  Print a mktuple type
181 ///////////////////////////////////////////////////////////////////////////////
182 void print_mktuple(std::ostream& f, Tys tys)
183 {  if (pretty_print_ty) {
184       f << ".[" << tys << ']';
185    } else {
186       f << "Tuple" << length(tys); 
187       print_tyvars(f,tys,false); 
188    }
191 ///////////////////////////////////////////////////////////////////////////////
193 //  Print a record type.
195 ///////////////////////////////////////////////////////////////////////////////
196 void print_record(std::ostream& f, Ids labs, Tys tys, Bool flex)
197 {  if (! pretty_print_ty) f << "struct ";
198    f << "{ ";
199    Tys t; Ids l;
200    for (t = tys, l = labs; t && l; t = t->#2, l = l->#2) {
201       if (pretty_print_ty) {
202          f << l->#1 << " : " << t->#1;
203          if (t->#2) f << ", ";
204       } else {
205          ty_id = l->#1; f << t->#1 << "; ";
206          ty_id = #[];
207       }
208    }
209    if (pretty_print_ty && flex) f << " ... ";
210    f << " }";
213 ///////////////////////////////////////////////////////////////////////////////
215 //  Print a function parameter.
217 ///////////////////////////////////////////////////////////////////////////////
218 void print_parameter (std::ostream& f, Ty ty, Id id, Parameter p)
219 {  Parameter save = ty_parameter;
220    Bool      sp = pretty_print_ty;
221    pretty_print_ty = false;
222    ty_parameter = p;
223    match (deref(ty))
224    {  TUPLEty tys:
225       {  int i = 1;
226          if (p == TYformal || p == TYsimpleformal || 
227              p == TYactual && tys != #[]) f << '(';
228          for (Tys ts = tys; ts; ts = ts->#2) {
229             ty_id = index_of(i,(p != TYbody ? "x" : ""));  
230             if (p != TYactual) f << ts->#1;
231             else f << ty_id;
232             if (p != TYbody) { if (ts->#2) f << ", "; }
233             else f << "; ";
234             i++;
235             ty_id = #[];
236          } 
237          if (p == TYformal || p == TYsimpleformal ||
238              p == TYactual && tys != #[]) f << ')';
239       }
240    |  RECORDty(labs,_,tys):
241       {  Ids l;
242          Tys t;
243          if (p == TYformal || p == TYsimpleformal ||
244              p == TYactual && tys != #[]) f << '(';
245          for (l = labs, t = tys; l && t; l = l->#2, t = t->#2) {
246             if (p != TYbody) 
247                ty_id = #"x_" + l->#1;
248             else
249                ty_id = l->#1;
250             if (p != TYactual) f << t->#1;
251             else f << ty_id;
252             if (p != TYbody) { if (t->#2) f << ", "; }
253             else f << "; ";
254             ty_id = #[];
255          }
256          if (p == TYformal || p == TYsimpleformal ||
257              p == TYactual && tys != #[]) f << ')';
258       }
259    |  ty: {  if (p != TYbody) f << '(';
260              if (p != TYbody) 
261                 ty_id = #"x_" + id;
262              else
263                 ty_id = id;
264              if (p != TYactual) f << ty;
265              else f << ty_id;
266              if (p == TYbody) f << "; "; 
267              ty_id = 0;
268              if (p != TYbody) f << ')';
269           }
270    }
271    ty_parameter = save;
272    pretty_print_ty = sp;
275 ///////////////////////////////////////////////////////////////////////////////
277 //  Method to print a type expression.
279 ///////////////////////////////////////////////////////////////////////////////
280 std::ostream& operator << (std::ostream& f, Ty ty)
281 {  Id this_id = 0;
282    if (ty_id) { this_id = ty_id; ty_id = 0; }
283    ty = deref(ty);
284    match (ty)
285    {  NOty:                 { f << "error"; }
286    |  VARty _:              { f << "???"; }
287    |  INDty (id, _):        { f << id; }
288    |  POLYty(t, _, _):      { f << t; }
289    |  TYPEty:               { f << "type"; }
290    |  POINTERty  t:         { f << t << " *"; }
291    |  REFty t:              { f << t << " &"; }
292    |  FUNty(a, b):          { f << a << " -> " << b; }
293    |  GRAPHty G:            { f << G->class_name; }
294    |  NODEty n:             { f << n->graph()->class_name <<"::"<< n->name(); }
295    |  EDGEty e:             { f << "edge " << e->name(); }
296    |  TUPLEty tys:          { print_tuple(f,tys); }
297    |  EXTUPLEty tys:        { print_mktuple(f,tys); }
298    |  RECORDty(l,flex,tys): { print_record(f,l,tys,flex); }
299    |  IDty(id, tys):        
300       {  if (options.new_type_format && tys != #[])
301          {  match (deref_all(ty))
302             {  DATATYPEty({ id ... },_): 
303                {  if (! pretty_print_ty) f << "a_";
304                   f << id; print_tyvars(f,tys,false); 
305                   if (! pretty_print_ty) 
306                   {  if (tys == #[]) f << ' ';
307                      f << "* ";
308                   }
309                }
310             |  _: { f << id; print_tyvars(f,tys,false); }
311             }
312          } else
313          {  f << id;
314             match (deref_all(ty))
315             {  DATATYPEty(_,_): { print_tyvars(f,tys,! pretty_print_ty); }
316             |  _:               { print_tyvars(f,tys,false); }
317             }
318          }
319       }
320    |  ARRAYty(t,exp):      
321       {  if (this_id) { ty_id = this_id; this_id = 0; }
322          f << t << '[' << exp << ']'; 
323       }
324    |  DEFVALty(ty, exp):                 
325       {  if (this_id) { ty_id = this_id; this_id = 0; }
326          f << ty;
327          if (ty_parameter != TYbody && ty_parameter != TYsimpleformal 
328            && print_default_value) f << " = " << exp; 
329       } 
330    |  QUALty  (q,t):                     
331       {  if (q & QUALunsigned) f << "unsigned ";
332          if (q & QUALsigned)   f << "signed ";
333          if ((ty_parameter == TYformal || ty_parameter == TYsimpleformal)
334              && (q & QUALclass)) 
335             f << (TYCONty(REFtycon,#[ QUALty(QUALconst,t) ]));
336          else 
337             f << t; 
338          if (q & QUALconst)    f << " const";
339       }
340    |  DATATYPEty({ id, tyvars ... }, #[]): { f << id; }
341    |  DATATYPEty({ id, tyvars ... }, tys): 
342       {  if (! pretty_print_ty) f << "a_";
343          f << id; print_tyvars(f,tys,false); 
344          if (! pretty_print_ty) 
345          {  if (tys == #[]) f << ' ';
346             f << "* ";
347          }
348       }
349    |  NESTEDty(a,b):  { f << a << "::" << b; }
350    |  _: { bug ("operator << (std::ostream&, Ty)"); }
351    }
352    if (this_id) f << ' ' << this_id; 
353    return f;
357 ///////////////////////////////////////////////////////////////////////////////
359 //  Method to print a pattern list.
361 ///////////////////////////////////////////////////////////////////////////////
362 void print (std::ostream& f, Pats pats, Id open, Id close, 
363             Bool flex1, Pat p, Bool flex2 = false, 
364             Pat len = NOpat, Pat array = NOpat)
365 {  f << open;
366    if (len != NOpat)   
367    {  f << " |" << len;
368       if (array != NOpat) f << " : " << array; 
369       f << " |";
370    }
371    if (flex2) f << " ... ";
372    for (Pats ps = pats; ps; ps = ps->#2) {
373       f << ps->#1;
374       if (ps->#2) f << ", ";
375    }
376    if (flex1 && pats != #[] && p != NOpat) f << " ... ";
377    if (p != NOpat) f << p;
378    f << close;
381 ///////////////////////////////////////////////////////////////////////////////
383 //  Method to print a labeled pattern list.
385 ///////////////////////////////////////////////////////////////////////////////
386 void print (std::ostream& f, LabPats lab_pats, Bool flex)
387 {  f << '{';
388    for (LabPats ps = lab_pats; ps; ps = ps->#2) {
389       f << ps->#1.label << " = " << ps->#1.pat;
390       if (ps->#2) f << ", ";
391    }
392    f << '}';
395 ///////////////////////////////////////////////////////////////////////////////
397 //  Methods extract the open and close brace of a list.
399 ///////////////////////////////////////////////////////////////////////////////
400 Id open_of(Cons c) 
401 {  match (c)
402    {  ONEcons { name ... }: { char s[3]; 
403                               s[0] = name[0]; s[1] = name[1]; s[2] = '\0';
404                               return Quark(s); 
405                             }
406    |  _:                    { return "<??>["; }
407    } 
410 Id close_of(Cons c)
411 {  match (c)
412    {  ONEcons { name ... }: { return name+2; }
413    |  _:                    { return "]"; }
414    } 
417 Id close_of2(Cons c)
418 {  match (c)
419    {  ONEcons { name ... }: { return name+strlen(name)-2; }
420    |  _:                    { return "]"; }
421    } 
424 ///////////////////////////////////////////////////////////////////////////////
426 //  Method to print a pattern list.
428 ///////////////////////////////////////////////////////////////////////////////
429 std::ostream& operator << (std::ostream& f, Pats ps)
430 {  print(f,ps,"","",false,NOpat); return f; }
432 ///////////////////////////////////////////////////////////////////////////////
434 //  Method to print a pattern.
436 ///////////////////////////////////////////////////////////////////////////////
437 std::ostream& operator << (std::ostream& f, Pat p)
438 {  match (p)
439    {  NOpat:                      // skip
440    |  WILDpat _:                  { f << '_'; }
441    |  BACKEDGEpat (_,id,_):       { f << '<' << id << '>'; }
442    |  IDpat (id,_,_):             { f << id; }
443    |  INDpat (id,_,_):            { f << '?' << id; }
444    |  ASpat (id,p,_,_):           { f << id << " as " << p; }
445    |  TYPEDpat (p,ty):            { f << p << " : " << ty; }
446    |  TUPLEpat ps:                { print(f,ps,"(",")",false,NOpat); }
447    |  EXTUPLEpat ps:              { print(f,ps,".(",")",false,NOpat); }
448    |  ARRAYpat (ps,flex):         { print(f,ps,"[","]",flex,NOpat); }
449    |  RECORDpat (ps,flex):        { print(f,ps,flex); }
450    |  LOGICALpat(NOTpat,a,_):     { f << "(! " << a << ")"; }
451    |  LOGICALpat(ANDpat,a,b):     { f << '(' << a << " && " << b << ')'; }
452    |  LOGICALpat(ORpat,a,b):      { f << '(' << a << " || " << b << ')'; }
453    |  LOGICALpat(IMPLIESpat,a,b): { f << '(' << a << " implies: " << b << ')'; }
454    |  LOGICALpat(EQUIVpat,a,b):   { f << '(' << a << " equiv: " << b << ')'; }
455    |  LOGICALpat(XORpat,a,b):     { f << '(' << a << " xor: " << b << ')'; }
456    |  GUARDpat(p,e):              { f << p << " | " << e; }
457    |  APPENDpat(p1,p2,_):         { f << '(' << p1 << " ; " << p2 << ')'; }
458    |  UNIFYpat(p,e):              { f << '(' << p << " := " << e << ")"; }
459    |  MARKEDpat(_,p):             { f << p; }
460    |  CONSpat(ONEcons { qual, alg_ty = DATATYPEty ({ id ... },_) ... })
461           | qual & QUALvariable: 
462                                   { f << id << "?"; }
463    |  CONSpat(ONEcons { name ... }):   { f << name; }
464    |  CONSpat(NOcons):            { f << "<none>"; }
465    |  APPpat(p1,p2):              { f << p1 << ' ' << p2; }
466    |  LEXEMEpat(id, ty, n, terms): { f << "lexeme class " << id; }
467    |  POLYpat(id,_,#[],p,e,_):      { f << id << " = " << p; }
468    |  POLYpat(id,_,vars,p,e,_):     { f << id << '(' << vars << ") = " << p; }
469    |  VECTORpat{cons,elements,len,array,head_flex=u,tail_flex=v}: 
470       { print(f,elements,open_of(cons),close_of2(cons),v,NOpat,u,len,array); }
471    |  LISTpat{nil,head,tail ...}: 
472       { print(f,head,open_of(nil),close_of(nil),true,tail); }
473    |  CONTEXTpat(context,pat):
474       {  f << "<<";
475          for (Conses ids = context; ids; ids = ids->#2)
476          {  if (ids->#1 != NOcons) f << ids->#1->name; 
477             if (ids->#2) f << ", "; 
478          }
479          f << ">>" << pat;
480       }
481    |  LITERALpat lit:
482       {  Bool save = pretty_print_pattern;
483          pretty_print_pattern = true;
484          f << lit;
485          pretty_print_pattern = save;
486       }
487    }
488    return f;
491 ///////////////////////////////////////////////////////////////////////////////
493 //  Convert a string into a suitable encoding
495 ///////////////////////////////////////////////////////////////////////////////
496 void encode_string(char * buf, const char * s)
497 {  while (*s)
498    {  unsigned char c = *s++;
499       if (c == '"')
500       {  *buf++ = 'X'; *buf++ = 'X';
501       } else if (isalnum(c) || c == '_')
502       {  *buf++ = '_'; *buf++ = c; 
503       } else      
504       {
505          int lo = c % 16, hi = c / 16;
506          *buf++ = hi + 'a';
507          *buf++ = lo + 'a';
508       }
509    }
510    *buf++ = '\0';  
513 ///////////////////////////////////////////////////////////////////////////////
515 //  Method to print the mangled name of list constructors.
517 ///////////////////////////////////////////////////////////////////////////////
518 fun mangle id | id == 0: { return "(null)"; }
519   | mangle "#[...]": Id: { return "list_1_"; }
520   | mangle "#(...)":     { return "list_2_"; }
521   | mangle "#{...}":     { return "list_3_"; }
522   | mangle "#[]":        { return "nil_1_"; }
523   | mangle "#()":        { return "nil_2_"; }
524   | mangle "#{}":        { return "nil_3_"; }
525   | mangle "[|...|]":    { return "vector_1_"; }
526   | mangle "(|...|)":    { return "vector_2_"; }
527   | mangle "{|...|}":    { return "vector_3_"; }
528   | mangle id | id[0] == '"':
529                          { char buf[256]; encode_string(buf,id); 
530                            return Quark(buf); }
531   | mangle id:           { return id; }
532   ;
534 ///////////////////////////////////////////////////////////////////////////////
536 //  Method to print the name of a constructor
538 ///////////////////////////////////////////////////////////////////////////////
539 std::ostream& print_cons (std::ostream& f, Cons cons)
540 {  match (cons)
541    {  ONEcons { name, ty = NOty ... }: {  f << mangle(name); }
542    |  ONEcons { name, alg_ty = DATATYPEty({ opt, id ... },_) ... }:
543       {  if (opt & OPTsubclassless)
544             f << "a_" << id;
545          else
546             f << id << "_" << mangle(name);
547       }
548    |  _: {  bug("print_cons()"); }
549    } 
550    return f;
553 ///////////////////////////////////////////////////////////////////////////////
555 //  Method to print an expression list
557 ///////////////////////////////////////////////////////////////////////////////
558 std::ostream& operator << (std::ostream& f, Exps es)
559 {  for (Exps l = es; l; l = l->#2) {
560       f << l->#1; if (l->#2) f << ',';
561    }
562    return f;
565 ///////////////////////////////////////////////////////////////////////////////
567 //  Method to print an expression.
569 ///////////////////////////////////////////////////////////////////////////////
570 std::ostream& operator << (std::ostream& f, Exp e)
571 {  match (e)
572    {  NOexp:                     { }
573    |  IDexp id:                  { f << id; }
574    |  RELexp i | same_selectors: { f << "_0"; }
575    |  RELexp i:                  { f << '_' << i; }
576    |  MARKEDexp (_,e):           { f << e; }
577    |  LITERALexp l:              { f << l; }
578    |  ASSIGNexp (e1,e2):         { f << '(' << e1 << " = " << e2 << ')'; }
579    |  DOTexp(SELECTORexp(e,c,t),id) | pretty_print_exp:
580       { f << e << '!' << c->name << '.';
581         int n = atol(id+1);
582         if (n > 0) f << n; else f << id; 
583       } 
584    |  SELECTORexp(e,c,t) | pretty_print_exp:
585       { f << e << '!' << c->name; }
586    |  DOTexp(SELECTORexp(e,c,t),id): 
587       { f << MatchCompiler::make_select(e,c,t,id); }
588    |  SELECTORexp(e,cons,t): { f << MatchCompiler::make_select(e,cons,t); }
589    |  DOTexp (DEREFexp e,id):    { f << e << "->" << id; }
590    |  DOTexp    (e,id):     { f << e << '.' << id; }
591    |  DEREFexp  (e):        { f << "(*" << e << ')'; }
592    |  ARROWexp  (e,id):     { f << e << "->" << id; }
593    |  APPexp    (e1,e2):    { f << e1 << '(' << e2 << ')'; }
594    |  INDEXexp  (e1,e2):    { f << e1 << '[' << e2 << ']'; }
595    |  BINOPexp  (x,e1,e2):  { f << '(' << e1 << ' ' << x << ' ' << e2 << ')'; }
596    |  PREFIXexp (x,e):      { f << '(' << x << ' ' << e << ')'; }
597    |  POSTFIXexp(x,e):      { f << '(' << e << ' ' << x << ')'; }
598    |  CASTexp (ty,e):       { Bool save = pretty_print_ty;
599                               pretty_print_ty = false;
600                               f << "((" << ty << ')' << e << ')'; 
601                               pretty_print_ty = save;
602                             }
603    |  QUALexp (ty,e):       { f << ty << "::" << e; }
604    |  EQexp(_,e1,e2):       { f << "equality_of(" << e1 << ',' << e2 << ')'; }
605    |  UNIFYexp(_,e1,e2):    { f << "unify(" << e1 << ',' << e2 << ')'; }
606    |  LTexp(_,e1,e2):       { f << '(' << e1 << " < " << e2 << ')'; }
607    |  HASHexp(_,e):         { f << "hash(" << e << ')'; }
608    |  TUPLEexp es:          { f << es; }
609    |  EXTUPLEexp es:        { f << "mkTuple" << length(es) << '(' << es << ')'; }
610    |  IFexp(a,b,c):         { f << '(' << a << " ? " << b << " : " << c <<')';}
611    |  SYNexp  (i,r,_,in_rewrite):             
612       { if (in_rewrite)
613            f << '_' << i << "__";
614         else if (r < 0) // parser semantic action
615         {  if (i == 0) f << "syn_" << "._" << -r;
616            else f << "t__[" << i << "+to__]._" << -r; 
617         }
618         else
619            f << "t__->kids[" << i << "]->u._" << r; 
620       }
621    |  THISSYNexp (r,_,in_rewrite):              
622       { if (in_rewrite)
623            f << "__";
624         else // in parser
625            f << "t__->u._" << r; 
626       }
627    |  COSTexp (i): { f << "t__->kids[" << i << "]->cost"; }
628    |  THISCOSTexp _: { f << "t__->cost"; }
629    |  CONSexp(c as 
630               ONEcons { name, ty = TYCONty(RECORDtycon(labels,_),tys) ... }, 
631               placement, e as RECORDexp lab_exps):  
632       {  // rearrange arguments to 
633          if (placement)
634          {  f << "new (" << placement << ") "; print_cons(f,c); }
635          else
636          {  f << mangle(name); }
638          f << '(';
639          {  for_each (LabExp, i, lab_exps) {
640                for_each (Id, j, labels) if (i.label == j) goto next;
641                error ("%Lillegal record label '%s' in expression: %s%e\n", 
642                       i.label,name,e);
643                next: ;
644             }
645          }
646          {  Bool comma = false;
647             Ids is; Tys ts;
648             for(is = labels, ts = tys; is; is = is->#2, ts = ts->#2) {
649                Id i = is->#1;
650                Bool found = false;
651                for_each (LabExp, j, lab_exps) {
652                   if (i == j.label) {
653                      if (found)
654                         error ("%Lduplicated label '%s' in expression: %s%e\n", 
655                                j.label,name,e);
656                      found = true;
657                      if (comma) f << ", "; comma = true;
658                      f << j.exp;
659                   } 
660                }
661                if (! found) {
662                   match (default_val(ts->#1)) 
663                   {  NOexp: { error ("%Lmissing label '%s' in expression: %s%e\n",
664                                       i, name, e); }
665                   |  def_e: { if (comma) f << ", "; comma = true; f << def_e; }
666                   }  
667                }
668              } 
669          }
670          f << ')';
671       }
672    |  CONSexp(ONEcons { name ... }, placement, RECORDexp _):
673       {  error("%Lconstructor '%s' doesn't take labeled arguments\n", name);
674       }
675    |  CONSexp(ONEcons { name, ty = NOty ... },#[], NOexp):
676       {  f << mangle(name); }
677    |  CONSexp(cons as ONEcons { name ... }, placement, e):
678       {  if (placement)
679          {  f << "new (" << placement << ") "; print_cons(f,cons); }
680          else
681          {  f << mangle(name); }
682          f << '(' << e << ')';
683       }
684    |  RECORDexp es:
685       {  f << "{ ";
686          for (LabExps l = es; l; l = l->#2) {
687             f << l->#1.label << " = " << l->#1.exp; 
688             if (l->#2) f << ", ";
689          } 
690          f << " }";
691       }
692    |  LISTexp (cons, nil, es, e) | pretty_print_exp:
693       {  f << open_of(nil);
694          for(Exps exp_list = es; exp_list; exp_list = exp_list->#2) 
695          {  f << exp_list->#1;
696             if (exp_list->#2) f << ", ";
697          }
698          if (e != NOexp)
699          {  f << " ... " << e; }
700          f << close_of(nil);
701       }
702    |  LISTexp (ONEcons { name = cons ...}, ONEcons { name = nil ...}, es, e):
703       {  int i = 0;
704          for(Exps exp_list = es; exp_list; exp_list = exp_list->#2) 
705          {  Exp exp = exp_list->#1;
706             f << mangle(cons) << '(' << exp;
707             if (exp_list->#2) f << ','; 
708             i++;
709          }
710          if (e != NOexp) f << ',' << e; 
711          else if (es == #[]) f << mangle(nil);
712          while (i-- > 0) f << ')';
713       }
714    |  LISTexp _: // skip
715    |  VECTORexp (ONEcons { name = vec ... }, es):
716       {  f << mangle(vec) << '(';
717          {  for(Exps exps = es; exps; exps = exps->#2) 
718             {  f << exps->#1;
719                if (exps->#2 != #[]) f << ',';
720             }
721          }
722          f << ')';
723       }
724    |  VECTORexp _: // skip
725    |  _:  { bug("operator << (std::ostream&, Exp);"); }
726    }
727    return f;
730 ///////////////////////////////////////////////////////////////////////////////
732 //  Method to print an inheritance type.
734 ///////////////////////////////////////////////////////////////////////////////
735 std::ostream& operator << (std::ostream& f, Inherit i)
736 {  if (i->qualifiers & QUALvirtual) f << "virtual ";
737    return f << i->scope << ' ' << i->super_class;
740 ///////////////////////////////////////////////////////////////////////////////
742 //  Method to print a class inheritance list.
744 ///////////////////////////////////////////////////////////////////////////////
745 std::ostream& operator << (std::ostream& f, Inherits i)
746 {  for ( ;i; i = i->#2) {
747       f << i->#1;
748       if (i->#2) f << ", ";
749    }
750    return f;
753 ///////////////////////////////////////////////////////////////////////////////
755 //  Method to print a cost expression
757 ///////////////////////////////////////////////////////////////////////////////
758 std::ostream& operator << (std::ostream& f, Cost c)
759 {  match (c)
760    {  NOcost:
761    |  EXPcost (e,_): { f << " \\ " << e; }
762    |  INTcost c:     { f << " \\ " << c; }
763    }
764    return f;
767 ///////////////////////////////////////////////////////////////////////////////
769 //  Method to print a qualified identifier.
771 ///////////////////////////////////////////////////////////////////////////////
772 std::ostream& operator << (std::ostream& f, QualId id)
773 {  match (id)
774    {  NESTEDid(ty, id):             { f << ty << "::" << id; }
775    |  SIMPLEid id | isalpha(id[0]): { f << id; }
776    |  SIMPLEid id:                  { f << "operator " << id; }
777    }
778    return f;
781 ///////////////////////////////////////////////////////////////////////////////
782 //  Method to print a pattern match rule.
783 ///////////////////////////////////////////////////////////////////////////////
784 std::ostream& operator << (std::ostream& f, MatchRule mr)
785 {  match (mr)
786    {  MATCHrule (non_terminal, pat, guard, cost, action): 
787       {  Bool save = pretty_print_exp;
788          pretty_print_exp = true;
789          if (non_terminal) f << non_terminal << " -> ";
790          f << pat;
791          if (guard != NOexp) f << " | " << guard;
792          f << cost << ": ...";
793          pretty_print_exp = save;
794       }
795    }
796    return f;
799 ///////////////////////////////////////////////////////////////////////////////
801 //  Method to pretty print a decision tree.
803 ///////////////////////////////////////////////////////////////////////////////
804 std::ostream& operator << (std::ostream& f, Match m)
805 {  match (m)
806    {  FAILmatch:              { f << '_'; }
807    |  DONTCAREmatch:          { f << '-'; }
808    |  BACKEDGEmatch (_,id,_): { f << '<' << id << '>'; }
809    |  SUCCESSmatch (r,_):     { f << r; }
810    |  GUARDmatch (e,yes,no):  { f << e << '(' << yes << ',' << no << ')'; }
811    |  SUCCESSESmatch (n,set,_): 
812       {  f << '{';
813          Bool comma = false;
814          for (int i = 0; i < n; i++)
815             if ((*set)[i]) {
816                if (comma) f << ", ";
817                f << i;
818                comma = true;
819             }
820          f << '}';
821       } 
822    |  COSTmatch (n,costs,set,_): 
823       {  f << '{';
824          Bool comma = false;
825          for (int i = 0; i < n; i++)
826             if ((*set)[i]) {
827                if (comma) f << ", ";
828                f << costs[i] << " = " << i;
829                comma = true;
830             }
831          f << '}';
832       } 
833    |  TREECOSTmatch (m,set,_): 
834       {  f << "TREE{" << *set << "} => " << m; } 
835    |  TREELABELmatch (m,ty,_,k): 
836       {  f << "LABEL{" << ty << "(" << k << ")} => " << m; } 
837    |  LITERALmatch(_,_,l as [REGEXPlit _],n,m,d):
838       {  f << "[\n"; 
839          for (int i = 0; i < n; i++) 
840          {  f << "   {" << i << "}" << l[i] << " => " << m[i] << ",\n"; 
841          }
842          f << d << ']';
843       }
844    |  LITERALmatch(_,_,l,n,m,d):
845       {  f << '['; 
846          for (int i = 0; i < n; i++) 
847             {  f << l[i] << ':' << m[i] << ", "; }
848          f << d << ']';
849       }
850    |  CONSmatch(_,_,_,TYCONty(DATATYPEtycon { id, qualifiers ... },_),n,m,d):
851       {  f << id << '['; 
852          for (int i = 0; i < n; i++) {
853             f << m[i];
854             if (i < n - 1) f << ", ";
855          }
856          if (qualifiers & QUALextensible) f << ", " << d;
857          f << ']';
858       }
859    |  RANGEmatch(_,_,lo,hi,y,n):
860       {  f << '[' << lo << ".." << hi << ": " << y << ", " << n << ']'; }
861    |  _:  { bug("operator << (std::ostream&, Match);"); }
862    }
863    return f;