Fix #354663
[mono.git] / mcs / mcs / statement.cs
index 2cac3e10c373881887ae4fd24110b129ecd2fa98..b260c27b6311becc535c765c3f5fd3a3041a9d33 100644 (file)
@@ -103,6 +103,12 @@ namespace Mono.CSharp {
                        return s;
                }
 
+               public virtual Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Report.Error (834, loc, "A lambda expression with statement body cannot be converted to an expresion tree");
+                       return null;
+               }
+
                public Statement PerformClone ()
                {
                        CloneContext clonectx = new CloneContext ();
@@ -1510,7 +1516,7 @@ namespace Mono.CSharp {
                //
                // Labels.  (label, block) pairs.
                //
-               Hashtable labels;
+               HybridDictionary labels;
 
                //
                // Keeps track of (name, type) pairs
@@ -1519,7 +1525,7 @@ namespace Mono.CSharp {
 
                //
                // Keeps track of constants
-               Hashtable constants;
+               HybridDictionary constants;
 
                //
                // Temporary variables.
@@ -1531,7 +1537,9 @@ namespace Mono.CSharp {
                //
                Block switch_block;
 
+               // TODO: merge with scope_initializers
                ExpressionStatement scope_init;
+               ArrayList scope_initializers;
 
                ArrayList anonymous_children;
 
@@ -1572,7 +1580,7 @@ namespace Mono.CSharp {
                        this.EndLocation = end;
                        this.loc = start;
                        this_id = id++;
-                       statements = new ArrayList (1);
+                       statements = new ArrayList (4);
                }
 
                public Block CreateSwitchBlock (Location start)
@@ -1669,7 +1677,7 @@ namespace Mono.CSharp {
                        Toplevel.CheckError158 (name, target.loc);
 
                        if (labels == null)
-                               labels = new Hashtable ();
+                               labels = new HybridDictionary();
 
                        labels.Add (name, target);
                        return true;
@@ -1844,7 +1852,7 @@ namespace Mono.CSharp {
                                return false;
                        
                        if (constants == null)
-                               constants = new Hashtable ();
+                               constants = new HybridDictionary();
 
                        constants.Add (name, value);
 
@@ -1900,6 +1908,18 @@ namespace Mono.CSharp {
                        }
                        return null;
                }
+
+               //
+               // It should be used by expressions which require to
+               // register a statement during resolve process.
+               //
+               public void AddScopeStatement (StatementExpression s)
+               {
+                       if (scope_initializers == null)
+                               scope_initializers = new ArrayList ();
+
+                       scope_initializers.Add (s);
+               }
                
                public void AddStatement (Statement s)
                {
@@ -2275,6 +2295,11 @@ namespace Mono.CSharp {
                        ec.Mark (StartLocation, true);
                        if (scope_init != null)
                                scope_init.EmitStatement (ec);
+                       if (scope_initializers != null) {
+                               foreach (StatementExpression s in scope_initializers)
+                                       s.Emit (ec);
+                       }
+
                        DoEmit (ec);
                        ec.Mark (EndLocation, true); 
 
@@ -2350,7 +2375,7 @@ namespace Mono.CSharp {
                        this.Explicit = this;
                }
 
-               Hashtable known_variables;
+               HybridDictionary known_variables;
 
                // <summary>
                //   Marks a variable with name @name as being used in this or a child block.
@@ -2360,7 +2385,7 @@ namespace Mono.CSharp {
                internal void AddKnownVariable (string name, IKnownVariable info)
                {
                        if (known_variables == null)
-                               known_variables = new Hashtable ();
+                               known_variables = new HybridDictionary();
 
                        known_variables [name] = info;
 
@@ -2607,6 +2632,11 @@ namespace Mono.CSharp {
                        return root_scope;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return ((Statement) statements [0]).CreateExpressionTree (ec);
+               }
+
                public void CreateIteratorHost (RootScopeInfo root)
                {
                        Report.Debug (64, "CREATE ITERATOR HOST", this, root, Parent, root_scope);
@@ -2767,6 +2797,10 @@ namespace Mono.CSharp {
 
                public override void EmitMeta (EmitContext ec)
                {
+                       // Avoid declaring an IL variable for this_variable since it is not accessed
+                       // from the generated IL
+                       if (this_variable != null)
+                               Variables.Remove ("this");
                        base.EmitMeta (ec);
                        parameters.ResolveVariable (this);
                }
@@ -4731,10 +4765,22 @@ namespace Mono.CSharp {
                {
                        Using target = (Using) t;
 
-                       if (expression_or_block is Expression)
+                       if (expression_or_block is Expression) {
                                target.expression_or_block = ((Expression) expression_or_block).Clone (clonectx);
-                       else
-                               target.expression_or_block = ((Statement) expression_or_block).Clone (clonectx);
+                       } else {
+                               DictionaryEntry de = (DictionaryEntry) expression_or_block;
+                               ArrayList var_list = (ArrayList) de.Value;
+                               ArrayList target_var_list = new ArrayList (var_list.Count);
+
+                               foreach (DictionaryEntry de_variable in var_list)
+                                       target_var_list.Add (new DictionaryEntry (
+                                               ((Expression) de_variable.Key).Clone (clonectx),
+                                               ((Expression) de_variable.Value).Clone (clonectx)));
+
+                               target.expression_or_block = new DictionaryEntry (
+                                       ((Expression) de.Key).Clone (clonectx),
+                                       target_var_list);
+                       }
                        
                        target.Statement = Statement.Clone (clonectx);
                }