2004-09-23 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / gmcs / gen-treedump.cs
1 // cs-treedump.cs: Dumps the parsed tree to standard output
2 //
3 // Author: Miguel de Icaza (miguel@gnu.org)
4 //
5 // Licensed under the terms of the GNU GPL
6 //
7 // (C) 2001 Ximian, Inc. (http://www.ximian.com)
8 //
9 // TODO:
10 //      Variable declarations
11 //      Fix precedence rules to lower the number of parenthesis.
12 //
13
14 using System;
15 using System.IO;
16 using System.Collections;
17 using CIR;
18
19 namespace Generator {
20         
21         public class TreeDump : CIR.ITreeDump {
22                 StreamWriter o;
23                 int indent;
24                 bool indented;
25                 bool tag_values;
26                 
27                 void space ()
28                 {
29                         if (!indented)
30                                 output (new String (' ', indent * 8));
31                         indented = true;
32                 }
33
34                 void output (string s)
35                 {
36                         Console.Write (s);
37                         //o.Write (s);
38                 }
39
40                 void newline ()
41                 {
42                         output ("\n");
43                         indented = false;
44                 }
45
46                 void output_newline (string s)
47                 {
48                         output (s);
49                         newline ();
50                 }
51                 
52                 void ioutput (string s)
53                 {
54                         space ();
55                         output (s);
56                 }
57
58                 string GetParameter (Parameter par)
59                 {
60                         Parameter.Modifier f = par.ModFlags;
61                         string mod = "";
62                         
63                         switch (f){
64                         case Parameter.Modifier.REF:
65                                 mod = "ref "; break;
66                         case Parameter.Modifier.OUT:
67                                 mod = "out "; break;
68                         case Parameter.Modifier.PARAMS:
69                                 mod = "params "; break;
70                         case Parameter.Modifier.NONE:
71                                 mod = ""; break;
72                         }
73                         return mod + par.Type + " " + par.Name;
74                 }
75
76                 string GetUnary (Unary u, int paren_level)
77                 {
78                         string e;
79                         bool left = true;
80                         string s = "0_ERROR>";
81                         int prec = 0;
82                         
83                         switch (u.Oper){
84                         case Unary.Operator.UnaryPlus:
85                                 prec = 10;
86                                 s = "+";
87                                 break;
88                                 
89                         case Unary.Operator.UnaryNegation:
90                                 prec = 10;
91                                 s = "-";
92                                 break;
93                                 
94                         case Unary.Operator.LogicalNot:
95                                 s = "!";
96                                 prec = 10;
97                                 break;
98                                 
99                         case Unary.Operator.OnesComplement:
100                                 prec = 10;
101                                 s = "~";
102                                 break;
103                                 
104                         case Unary.Operator.Indirection:
105                                 prec = 10;
106                                 s = "*";
107                                 break;
108                                 
109                         case Unary.Operator.AddressOf:
110                                 prec = 10;
111                                 s = "&";
112                                 break;
113                                 
114                         case Unary.Operator.PreIncrement:
115                                 prec = 11;
116                                 s = "++";
117                                 break;
118                                 
119                         case Unary.Operator.PreDecrement:
120                                 prec = 11;
121                                 s = "--";
122                                 break;
123                                 
124                         case Unary.Operator.PostDecrement:
125                                 left = false;
126                                 prec = 12;
127                                 s = "--";
128                                 break;
129                                 
130                         case Unary.Operator.PostIncrement:
131                                 s = "++";
132                                 prec = 12;
133                                 left = false;
134                                 break;
135                         }
136
137                         e = GetExpression (u.Expr, prec);
138                         if (left)
139                                 e = s + e;
140                         else
141                                 e = e + s;
142                         
143                         if (prec < paren_level)
144                                 return "(" + e + ")";
145                         else
146                                 return e;
147                 }
148
149                 string GetBinary (Binary b, int paren_level)
150                 {
151                         string l, r;
152                         string op = null;
153                         bool assoc_left = true;
154                         int prec = 0;
155                         
156                         switch (b.Oper){
157                                 case Binary.Operator.Multiply:
158                                         prec = 9;
159                                         op = "*"; break;
160
161                                 case Binary.Operator.Division:
162                                         prec = 9;
163                                         op = "/"; break;
164                                 
165                                 case Binary.Operator.Modulus:
166                                         prec = 9;
167                                         op = "%"; break;
168                                 
169                                 case Binary.Operator.Addition:
170                                         prec = 8;
171                                         op = "+"; break;
172                                 
173                                 case Binary.Operator.Subtraction:
174                                         prec = 8;
175                                         op = "-"; break;
176                                 
177                                 case Binary.Operator.LeftShift:
178                                         prec = 7;
179                                         op = "<<"; break;
180                                 
181                                 case Binary.Operator.RightShift:
182                                         prec = 7;
183                                         op = ">>"; break;
184                                 
185                                 case Binary.Operator.LessThan:
186                                         prec = 6;
187                                         op = "<"; break;
188                                 
189                                 case Binary.Operator.GreaterThan:
190                                         prec = 6;
191                                         op = ">"; break;
192                                 
193                                 case Binary.Operator.LessThanOrEqual:
194                                         prec = 6;
195                                         op = "<="; break;
196                                 
197                                 case Binary.Operator.GreaterThanOrEqual:
198                                         prec = 6;
199                                         op = ">="; break;
200                                 
201                                 case Binary.Operator.Equality:
202                                         prec = 5;
203                                         op = "=="; break;
204                                 
205                                 case Binary.Operator.Inequality:
206                                         prec = 5;
207                                         op = "!="; break;
208                                 
209                                 case Binary.Operator.BitwiseAnd:
210                                         prec = 4;
211                                         op = "&"; break;
212                                 
213                                 case Binary.Operator.BitwiseOr:
214                                         prec = 2;
215                                         op = "|"; break;
216                                 
217                                 case Binary.Operator.LogicalAnd:
218                                         prec = 1;
219                                         op = "&&"; break;
220                                 
221                                 case Binary.Operator.LogicalOr:
222                                         prec = 0;
223                                         op = "||"; break;
224                                 
225                                 case Binary.Operator.ExclusiveOr:
226                                         prec = 3;
227                                         op = "^"; break;
228                         }
229
230                         l = GetExpression (b.Left, prec - (assoc_left ? 0 : 1));
231                         r = GetExpression (b.Right, prec - (assoc_left ? 0 : 1));
232                         
233                         if (prec <= paren_level)
234                                 return "(" + l + " " + op + " " + r + ")";
235                         else
236                                 return l + " " + op + " " + r;
237                 }
238
239                 string GetCast (Cast c)
240                 {
241                         return "(" + c.TargetType + ") (" + GetExpression (c.Expr, 0) + ")";
242                 }
243
244                 string GetConditional (Conditional c)
245                 {
246                         return "(" + GetExpression (c.Expr, 0) + ") ? (" +
247                                 GetExpression (c.TrueExpr, 0) + ") : (" +
248                                 GetExpression (c.FalseExpr, 0) + ")";
249                 }
250
251                 string GetAssign (Assign a)
252                 {
253                         return GetExpression (a.Target, 0) + " = " + GetExpression (a.Source, 0);
254                 }
255
256                 string GetArguments (ArrayList args)
257                 {
258                         string r = "";
259                         
260                         if (args != null){
261                                 int top = args.Count;
262                                 
263                                 for (int i = 0; i < top; i++){
264                                         Argument arg = (Argument) args [i];
265                                                 
266                                         switch (arg.ArgType){
267                                                 case Argument.AType.Ref:
268                                                         r += "ref "; break;
269                                                 case Argument.AType.Out:
270                                                         r += "out "; break;
271                                         }
272                                         r += GetExpression (arg.Expr, 0);
273
274                                         if (i+1 != top)
275                                                 r += ", ";
276                                 }
277                         }
278
279                         return "(" + r + ")";
280                 }
281                 
282                 string GetInvocation (Invocation i)
283                 {
284                         return GetExpression (i.Expr, 0) + " " + GetArguments (i.Arguments);
285                 }
286
287                 string GetNew (New n)
288                 {
289                         return "new " + n.RequestedType + GetArguments (n.Arguments);
290                 }
291
292                 string GetTypeOf (TypeOf t)
293                 {
294                         return "typeof (" + t.QueriedType + ")";
295                 }
296
297                 string GetSizeOf (SizeOf t)
298                 {
299                         return "sizeof (" + t.QueriedType + ")";
300                 }
301
302                 string GetMemberAccess (MemberAccess m)
303                 {
304                         return GetExpression (m.Expr, 0) +
305                                 (tag_values ? "/* member access */ . " : ".") +
306                                 m.Identifier;
307                 }
308
309                 string GetSimpleName (SimpleName n)
310                 {
311                         string s = n.Name;
312                         
313                         if (s.StartsWith ("0_"))
314                                 return "id_" + s;
315                         else
316                                 return s;
317                 }
318
319                 string GetProbe (Probe p)
320                 {
321                         string s = GetExpression (p.Expr, 6);
322
323                         if (p.Oper == CIR.Probe.Operator.Is)
324                                 s += " is ";
325                         else if (p.Oper == CIR.Probe.Operator.As)
326                                 s += " as ";
327                         else
328                                 s += "UNHANDLED";
329
330                         s += p.ProbeType;
331
332                         return s;
333                 }
334
335                 string GetLocalVariableReference (LocalVariableReference l)
336                 {
337                         if (tag_values)
338                                 return "/* local var: */" + l.Name;
339                         else
340                                 return l.Name;
341                 }
342
343                 string GetParameterReference (ParameterReference r)
344                 {
345                         if (tag_values)
346                                 return "/* par: */ " + r.Name;
347                         else
348                                 return r.Name;
349                 }
350                 
351                 string GetExpression (Expression e, int paren_level)
352                 {
353                         if (e == null){
354                                 return "<NULL EXPRESSION>";
355                         }
356                         
357                         if (e is Unary)
358                                 return GetUnary ((Unary) e, paren_level);
359                         else if (e is Binary)
360                                 return GetBinary ((Binary) e, paren_level);
361                         else if (e is Cast)
362                                 return GetCast ((Cast) e);
363                         else if (e is Conditional)
364                                 return GetConditional ((Conditional) e);
365                         else if (e is SimpleName)
366                                 return GetSimpleName ((SimpleName)e);
367                         else if (e is LocalVariableReference)
368                                 return GetLocalVariableReference ((LocalVariableReference) e);
369                         else if (e is ParameterReference)
370                                 return GetParameterReference ((ParameterReference) e);
371                         else if (e is Assign)
372                                 return GetAssign ((Assign) e);
373                         else if (e is Literal)
374                                 return e.ToString ();
375                         else if (e is Invocation)
376                                 return GetInvocation ((Invocation) e);
377                         else if (e is New)
378                                 return GetNew ((New) e);
379                         else if (e is This)
380                                 return "this";
381                         else if (e is TypeOf)
382                                 return GetTypeOf ((TypeOf) e);
383                         else if (e is SizeOf)
384                                 return GetSizeOf ((SizeOf) e);
385                         else if (e is MemberAccess)
386                                 return GetMemberAccess ((MemberAccess) e);
387                         else if (e is Probe)
388                                 return GetProbe ((Probe) e);
389                         else
390                                 return "WARNING {" + e.ToString () + "} WARNING";
391                 }
392                 
393                 void GenerateParameters (Parameters pars)
394                 {
395                         Parameter [] pfixed;
396                         Parameter parray;
397
398                         pfixed = pars.FixedParameters;
399
400                         if (pfixed != null){
401                                 for (int i = 0; i < pfixed.Length; i++){
402                                         output (GetParameter (pfixed [i]));
403                                         if (i+1 != pfixed.Length)
404                                                 output (", ");
405                                 }
406                         }
407
408                         parray = pars.ArrayParameter;
409                         if (parray != null){
410                                 output (GetParameter (parray));
411                         }
412                 }
413
414                 void GenerateIf (If s)
415                 {
416                         bool do_indent;
417                         
418                         output ("if (" + GetExpression (s.Expr, 0) + ") ");
419                         do_indent = !(s.TrueStatement is Block);
420                         if (do_indent)
421                                 indent++;
422                         GenerateStatement (s.TrueStatement, true, false, false);
423                         if (do_indent)
424                                 indent--;
425                         if (s.FalseStatement != null){
426                                 ioutput ("else");
427                                 newline ();
428                                 GenerateStatement (s.FalseStatement, false, true, false);
429                         }
430                 }
431
432                 void GenerateDo (Do s)
433                 {
434                         output ("do"); newline ();
435                         indent++;
436                         GenerateStatement (s.EmbeddedStatement, false, false, false);
437                         indent--;
438                         output (" while (" + GetExpression (s.Expr, 0) + ");");
439                         newline ();
440                 }
441
442                 void GenerateWhile (While s)
443                 {
444                         output ("while (" + GetExpression (s.Expr, 0) + ")");
445                         GenerateStatement (s.Statement, true, true, false);
446                 }
447
448                 void GenerateFor (For s)
449                 {
450                         output ("for (");
451                         if (! (s.InitStatement == EmptyStatement.Value))
452                                 GenerateStatement (s.InitStatement, true, true, true);
453                         output ("; ");
454                         output (GetExpression (s.Test, 0));
455                         output ("; ");
456                         if (! (s.Increment == EmptyStatement.Value))
457                                 GenerateStatement (s.Increment, true, true, true);
458                         output (") ");
459                         GenerateStatement (s.Statement, true, true, false);
460                 }
461
462                 void GenerateReturn (Return s)
463                 {
464                         output ("return " +
465                                 (s.Expr != null ?
466                                  GetExpression (s.Expr, 0) : "" + ";") +
467                                 ";");
468                         newline ();
469                 }
470
471                 void GenerateGoto (Goto s)
472                 {
473                         output ("goto " + s.Target + ";");
474                         newline ();
475                 }
476
477                 void GenerateThrow (Throw s)
478                 {
479                 }
480
481                 void GenerateStatementExpression (StatementExpression s)
482                 {
483                         output (GetExpression (s.Expr, 0) + ";");
484                         newline ();
485                 }
486
487                 void GenerateSwitchLabels (ArrayList labels)
488                 {
489                         foreach (SwitchLabel sl in labels){
490                                 Expression lab = sl.Label;
491                                 
492                                 if (lab == null){
493                                         ioutput ("default:");
494                                         newline ();
495                                 } else {
496                                         ioutput ("case " + GetExpression (lab, 0) + ":");
497                                         newline ();
498                                 }
499                         }
500                 }
501                 
502                 void GenerateSwitch (Switch s)
503                 {
504                         output_newline ("switch (" + GetExpression (s.Expr, 0) + ")");
505                         foreach (SwitchSection ss in s.Sections){
506                                 GenerateSwitchLabels (ss.Labels);
507                                 GenerateBlock (ss.Block, false, false);
508                         }
509                 }
510                 
511                 void GenerateChecked (Checked c)
512                 {
513                         output ("checked ");
514                         GenerateBlock (c.Block, false, false);
515                 }
516
517                 void GenerateUnchecked (Unchecked c)
518                 {
519                         output ("unchecked ");
520                         GenerateBlock (c.Block, false, false);
521                 }
522
523                 void GenerateCatchClauses (ArrayList list)
524                 {
525                         foreach (Catch c in list){
526                                 space ();
527                                 output ("catch ");
528                                 
529                                 if (c.Type != null){
530                                         output ("(" + c.Type +
531                                                 (c.Name != null ? " " + c.Name : "") + ")");
532                                 } 
533                                 GenerateBlock (c.Block, false, false);
534                         }
535                 }
536
537                 void GenerateTry (Try t)
538                 {
539                         output ("try");
540                         GenerateBlock (t.Block, false, false);
541
542                         if (t.Specific != null){
543                                 GenerateCatchClauses (t.Specific);
544                         }
545
546                         if (t.General != null){
547                                 space ();
548                                 output ("catch");
549                                 GenerateBlock (t.Block, false, false);
550                         }
551
552                         if (t.Fini != null){
553                                 GenerateBlock (t.Fini, false, false);
554                         }
555                 }
556                 
557                 void GenerateStatement (Statement s, bool doPlacement, bool blockFlushesLine, bool embedded)
558                 {
559                         if (s == null){
560                                 output ("WARNING: got a null Statement");
561                                 newline ();
562                                 return;
563                         }
564
565                         if (doPlacement){
566                                 if (s is Block){
567                                         GenerateBlock ((Block) s, doPlacement, embedded);
568                                         return;
569                                 } else 
570                                         newline ();
571                         } 
572                                 
573                         space ();
574                         if (s is If)
575                                 GenerateIf ((If) s);
576                         else if (s is Do)
577                                 GenerateDo ((Do) s);
578                         else if (s is While)
579                                 GenerateWhile ((While) s);
580                         else if (s is For)
581                                 GenerateFor ((For) s);
582                         else if (s is Return)
583                                 GenerateReturn ((Return) s);
584                         else if (s is Goto)
585                                 GenerateGoto ((Goto) s);
586                         else if (s is Throw)
587                                 GenerateThrow ((Throw) s);
588                         else if (s is Break)
589                                 output_newline ("break;");
590                         else if (s is Continue)
591                                 output_newline ("continue;");
592                         else if (s == EmptyStatement.Value)
593                                 output_newline ("/* empty statement */;");
594                         else if (s is Block)
595                                 GenerateBlock ((Block) s, doPlacement, embedded);
596                         else if (s is StatementExpression)
597                                 GenerateStatementExpression ((StatementExpression) s);
598                         else if (s is Switch)
599                                 GenerateSwitch ((Switch) s);
600                         else if (s is Checked)
601                                 GenerateChecked ((Checked) s);
602                         else if (s is Unchecked)
603                                 GenerateUnchecked ((Unchecked) s);
604                         else if (s is Try)
605                                 GenerateTry ((Try) s);
606                         else {
607                                 System.Type t = s.GetType ();
608
609                                 output ("\n*****UNKNOWN Statement:" + t.ToString ());
610                         }
611                 }
612
613                 //
614                 // embedded is used only for things like the For thing
615                 // that has blocks but for display purposes we want to keep
616                 // without newlines.
617                 void GenerateBlock (Block b, bool doPlacement, bool embedded)
618                 {
619                         if (b.Label != null)
620                                 output (b.Label + ":");
621
622                         if (!b.Implicit){
623                                 if (!doPlacement)
624                                         space ();
625                         
626                                 output ("{");
627                                 if (!embedded)
628                                         newline ();
629                                 indent++;
630                         }
631
632                         if (b.Variables != null){
633                                 foreach (DictionaryEntry entry in b.Variables){
634                                         VariableInfo vi = (VariableInfo) entry.Value;
635                                         
636                                         space ();
637                                         output_newline (
638                                                 vi.Type + " " +
639                                                 (string) entry.Key + ";");
640                                 }
641                                 newline ();
642                         }
643                         
644                         foreach (Statement s in b.Statements){
645                                 GenerateStatement (s, false, true, false);
646                         }
647                         
648                         if (!b.Implicit){
649                                 indent--;
650                                 ioutput ("}");
651                                 if (!embedded)
652                                         newline ();
653                         }
654                 }
655                 
656                 void GenerateMethod (Method m)
657                 {
658                         ioutput (GetModifiers (m.ModFlags) +
659                                  m.ReturnType + " " +
660                                  m.Name + " (");
661                         GenerateParameters (m.Parameters);
662                         output_newline (")");
663                         
664
665                         GenerateBlock (m.Block, false, false);
666                         newline ();
667                 }
668
669                 void GenerateInterfaceMethod (InterfaceMethod imethod)
670                 {
671                         space ();
672                         output (imethod.IsNew ? "new " : "");
673                         output (imethod.ReturnType + " " + imethod.Name + " (");
674                         GenerateParameters (imethod.Parameters);
675                         output (");");
676                         newline ();
677                 }
678
679                 void GenerateInterfaceProperty (InterfaceProperty iprop)
680                 {
681                         space ();
682                         output (iprop.IsNew ? "new " : "");
683                         output (iprop.Type + " " + iprop.Name + " { ");
684                         if (iprop.HasGet) output ("get; ");
685                         if (iprop.HasSet) output ("set; ");
686                         output ("}");
687                         newline ();
688                 }
689                 
690                 void GenerateInterfaceEvent (InterfaceEvent ievent)
691                 {
692                         space ();
693                         output ((ievent.IsNew ? "new " : "") + "event ");
694                         output (ievent.Type + " " + ievent.Name + ";");
695                         newline ();
696                 }
697                 
698                 void GenerateInterfaceIndexer (InterfaceIndexer iindexer)
699                 {
700                         space ();
701                         output (iindexer.IsNew ? "new " : "");
702                         output (iindexer.Type + " this [");
703                         output (iindexer.Parameters + "] {");
704                         if (iindexer.HasGet) output ("get; ");
705                         if (iindexer.HasSet) output ("set; ");
706                         output ("}");
707                         newline ();
708                 }
709
710                 string GenIfaceBases (Interface iface)
711                 {
712                         return GenBases (iface.Bases);
713                 }
714                 
715                 void GenerateInterface (Interface iface)
716                 {
717                         ioutput (GetModifiers (iface.ModFlags) + "interface " +
718                                  ClassName (iface.Name) + GenIfaceBases (iface) + " {");
719                         newline ();
720                         indent++;
721                         
722                         if (iface.InterfaceMethods != null){
723                                 foreach (DictionaryEntry de in iface.InterfaceMethods){
724                                         InterfaceMethod method = (InterfaceMethod) de.Value;
725                                         GenerateInterfaceMethod (method);
726                                 }
727                         }
728
729                         if (iface.InterfaceProperties != null){
730                                 foreach (DictionaryEntry de in iface.InterfaceProperties){
731                                         InterfaceProperty iprop = (InterfaceProperty) de.Value;
732                                         GenerateInterfaceProperty (iprop);
733                                 }
734                         }
735
736                         if (iface.InterfaceEvents != null){
737                                 foreach (DictionaryEntry de in iface.InterfaceEvents){
738                                         InterfaceEvent ievent = (InterfaceEvent) de.Value;
739                                         GenerateInterfaceEvent (ievent);
740                                 }
741                         }
742
743                         if (iface.InterfaceIndexers != null){
744                                 foreach (DictionaryEntry de in iface.InterfaceIndexers){
745                                         InterfaceIndexer iindexer = (InterfaceIndexer) de.Value;
746                                         GenerateInterfaceIndexer (iindexer);
747                                 }
748                         }
749                         indent--;
750                         ioutput ("}");
751                         newline ();
752                         newline ();
753                 }
754
755                 void GenerateField (Field f)
756                 {
757                         space ();
758                         output (GetModifiers (f.ModFlags) + 
759                                 f.Type + " " + f.Name);
760                         if (f.Initializer != null){
761                                 if (f.Initializer is Expression)
762                                         output (" = " + GetExpression ((Expression) f.Initializer, 0));
763                                 else
764                                         output ("ADD SUPPORT FOR ARRAYS");
765                         }
766                         output (";");
767                         newline ();
768                 }
769
770                 void GenerateConstructor (Constructor c)
771                 {
772                         ConstructorInitializer init = c.Initializer;
773
774                         space ();
775                         output (GetModifiers (c.ModFlags) + c.Name + " (");
776                         GenerateParameters (c.Parameters);
777                         output (")");
778
779                         if (init != null){
780                                 if (init is ConstructorThisInitializer)
781                                         output (": this (");
782                                 else
783                                         output (": base (");
784                                 output (GetArguments (init.Arguments));
785                                 output (")");
786                         }
787                         newline ();
788                         GenerateBlock (c.Block, false, false);
789                 }
790
791                 void GenerateProperty (Property prop)
792                 {
793                         space ();
794                         output (GetModifiers (prop.ModFlags) + prop.Type +
795                                 " " + prop.Name + " {");
796                         newline ();
797                         indent++;
798                         if (prop.Get != null){
799                                 space ();
800                                 output ("get ");
801                                 GenerateBlock (prop.Get, false, false);
802                                 newline (); 
803                         }
804
805                         if (prop.Set != null){
806                                 space ();
807                                 output ("set ");
808                                 GenerateBlock (prop.Set, false, false);
809                         }
810                         indent--;
811                         space ();
812                         output ("}");
813                         newline ();
814                 }
815
816                 void GenerateEnum (CIR.Enum e)
817                 {
818                         space ();
819                         output ("enum " + e.Name + " {");
820                         newline ();
821
822                         indent++;
823                         foreach (string name in e.ValueNames){
824                                 Expression expr = e [name];
825
826                                 space ();
827
828                                 output (name);
829                                 if (expr != null)
830                                         output (" = " + GetExpression (expr, 0));
831
832                                 output (",");
833                                 newline ();
834                         }
835                         indent--;
836                         space ();
837                         output_newline ("}");
838                 }
839                 
840                 void GenerateTypeContainerData (TypeContainer tc)
841                 {
842                         if (tc.Constants != null){
843                                 foreach (Constant c in tc.Constants){
844                                         space ();
845
846                                         output ("const " + c.ConstantType + " " + c.Name + " = " +
847                                                 GetExpression (c.Expr, 0) + ";");
848                                         newline ();
849                                 }
850                                 newline ();
851                         }
852
853                         if (tc.Enums != null){
854                                 foreach (CIR.Enum e in tc.Enums)
855                                         GenerateEnum (e);
856                         }
857
858                         if (tc.Fields != null){
859                                 foreach (Field f in tc.Fields)
860                                         GenerateField (f);
861                                 newline ();
862                         }
863
864                         if (tc.Constructors != null){
865                                 foreach (Constructor c in tc.Constructors)
866                                         GenerateConstructor (c);
867
868                                 newline ();
869                                         
870                         }
871
872                         if (tc.Properties != null){
873                                 foreach (Property prop in tc.Properties)
874                                         GenerateProperty (prop);
875                         }
876                         
877                         GenerateFromTypes (tc);
878                         
879                         if (tc.Methods != null){
880                                 foreach (Method m in tc.Methods){
881                                         GenerateMethod (m);
882                                 }
883                         }
884                 }
885
886                 string GetModifiers (int mod_flags)
887                 {
888                         string s = "";
889
890                         for (int i = 1; i <= (int) CIR.Modifiers.TOP; i <<= 1){
891                                 if ((mod_flags & i) != 0)
892                                         s += Modifiers.Name (i) + " ";
893                         }
894
895                         return s;
896                 }
897
898                 string ClassName (string name)
899                 {
900                         return name;
901                         //return name.Substring (1 + name.LastIndexOf ('.'));
902                 }
903
904                 string GenBases (ArrayList bases)
905                 {
906                         if (bases == null)
907                                 return "";
908
909                         string res = ": ";
910                         int top = bases.Count;
911                         for (int i = 0; i < bases.Count; i++){
912                                 Type t = (Type) bases [i];
913
914                                 res += t.Name;
915                                 if (i + 1 != top)
916                                         res += ", ";
917                         }
918                         return res;
919                 }
920                 
921                 string GenClassBases (Class c)
922                 {
923                         return GenBases (c.Bases);
924                 }
925                 
926                 void GenerateFromClass (Class c)
927                 {
928                         ioutput (GetModifiers (c.ModFlags) + "class " + ClassName (c.Name) +
929                                  " " + GenClassBases (c) + " {");
930                         newline ();
931                         indent++;
932                         
933                         GenerateTypeContainerData (c);
934
935                         indent--;
936                         ioutput ("}");
937                         newline ();
938                         newline ();
939                 }
940
941                 void GenerateFromStruct (Struct s)
942                 {
943                         GenerateTypeContainerData (s);
944                 }
945                 
946                 void GenerateFromTypes (TypeContainer types)
947                 {
948                         if (types.Types == null)
949                                 return;
950                         
951                         foreach (DictionaryEntry de in types.Types){
952                                 TypeContainer type = (TypeContainer) de.Value;
953                                 
954                                 if (type is Class)
955                                         GenerateFromClass ((Class) type);
956                                 if (type is Struct)
957                                         GenerateFromStruct ((Struct) type);
958                                         
959                         }
960
961                         if (types.Interfaces != null){
962                                 foreach (DictionaryEntry de in types.Interfaces){
963                                         Interface iface = (Interface) de.Value;
964
965                                         GenerateInterface (iface);
966                                 }
967                         }
968                 }
969                 
970                 public int Dump (Tree tree, StreamWriter output)
971                 {
972                         this.o = output;
973
974                         indent = 0;
975                         GenerateFromTypes (tree.Types);
976
977                         return 0;
978                 }
979
980                 public void ParseOptions (string options)
981                 {
982                         if (options == "tag")
983                                 tag_values = true;
984                 }
985         }
986 }
987
988