2001-09-12 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / statement.cs
1 //
2 // statement.cs: Statement representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9
10 using System;
11 using System.Reflection;
12 using System.Reflection.Emit;
13
14 namespace CIR {
15
16         using System.Collections;
17         
18         public abstract class Statement {
19         }
20
21         public class EmptyStatement : Statement {
22         }
23         
24         public class If : Statement {
25                 Expression expr;
26                 Statement trueStatement;
27                 Statement falseStatement;
28                 
29                 public If (Expression expr, Statement trueStatement)
30                 {
31                         this.expr = expr;
32                         this.trueStatement = trueStatement;
33                 }
34
35                 public If (Expression expr,
36                            Statement trueStatement,
37                            Statement falseStatement)
38                 {
39                         this.expr = expr;
40                         this.trueStatement = trueStatement;
41                         this.falseStatement = falseStatement;
42                 }
43
44                 public Statement TrueStatement {
45                         get {
46                                 return trueStatement;
47                         }
48                 }
49
50                 public Statement FalseStatement {
51                         get {
52                                 return falseStatement;
53                         }
54                 }
55
56                 public Expression Expr {
57                         get {
58                                 return expr;
59                         }
60                 }
61         }
62
63         public class Do : Statement {
64                 Expression boolExpr;
65                 Statement statement;
66                 
67                 public Do (Statement statement, Expression boolExpr)
68                 {
69                         this.boolExpr = boolExpr;
70                         this.statement = statement;
71                 }
72
73                 public Statement EmbeddedStatement {
74                         get {
75                                 return statement;
76                         }
77                 }
78
79                 public Expression Expr {
80                         get {
81                                 return boolExpr;
82                         }
83                 }
84         }
85
86         public class While : Statement {
87                 Expression boolExpr;
88                 Statement statement;
89                 
90                 public While (Expression boolExpr, Statement statement)
91                 {
92                         this.boolExpr = boolExpr;
93                         this.statement = statement;
94                 }
95
96                 public Statement Statement {
97                         get {
98                                 return statement;
99                         }
100                 }
101
102                 public Expression Expr {
103                         get {
104                                 return boolExpr;
105                         }
106                 }
107         }
108
109         public class For : Statement {
110                 Statement initStatement;
111                 Expression test;
112                 Statement increment;
113                 Statement statement;
114                 
115                 public For (Statement initStatement,
116                             Expression test,
117                             Statement increment,
118                             Statement statement)
119                 {
120                         this.initStatement = initStatement;
121                         this.test = test;
122                         this.increment = increment;
123                         this.statement = statement;
124                 }
125
126                 public Statement InitStatement {
127                         get {
128                                 return initStatement;
129                         }
130                 }
131
132                 public Expression Test {
133                         get {
134                                 return test;
135                         }
136                 }
137                 
138                 public Statement Increment {
139                         get {
140                                 return increment;
141                         }
142                 }
143
144                 public Statement Statement {
145                         get {
146                                 return statement;
147                         }
148                 }
149
150         }
151         
152         public class StatementExpression : Statement {
153                 Expression expr;
154                 
155                 public StatementExpression (Expression expr)
156                 {
157                         this.expr = expr;
158                 }
159
160                 public Expression Expr {
161                         get {
162                                 return expr;
163                         }
164                 }
165         }
166
167         public class Return : Statement {
168                 Expression expr;
169                 
170                 public Return (Expression expr)
171                 {
172                         this.expr = expr;
173                 }
174
175                 public Expression Expr {
176                         get {
177                                 return expr;
178                         }
179                 }
180         }
181
182         public class Goto : Statement {
183                 string target;
184                 
185                 public Goto (string label)
186                 {
187                         target = label;
188                 }
189
190                 public string Target {
191                         get {
192                                 return target;
193                         }
194                 }
195         }
196
197         public class Throw : Statement {
198                 Expression expr;
199                 
200                 public Throw (Expression expr)
201                 {
202                         this.expr = expr;
203                 }
204         }
205
206         public class Break : Statement {
207                 public Break ()
208                 {
209                 }
210         }
211
212         public class Continue : Statement {
213                 public Continue ()
214                 {
215                 }
216         }
217         
218         public class VariableInfo {
219                 public readonly string Type;
220                 public LocalBuilder LocalBuilder;
221                 public Type VariableType;
222                 
223                 int idx;
224                 
225                 public VariableInfo (string type)
226                 {
227                         Type = type;
228                         LocalBuilder = null;
229                         idx = 0;
230                 }
231
232                 public int Idx {
233                         get {
234                                 return idx;
235                         }
236
237                         set {
238                                 idx = value;
239                         }
240                 }
241
242         }
243                 
244         // <summary>
245         //   Used for Label management
246         // </summary>
247         //
248         public class Block : Statement {
249                 public readonly Block  Parent;
250                 public readonly bool   Implicit;
251                 public readonly string Label;
252
253                 //
254                 // The statements in this block
255                 //
256                 StatementCollection statements;
257
258                 //
259                 // An array of Blocks
260                 //
261                 ArrayList children;
262                 
263                 //
264                 // Labels.  (label, block) pairs.
265                 //
266                 Hashtable labels;
267
268                 //
269                 // Keeps track of (name, type) pairs
270                 //
271                 Hashtable variables;
272
273                 //
274                 // Maps variable names to ILGenerator.LocalBuilders
275                 //
276                 Hashtable local_builders;
277
278                 bool used = false;
279
280                 public Block (Block parent)
281                 {
282                         if (parent != null)
283                                 parent.AddChild (this);
284                         
285                         this.Parent = parent;
286                         this.Implicit = false;
287                 }
288
289                 public Block (Block parent, bool implicit_block)
290                 {
291                         if (parent != null)
292                                 parent.AddChild (this);
293                         
294                         this.Parent = parent;
295                         this.Implicit = true;
296                 }
297
298                 public Block (Block parent, string labeled)
299                 {
300                         if (parent != null)
301                                 parent.AddChild (this);
302                         
303                         this.Parent = parent;
304                         this.Implicit = true;
305                         Label = labeled;
306                 }
307
308                 public void AddChild (Block b)
309                 {
310                         if (children == null)
311                                 children = new ArrayList ();
312                         
313                         children.Add (b);
314                 }
315
316                 // <summary>
317                 //   Adds a label to the current block. 
318                 // </summary>
319                 //
320                 // <returns>
321                 //   false if the name already exists in this block. true
322                 //   otherwise.
323                 // </returns>
324                 //
325                 public bool AddLabel (string name, Block block)
326                 {
327                         if (labels == null)
328                                 labels = new Hashtable ();
329                         if (labels.Contains (name))
330                                 return false;
331                         
332                         labels.Add (name, block);
333                         return true;
334                 }
335
336                 public bool AddVariable (string type, string name)
337                 {
338                         if (variables == null)
339                                 variables = new Hashtable ();
340
341                         if (GetVariableType (name) != null)
342                                 return false;
343
344                         VariableInfo vi = new VariableInfo (type);
345                         
346                         variables.Add (name, vi);
347                         return true;
348                 }
349
350                 public Hashtable Variables {
351                         get {
352                                 return variables;
353                         }
354                 }
355
356                 public VariableInfo GetVariableInfo (string name)
357                 {
358                         if (variables != null) {
359                                 object temp;
360                                 temp = variables [name];
361                                 return (VariableInfo) temp;
362                         }
363
364                         if (Parent != null){
365                                 return Parent.GetVariableInfo (name);
366                         }
367
368                         return null;
369                 }
370                 
371                 public string GetVariableType (string name)
372                 {
373                         VariableInfo vi = GetVariableInfo (name);
374
375                         if (vi != null)
376                                 return vi.Type;
377
378                         return null;
379                 }
380
381                 // <summary>
382                 //   True if the variable named @name has been defined
383                 //   in this block
384                 // </summary>
385                 public bool IsVariableDefined (string name)
386                 {
387                         return GetVariableType (name) != null;
388                 }
389
390                 // <summary>
391                 //   Use to fetch the statement associated with this label
392                 // </summary>
393                 public Statement this [string name] {
394                         get {
395                                 return (Statement) labels [name];
396                         }
397                 }
398
399                 // <returns>
400                 //   A list of labels that were not used within this block
401                 // </returns>
402                 public string [] GetUnreferenced ()
403                 {
404                         // FIXME: Implement me
405                         return null;
406                 }
407
408                 public StatementCollection Statements {
409                         get {
410                                 if (statements == null)
411                                         statements = new StatementCollection ();
412
413                                 return statements;
414                         }
415                 }
416
417                 public void AddStatement (Statement s)
418                 {
419                         if (statements == null)
420                                 statements = new StatementCollection ();
421
422                         statements.Add (s);
423                         used = true;
424                 }
425
426                 public bool Used {
427                         get {
428                                 return used;
429                         }
430                 }
431                 
432                 // <summary>
433                 //   Creates a compiler-internal identifier, this is
434                 //   used to create temporary variables that should not
435                 //   be seen by the application
436                 // </summary
437                 int internal_id_serial;
438                 public string MakeInternalID () {
439                         string ret = internal_id_serial.ToString ();
440
441                         internal_id_serial++;
442                         return "0_" + ret;
443                 }
444
445                 // <summary>
446                 //   Emits the variable declarations and labels.
447                 // </summary>
448                 //
449                 // tc: is our typecontainer (to resolve type references)
450                 // ig: is the code generator:
451                 // toplevel: the toplevel block.  This is used for checking 
452                 //           that no two labels with the same name are used.
453                 //
454                 public void EmitMeta (TypeContainer tc, ILGenerator ig, Block toplevel)
455                 {
456                         //
457                         // Process this block variables
458                         //
459                         if (variables != null){
460                                 local_builders = new Hashtable ();
461                                 int count = 0;
462                                 
463                                 foreach (DictionaryEntry de in variables){
464                                         string name = (string) de.Key;
465                                         VariableInfo vi = (VariableInfo) de.Value;
466                                         Type t;
467                                         
468                                         t = tc.LookupType (vi.Type, false);
469                                         if (t == null)
470                                                 continue;
471
472                                         vi.VariableType = t;
473                                         vi.LocalBuilder = ig.DeclareLocal (t);
474                                         vi.Idx = count++;
475                                 }
476                         }
477
478                         //
479                         // Now, handle the children
480                         //
481                         if (children != null){
482                                 foreach (Block b in children)
483                                         b.EmitMeta (tc, ig, toplevel);
484                         }
485                 }
486         }
487
488         public class SwitchLabel {
489                 Expression label;
490
491                 //
492                 // if expr == null, then it is the default case.
493                 //
494                 public SwitchLabel (Expression expr)
495                 {
496                         label = expr;
497                 }
498                 
499                 public Expression Label {
500                         get {
501                                 return label;
502                         }
503                 }
504         }
505
506         public class SwitchSection {
507                 // An array of SwitchLabels.
508                 ArrayList labels;
509                 Block block;
510                 
511                 public SwitchSection (ArrayList labels, Block block)
512                 {
513                         this.labels = labels;
514                         this.block = block;
515                 }
516
517                 public Block Block {
518                         get {
519                                 return block;
520                         }
521                 }
522
523                 public ArrayList Labels {
524                         get {
525                                 return labels;
526                         }
527                 }
528         }
529         
530         public class Switch : Statement {
531                 ArrayList sections;
532                 Expression expr;
533                 
534                 public Switch (Expression expr, ArrayList sections)
535                 {
536                         this.expr = expr;
537                         this.sections = sections;
538                 }
539
540                 public Expression Expr {
541                         get {
542                                 return expr;
543                         }
544                 }
545
546                 public ArrayList Sections {
547                         get {
548                                 return sections;
549                         }
550                 }
551         }
552
553         public class Lock : Statement {
554                 Expression expr;
555                 Statement stmt;
556                 
557                 public Lock (Expression expr, Statement stmt)
558                 {
559                         this.expr = expr;
560                         this.stmt = stmt;
561                 }
562
563                 public Statement Statement {
564                         get {
565                                 return stmt;
566                         }
567                 }
568
569                 public Expression Expr {
570                         get {
571                                 return expr;
572                         }
573                 }
574                 
575         }
576
577         public class Unchecked : Statement {
578                 Block b;
579                 
580                 public Unchecked (Block b)
581                 {
582                         this.b = b;
583                 }
584
585                 public Block Block {
586                         get {
587                                 return b;
588                         }
589                 }
590         }
591
592         public class Checked : Statement {
593                 Block b;
594                 
595                 public Checked (Block b)
596                 {
597                         this.b = b;
598                 }
599
600                 public Block Block {
601                         get {
602                                 return b;
603                         }
604                 }
605         }
606
607         public class Try : Statement {
608                 Block fini, block;
609                 ArrayList specific;
610                 Catch general;
611                 
612                 //
613                 // specific, general and fini might all be null.
614                 //
615                 public Try (Block block, ArrayList specific, Catch general, Block fini)
616                 {
617                         if (specific == null && general == null){
618                                 Console.WriteLine ("CIR.Try: Either specific or general have to be non-null");
619                         }
620                         
621                         this.block = block;
622                         this.specific = specific;
623                         this.general = general;
624                         this.fini = fini;
625                 }
626
627                 public Block Block {
628                         get {
629                                 return block;
630                         }
631                 }
632
633                 public ArrayList Specific {
634                         get {
635                                 return specific;
636                         }
637                 }
638
639                 public Catch General {
640                         get {
641                                 return general;
642                         }
643                 }
644
645                 public Block Fini {
646                         get {
647                                 return fini;
648                         }
649                 }
650         }
651         
652         public class Catch {
653                 string type;
654                 string name;
655                 Block block;
656                 
657                 public Catch (string type, string name, Block block)
658                 {
659                         this.type = type;
660                         this.name = name;
661                         this.block = block;
662                 }
663
664                 public Block Block {
665                         get {
666                                 return block;
667                         }
668                 }
669
670                 public string Name {
671                         get {
672                                 return name;
673                         }
674                 }
675
676                 public string Type {
677                         get {
678                                 return type;
679                         }
680                 }
681         }
682 }
683