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