2 // statement.cs: Statement representation for the IL tree.
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2001 Ximian, Inc.
11 using System.Reflection;
12 using System.Reflection.Emit;
16 using System.Collections;
18 public abstract class Statement {
21 public class EmptyStatement : Statement {
24 public class If : Statement {
26 Statement trueStatement;
27 Statement falseStatement;
29 public If (Expression expr, Statement trueStatement)
32 this.trueStatement = trueStatement;
35 public If (Expression expr,
36 Statement trueStatement,
37 Statement falseStatement)
40 this.trueStatement = trueStatement;
41 this.falseStatement = falseStatement;
44 public Statement TrueStatement {
50 public Statement FalseStatement {
52 return falseStatement;
56 public Expression Expr {
63 public class Do : Statement {
67 public Do (Statement statement, Expression boolExpr)
69 this.boolExpr = boolExpr;
70 this.statement = statement;
73 public Statement EmbeddedStatement {
79 public Expression Expr {
86 public class While : Statement {
90 public While (Expression boolExpr, Statement statement)
92 this.boolExpr = boolExpr;
93 this.statement = statement;
96 public Statement Statement {
102 public Expression Expr {
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;
115 public For (Statement initStatement,
120 InitStatement = initStatement;
122 Increment = increment;
123 Statement = statement;
127 public class StatementExpression : Statement {
128 ExpressionStatement expr;
130 public StatementExpression (ExpressionStatement expr)
135 public ExpressionStatement Expr {
142 public class Return : Statement {
143 public readonly Expression Expr;
145 public Return (Expression expr)
151 public class Goto : Statement {
154 public Goto (string label)
159 public string Target {
166 public class Throw : Statement {
169 public Throw (Expression expr)
175 public class Break : Statement {
181 public class Continue : Statement {
187 public class VariableInfo {
188 public readonly string Type;
189 public LocalBuilder LocalBuilder;
190 public Type VariableType;
191 public readonly Location Location;
195 public bool Assigned;
197 public VariableInfo (string type, Location l)
208 throw new Exception ("Unassigned idx for variable");
221 // Used for Label management
224 public class Block : Statement {
225 public readonly Block Parent;
226 public readonly bool Implicit;
227 public readonly string Label;
230 // The statements in this block
232 StatementCollection statements;
235 // An array of Blocks
240 // Labels. (label, block) pairs.
245 // Keeps track of (name, type) pairs
250 // Maps variable names to ILGenerator.LocalBuilders
252 Hashtable local_builders;
256 public Block (Block parent)
259 parent.AddChild (this);
261 this.Parent = parent;
262 this.Implicit = false;
265 public Block (Block parent, bool implicit_block)
268 parent.AddChild (this);
270 this.Parent = parent;
271 this.Implicit = true;
274 public Block (Block parent, string labeled)
277 parent.AddChild (this);
279 this.Parent = parent;
280 this.Implicit = true;
284 public void AddChild (Block b)
286 if (children == null)
287 children = new ArrayList ();
293 // Adds a label to the current block.
297 // false if the name already exists in this block. true
301 public bool AddLabel (string name, Block block)
304 labels = new Hashtable ();
305 if (labels.Contains (name))
308 labels.Add (name, block);
312 public bool AddVariable (string type, string name, Location l)
314 if (variables == null)
315 variables = new Hashtable ();
317 if (GetVariableType (name) != null)
320 VariableInfo vi = new VariableInfo (type, l);
322 variables.Add (name, vi);
326 public Hashtable Variables {
332 public VariableInfo GetVariableInfo (string name)
334 if (variables != null) {
336 temp = variables [name];
339 return (VariableInfo) temp;
343 return Parent.GetVariableInfo (name);
349 public string GetVariableType (string name)
351 VariableInfo vi = GetVariableInfo (name);
360 // True if the variable named @name has been defined
363 public bool IsVariableDefined (string name)
365 return GetVariableType (name) != null;
369 // Use to fetch the statement associated with this label
371 public Statement this [string name] {
373 return (Statement) labels [name];
378 // A list of labels that were not used within this block
380 public string [] GetUnreferenced ()
382 // FIXME: Implement me
386 public StatementCollection Statements {
388 if (statements == null)
389 statements = new StatementCollection ();
395 public void AddStatement (Statement s)
397 if (statements == null)
398 statements = new StatementCollection ();
411 // Creates a compiler-internal identifier, this is
412 // used to create temporary variables that should not
413 // be seen by the application
415 int internal_id_serial;
416 public string MakeInternalID () {
417 string ret = internal_id_serial.ToString ();
419 internal_id_serial++;
424 // Emits the variable declarations and labels.
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.
432 public void EmitMeta (TypeContainer tc, ILGenerator ig, Block toplevel, int count)
435 // Process this block variables
437 if (variables != null){
438 local_builders = new Hashtable ();
440 foreach (DictionaryEntry de in variables){
441 string name = (string) de.Key;
442 VariableInfo vi = (VariableInfo) de.Value;
445 t = tc.LookupType (vi.Type, false);
450 vi.LocalBuilder = ig.DeclareLocal (t);
456 // Now, handle the children
458 if (children != null){
459 foreach (Block b in children)
460 b.EmitMeta (tc, ig, toplevel, count);
464 public void UsageWarning ()
468 if (variables != null){
469 foreach (DictionaryEntry de in variables){
470 VariableInfo vi = (VariableInfo) de.Value;
475 name = (string) de.Key;
479 219, vi.Location, "The variable `" + name +
480 "' is assigned but its value is never used");
483 168, vi.Location, "The variable `" +
485 "' is declared but never used");
490 if (children != null)
491 foreach (Block b in children)
496 public class SwitchLabel {
500 // if expr == null, then it is the default case.
502 public SwitchLabel (Expression expr)
507 public Expression Label {
514 public class SwitchSection {
515 // An array of SwitchLabels.
519 public SwitchSection (ArrayList labels, Block block)
521 this.labels = labels;
531 public ArrayList Labels {
538 public class Switch : Statement {
542 public Switch (Expression expr, ArrayList sections)
545 this.sections = sections;
548 public Expression Expr {
554 public ArrayList Sections {
561 public class Lock : Statement {
565 public Lock (Expression expr, Statement stmt)
571 public Statement Statement {
577 public Expression Expr {
585 public class Unchecked : Statement {
588 public Unchecked (Block b)
600 public class Checked : Statement {
603 public Checked (Block b)
615 public class Try : Statement {
621 // specific, general and fini might all be null.
623 public Try (Block block, ArrayList specific, Catch general, Block fini)
625 if (specific == null && general == null){
626 Console.WriteLine ("CIR.Try: Either specific or general have to be non-null");
630 this.specific = specific;
631 this.general = general;
641 public ArrayList Specific {
647 public Catch General {
665 public Catch (string type, string name, Block block)
691 public class Foreach : Statement {
692 public readonly string Type;
693 public readonly string Identifier;
694 public readonly Expression Expr;
695 public readonly Statement Statement;
697 public Foreach (string type, string identifier, Expression expr, Statement stmt)
700 Identifier = identifier;