2006-08-13 Miguel de Icaza <miguel@novell.com>
[mono.git] / mcs / mbas / statement.cs
index 01e371829faf64608275a55ecde9adb833e0df39..0914861a26983cae60906917d5bd93e3f00365eb 100644 (file)
@@ -72,8 +72,8 @@ namespace Mono.MonoBASIC {
                ///    Encapsulates the emission of a boolean test and jumping to a
                ///    destination.
                ///
-               ///    This will emit the bool expression in `bool_expr' and if
-               ///    `target_is_for_true' is true, then the code will generate a 
+               ///    This will emit the bool expression in 'bool_expr' and if
+               ///    'target_is_for_true' is true, then the code will generate a 
                ///    brtrue to the target.   Otherwise a brfalse. 
                /// </remarks>
                public static void EmitBoolExpression (EmitContext ec, Expression bool_expr,
@@ -431,8 +431,8 @@ namespace Mono.MonoBASIC {
                                ig.Emit (OpCodes.Br, ec.LoopBegin);
                                        
                                //
-                               // Inform that we are infinite (ie, `we return'), only
-                               // if we do not `break' inside the code.
+                               // Inform that we are infinite (ie, 'we return'), only
+                               // if we do not 'break' inside the code.
                                //
                                ret = may_return == false;
                                ig.MarkLabel (ec.LoopEnd);
@@ -812,6 +812,7 @@ namespace Mono.MonoBASIC {
                
                public Return (Expression expr, Location l)
                {
+                       expr = Parser.SetValueRequiredFlag (expr);
                        Expr = expr;
                        loc = l;
                }
@@ -829,8 +830,10 @@ namespace Mono.MonoBASIC {
                        if (ec.CurrentBranching.InTryBlock ())
                                ec.CurrentBranching.AddFinallyVector (vector);
 
-                       vector.Returns = FlowReturns.ALWAYS;
-                       vector.Breaks = FlowReturns.ALWAYS;
+                       if (! ec.InTry && ! ec.InCatch) {
+                               vector.Returns = FlowReturns.ALWAYS;
+                               vector.Breaks = FlowReturns.ALWAYS;
+                       }
                        return true;
                }
                
@@ -848,7 +851,7 @@ namespace Mono.MonoBASIC {
                                }
                        } else {
                                if (Expr == null){
-                                       Report.Error (126, loc, "An object of type `" +
+                                       Report.Error (126, loc, "An object of type '" +
                                                      TypeManager.MonoBASIC_Name (ec.ReturnType) + "' is " +
                                                      "expected for the return statement");
                                        return true;
@@ -888,10 +891,11 @@ namespace Mono.MonoBASIC {
                public override bool Resolve (EmitContext ec)
                {
                        label = block.LookupLabel (target);
+
                        if (label == null){
                                Report.Error (
                                        30132, loc,
-                                       "No such label `" + target + "' in this scope");
+                                       "No such label '" + target + "' in this scope");
                                return false;
                        }
 
@@ -899,8 +903,8 @@ namespace Mono.MonoBASIC {
                        if (!label.IsDefined)
                                label.AddUsageVector (ec.CurrentBranching.CurrentUsageVector);
 
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
-
+                        ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       label.AddReference ();
                        return true;
                }
                
@@ -920,7 +924,10 @@ namespace Mono.MonoBASIC {
                protected override bool DoEmit (EmitContext ec)
                {
                        Label l = label.LabelTarget (ec);
-                       ec.ig.Emit (OpCodes.Br, l);
+                        if (ec.InTry || ec.InCatch)
+                               ec.ig.Emit (OpCodes.Leave, l);
+                       else 
+                               ec.ig.Emit (OpCodes.Br, l);
                        
                        return false;
                }
@@ -940,12 +947,19 @@ namespace Mono.MonoBASIC {
                        this.label_name = label_name;
                        this.Location = l;
                }
+               
+               public string LabelName {
+                       get {
+                               return label_name;
+                       }
+               }
 
                public Label LabelTarget (EmitContext ec)
                {
-                       if (defined)
+                       if (defined) 
                                return label;
                        label = ec.ig.DefineLabel ();
+
                        defined = true;
 
                        return label;
@@ -969,12 +983,14 @@ namespace Mono.MonoBASIC {
                                vectors = new ArrayList ();
 
                        vectors.Add (vector.Clone ());
+
                }
 
                public override bool Resolve (EmitContext ec)
                {
-                       if (vectors != null)
+                       if (vectors != null) {
                                ec.CurrentBranching.CurrentUsageVector.MergeJumpOrigins (vectors);
+                       }
                        else {
                                ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.NEVER;
                                ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.NEVER;
@@ -982,6 +998,7 @@ namespace Mono.MonoBASIC {
 
                        referenced = true;
 
+
                        return true;
                }
 
@@ -992,11 +1009,15 @@ namespace Mono.MonoBASIC {
 
                        return false;
                }
+               public void AddReference ()
+                {
+                        referenced = true;
+                }
        }
        
 
        /// <summary>
-       ///   `goto default' statement
+       ///   'goto default' statement
        /// </summary>
        public class GotoDefault : Statement {
                
@@ -1028,7 +1049,7 @@ namespace Mono.MonoBASIC {
        }
 
        /// <summary>
-       ///   `goto case' statement
+       ///   'goto case' statement
        /// </summary>
        public class GotoCase : Statement {
                Expression expr;
@@ -1268,14 +1289,15 @@ namespace Mono.MonoBASIC {
                                }
                        
                                if (ec.InTry || ec.InCatch) {
-                                       if (!ec.HasReturnLabel) {
-                                               ec.ReturnLabel = ec.ig.DefineLabel ();
-                                               ec.HasReturnLabel = true;
-                                       }
-                                       ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
+                                       if (ec.HasExitLabel)
+                                               ec.ig.Emit (OpCodes.Leave, ec.ExitLabel);
                                } else {
-                                       ec.ig.Emit (OpCodes.Ldloc_0);
-                                       ec.ig.Emit (OpCodes.Ret);
+                                       if(type == ExitType.SUB) {   
+                                                ec.ig.Emit (OpCodes.Ret);
+                                        } else {
+                                               ec.ig.Emit (OpCodes.Ldloc_0);
+                                               ec.ig.Emit (OpCodes.Ret);
+                                       }
 
                                }
 
@@ -1360,7 +1382,8 @@ namespace Mono.MonoBASIC {
        //   current one.
        // </summary>
        public class MyBitVector {
-               public readonly int Count;
+               private int count;
+               public int Count { get { return count; } }
                public readonly MyBitVector InheritsFrom;
 
                bool is_dirty;
@@ -1373,7 +1396,7 @@ namespace Mono.MonoBASIC {
                public MyBitVector (MyBitVector InheritsFrom, int Count)
                {
                        this.InheritsFrom = InheritsFrom;
-                       this.Count = Count;
+                       this.count = Count;
                }
 
                // <summary>
@@ -1392,12 +1415,12 @@ namespace Mono.MonoBASIC {
                }
 
                // <summary>
-               //   Get/set bit `index' in the bit vector.
+               //   Get/set bit 'index' in the bit vector.
                // </summary>
                public bool this [int index]
                {
                        get {
-                               if (index > Count)
+                               if (index > count)
                                        throw new ArgumentOutOfRangeException ();
 
                                // We're doing a "copy-on-write" strategy here; as long
@@ -1418,7 +1441,7 @@ namespace Mono.MonoBASIC {
                        }
 
                        set {
-                               if (index > Count)
+                               if (index > count)
                                        throw new ArgumentOutOfRangeException ();
 
                                // Only copy the vector if we're actually modifying it.
@@ -1442,7 +1465,7 @@ namespace Mono.MonoBASIC {
                }
 
                // <summary>
-               //   Performs an `or' operation on the bit vector.  The `new_vector' may have a
+               //   Performs an 'or' operation on the bit vector.  The 'new_vector' may have a
                //   different size than the current one.
                // </summary>
                public void Or (MyBitVector new_vector)
@@ -1462,7 +1485,7 @@ namespace Mono.MonoBASIC {
                }
 
                // <summary>
-               //   Perfonrms an `and' operation on the bit vector.  The `new_vector' may have
+               //   Perfonrms an 'and' operation on the bit vector.  The 'new_vector' may have
                //   a different size than the current one.
                // </summary>
                public void And (MyBitVector new_vector)
@@ -1497,6 +1520,18 @@ namespace Mono.MonoBASIC {
 
                        return retval;
                }
+               
+               public void ExpandBy(int howMany)
+               {
+                       if (howMany < 1)
+                               throw new ArgumentException("howMany");
+                       initialize_vector();
+                       count = vector.Count + howMany;
+                       BitArray newVector = new BitArray(count, false);
+                       for (int i = 0; i < vector.Count; i++)
+                                       newVector [i] = vector [i];
+                       vector = newVector;
+               }
 
                BitArray Vector {
                        get {
@@ -1625,7 +1660,7 @@ namespace Mono.MonoBASIC {
                int id;
 
                // <summary>
-               //   Performs an `And' operation on the FlowReturns status
+               //   Performs an 'And' operation on the FlowReturns status
                //   (for instance, a block only returns ALWAYS if all its siblings
                //   always return).
                // </summary>
@@ -1682,6 +1717,12 @@ namespace Mono.MonoBASIC {
                        //   The number of locals in this block.
                        // </summary>
                        public readonly int CountLocals;
+                       
+                       // <summary>
+                       //   The number of locals in this block added after starting usage track.
+                       // </summary>
+                       public int ExtraLocals  { get { return locals.Count - CountLocals; } } 
+
 
                        // <summary>
                        //   If not null, then we inherit our state from this vector and do a
@@ -1730,6 +1771,11 @@ namespace Mono.MonoBASIC {
                                : this (parent, parent.CountParameters, parent.CountLocals)
                        { }
 
+                       public void AddExtraLocals(int howMany)
+                       {
+                               locals.ExpandBy(howMany);
+                       }
+                       
                        // <summary>
                        //   This does a deep copy of the usage vector.
                        // </summary>
@@ -1747,7 +1793,7 @@ namespace Mono.MonoBASIC {
                        }
 
                        // 
-                       // State of parameter `number'.
+                       // State of parameter 'number'.
                        //
                        public bool this [int number]
                        {
@@ -1771,8 +1817,8 @@ namespace Mono.MonoBASIC {
                        }
 
                        //
-                       // State of the local variable `vi'.
-                       // If the local variable is a struct, use a non-zero `field_idx'
+                       // State of the local variable 'vi'.
+                       // If the local variable is a struct, use a non-zero 'field_idx'
                        // to check an individual field in it.
                        //
                        public bool this [VariableInfo vi, int field_idx]
@@ -1879,7 +1925,7 @@ namespace Mono.MonoBASIC {
                                        if (!child.is_finally) {
                                                if (child.Breaks != FlowReturns.UNREACHABLE) {
                                                        // If Returns is already set, perform an
-                                                       // `And' operation on it, otherwise just set just.
+                                                       // 'And' operation on it, otherwise just set just.
                                                        if (!new_returns_set) {
                                                                new_returns = child.Returns;
                                                                new_returns_set = true;
@@ -1889,7 +1935,7 @@ namespace Mono.MonoBASIC {
                                                }
 
                                                // If Breaks is already set, perform an
-                                               // `And' operation on it, otherwise just set just.
+                                               // 'And' operation on it, otherwise just set just.
                                                if (!new_breaks_set) {
                                                        new_breaks = child.Breaks;
                                                        new_breaks_set = true;
@@ -1922,7 +1968,7 @@ namespace Mono.MonoBASIC {
                                        //    6   Console.WriteLine (a);
                                        //
                                        // The if block in lines 3-4 always returns, so we must not look
-                                       // at the initialization of `a' in line 4 - thus it'll still be
+                                       // at the initialization of 'a' in line 4 - thus it'll still be
                                        // uninitialized in line 6.
                                        //
                                        // On the other hand, the following is allowed:
@@ -1934,7 +1980,7 @@ namespace Mono.MonoBASIC {
                                        //    5      return;
                                        //    6   Console.WriteLine (a);
                                        //
-                                       // Here, `a' is initialized in line 3 and we must not look at
+                                       // Here, 'a' is initialized in line 3 and we must not look at
                                        // line 5 since it always returns.
                                        // 
                                        if (child.is_finally) {
@@ -1961,7 +2007,7 @@ namespace Mono.MonoBASIC {
                                                        new_locals.Or (child.locals);
                                                }
 
-                                               // An `out' parameter must be assigned in all branches which do
+                                               // An 'out' parameter must be assigned in all branches which do
                                                // not always throw an exception.
                                                if (parameters != null) {
                                                        if (child.Breaks != FlowReturns.EXCEPTION) {
@@ -2051,11 +2097,11 @@ namespace Mono.MonoBASIC {
 
                        // <summary>
                        //   Tells control flow analysis that the current code position may be reached with
-                       //   a forward jump from any of the origins listed in `origin_vectors' which is a
+                       //   a forward jump from any of the origins listed in 'origin_vectors' which is a
                        //   list of UsageVectors.
                        //
                        //   This is used when resolving forward gotos - in the following example, the
-                       //   variable `a' is uninitialized in line 8 becase this line may be reached via
+                       //   variable 'a' is uninitialized in line 8 becase this line may be reached via
                        //   the goto in line 4:
                        //
                        //      1     int a;
@@ -2112,7 +2158,7 @@ namespace Mono.MonoBASIC {
                                Report.Debug (1, "MERGING FINALLY ORIGIN DONE", this);
                        }
                        // <summary>
-                       //   Performs an `or' operation on the locals and the parameters.
+                       //   Performs an 'or' operation on the locals and the parameters.
                        // </summary>
                        public void Or (UsageVector new_vector)
                        {
@@ -2122,7 +2168,7 @@ namespace Mono.MonoBASIC {
                        }
 
                        // <summary>
-                       //   Performs an `and' operation on the locals.
+                       //   Performs an 'and' operation on the locals.
                        // </summary>
                        public void AndLocals (UsageVector new_vector)
                        {
@@ -2186,7 +2232,7 @@ namespace Mono.MonoBASIC {
                }
 
                // <summary>
-               //   Creates a new flow branching for `block'.
+               //   Creates a new flow branching for 'block'.
                //   This is used from Block.Resolve to create the top-level branching of
                //   the block.
                // </summary>
@@ -2204,7 +2250,7 @@ namespace Mono.MonoBASIC {
                        num_params = 0;
 
                        for (int i = 0; i < count; i++) {
-                               Parameter.Modifier mod = param_info.ParameterModifier (i);
+                               //Parameter.Modifier mod = param_info.ParameterModifier (i);
 
                        //      if ((mod & Parameter.Modifier.OUT) == 0)
                        //              continue;
@@ -2223,8 +2269,8 @@ namespace Mono.MonoBASIC {
                }
 
                // <summary>
-               //   Creates a new flow branching which is contained in `parent'.
-               //   You should only pass non-null for the `block' argument if this block
+               //   Creates a new flow branching which is contained in 'parent'.
+               //   You should only pass non-null for the 'block' argument if this block
                //   introduces any new variables - in this case, we need to create a new
                //   usage vector with a different size than our parent's one.
                // </summary>
@@ -2282,7 +2328,7 @@ namespace Mono.MonoBASIC {
                }
 
                // <summary>
-               //   Creates a sibling for a `finally' block.
+               //   Creates a sibling for a 'finally' block.
                // </summary>
                public void CreateSiblingForFinally ()
                {
@@ -2470,7 +2516,7 @@ namespace Mono.MonoBASIC {
 
                        case FlowBranchingType.LOOP_BLOCK:
                                // The code following a loop is reachable unless the loop always
-                               // returns or it's an infinite loop without any `break's in it.
+                               // returns or it's an infinite loop without any 'break's in it.
                                reachable = !CurrentUsageVector.AlwaysReturns &&
                                        (CurrentUsageVector.Breaks != FlowReturns.UNREACHABLE);
                                break;
@@ -2632,16 +2678,24 @@ namespace Mono.MonoBASIC {
                public Expression Type;
                public LocalBuilder LocalBuilder;
                public Type VariableType;
+               public string Alias;
+               FieldBase FieldAlias;
                public readonly string Name;
                public readonly Location Location;
                public readonly int Block;
-
+               
                public int Number;
                
                public bool Used;
                public bool Assigned;
                public bool ReadOnly;
                
+               public VariableInfo (Expression type, string name, int block, Location l, string Alias)
+                       : this (type, name, block, l)
+               {
+                       this.Alias = Alias;
+               }
+               
                public VariableInfo (Expression type, string name, int block, Location l)
                {
                        Type = type;
@@ -2651,6 +2705,12 @@ namespace Mono.MonoBASIC {
                        Location = l;
                }
 
+               public VariableInfo (TypeContainer tc, int block, Location l, string Alias)
+                       : this (tc, block, l)
+               {
+                       this.Alias = Alias;
+               }
+               
                public VariableInfo (TypeContainer tc, int block, Location l)
                {
                        VariableType = tc.TypeBuilder;
@@ -2674,7 +2734,7 @@ namespace Mono.MonoBASIC {
 
                        MyStructInfo struct_info = StructInfo;
                        if ((struct_info == null) || (struct_info.HasNonPublicFields && (Name != null))) {
-                               Report.Error (165, loc, "Use of unassigned local variable `" + Name + "'");
+                               Report.Error (165, loc, "Use of unassigned local variable '" + Name + "'");
                                ec.CurrentBranching.SetVariableAssigned (this);
                                return false;
                        }
@@ -2685,7 +2745,7 @@ namespace Mono.MonoBASIC {
                                if (!ec.CurrentBranching.IsVariableAssigned (this, i+1)) {
                                        if (Name != null) {
                                                Report.Error (165, loc,
-                                                             "Use of unassigned local variable `" +
+                                                             "Use of unassigned local variable '" +
                                                              Name + "'");
                                                ec.CurrentBranching.SetVariableAssigned (this);
                                                return false;
@@ -2693,7 +2753,7 @@ namespace Mono.MonoBASIC {
 
                                        FieldInfo field = struct_info [i];
                                        Report.Error (171, loc,
-                                                     "Field `" + TypeManager.MonoBASIC_Name (VariableType) +
+                                                     "Field '" + TypeManager.MonoBASIC_Name (VariableType) +
                                                      "." + field.Name + "' must be fully initialized " +
                                                      "before control leaves the constructor");
                                        return false;
@@ -2715,7 +2775,7 @@ namespace Mono.MonoBASIC {
 
                        if (!ec.CurrentBranching.IsVariableAssigned (this, field_idx)) {
                                Report.Error (170, loc,
-                                             "Use of possibly unassigned field `" + name + "'");
+                                             "Use of possibly unassigned field '" + name + "'");
                                ec.CurrentBranching.SetVariableAssigned (this, field_idx);
                                return false;
                        }
@@ -2735,6 +2795,24 @@ namespace Mono.MonoBASIC {
                                ec.CurrentBranching.SetVariableAssigned (this, StructInfo [name]);
                }
 
+               public FieldBase GetFieldAlias (EmitContext ec)  {
+                       if ( this.FieldAlias != null )
+                               return this.FieldAlias;
+                       else
+                       {
+                               ArrayList fields = ec.TypeContainer.Fields;
+                                for (int i = 0; i < fields.Count; i++) 
+                               {
+                                       if (((Field) fields[i]).Name == this.Alias) 
+                                       {
+                                               this.FieldAlias = (Field) fields[i];
+                                               break;
+                                       }
+                               }
+                               return this.FieldAlias;
+                       }
+               }
+               
                public bool Resolve (DeclSpace decl)
                {
                        if (struct_info != null)
@@ -2761,712 +2839,49 @@ namespace Mono.MonoBASIC {
                        return "VariableInfo (" + Number + "," + Type + "," + Location + ")";
                }
        }
-               
-       /// <summary>
-       ///   Block represents a C# block.
-       /// </summary>
-       ///
-       /// <remarks>
-       ///   This class is used in a number of places: either to represent
-       ///   explicit blocks that the programmer places or implicit blocks.
-       ///
-       ///   Implicit blocks are used as labels or to introduce variable
-       ///   declarations.
-       /// </remarks>
-       public class Block : Statement {
-               public readonly Block     Parent;
-               public readonly bool      Implicit;
-               public readonly Location  StartLocation;
-               public Location           EndLocation;
-
-               //
-               // The statements in this block
-               //
-               public ArrayList statements;
 
-               //
-               // An array of Blocks.  We keep track of children just
-               // to generate the local variable declarations.
-               //
-               // Statements and child statements are handled through the
-               // statements.
-               //
-               ArrayList children;
                
-               //
-               // Labels.  (label, block) pairs.
-               //
-               CaseInsensitiveHashtable labels;
-
-               //
-               // Keeps track of (name, type) pairs
-               //
-               CaseInsensitiveHashtable variables;
-
-               //
-               // Keeps track of constants
-               CaseInsensitiveHashtable constants;
-
-               //
-               // Maps variable names to ILGenerator.LocalBuilders
-               //
-               CaseInsensitiveHashtable local_builders;
-
-               // to hold names of variables required for late binding
-               public const string lateBindingArgs = "1_LBArgs";
-               public const string lateBindingArgNames = "1_LBArgsNames";
-               public const string lateBindingCopyBack = "1_LBCopyBack";
-
-               bool isLateBindingRequired = false;
-
-               bool used = false;
-
-               static int id;
-
-               int this_id;
-               
-               public Block (Block parent)
-                       : this (parent, false, Location.Null, Location.Null)
-               { }
-
-               public Block (Block parent, bool implicit_block)
-                       : this (parent, implicit_block, Location.Null, Location.Null)
-               { }
-
-               public Block (Block parent, bool implicit_block, Parameters parameters)
-                       : this (parent, implicit_block, parameters, Location.Null, Location.Null)
-               { }
-
-               public Block (Block parent, Location start, Location end)
-                       : this (parent, false, start, end)
-               { }
-
-               public Block (Block parent, Parameters parameters, Location start, Location end)
-                       : this (parent, false, parameters, start, end)
-               { }
-
-               public Block (Block parent, bool implicit_block, Location start, Location end)
-                       : this (parent, implicit_block, Parameters.EmptyReadOnlyParameters,
-                               start, end)
-               { }
-
-               public Block (Block parent, bool implicit_block, Parameters parameters,
-                             Location start, Location end)
-               {
-                       if (parent != null)
-                               parent.AddChild (this);
-                       else {
-                               // Top block
-                               // Add variables that may be required for late binding
-                               variables = new CaseInsensitiveHashtable ();
-                               ArrayList rank_specifier = new ArrayList ();
-                               ArrayList element = new ArrayList ();
-                               element.Add (new EmptyExpression ());
-                               rank_specifier.Add (element);
-                               Expression e = Mono.MonoBASIC.Parser.DecomposeQI ("System.Object[]", start);
-                               AddVariable (e, Block.lateBindingArgs, null, start);
-                               e = Mono.MonoBASIC.Parser.DecomposeQI ("System.String[]", start);
-                               AddVariable (e, Block.lateBindingArgNames, null, start);
-                               e = Mono.MonoBASIC.Parser.DecomposeQI ("System.Boolean[]", start);
-                               AddVariable (e, Block.lateBindingCopyBack, null, start);
-                       }
-                       
-                       this.Parent = parent;
-                       this.Implicit = implicit_block;
-                       this.parameters = parameters;
-                       this.StartLocation = start;
-                       this.EndLocation = end;
-                       this.loc = start;
-                       this_id = id++;
-                       statements = new ArrayList ();
-               }
-
-               public bool IsLateBindingRequired {
-                       get {
-                               return isLateBindingRequired;
-                       }
-                       set {
-                               isLateBindingRequired = value;
-                       }
-               }
-
-               public int ID {
-                       get {
-                               return this_id;
-                       }
-               }
-
-               void AddChild (Block b)
-               {
-                       if (children == null)
-                               children = new ArrayList ();
-                       
-                       children.Add (b);
-               }
-
-               public void SetEndLocation (Location loc)
-               {
-                       EndLocation = loc;
-               }
-
-               /// <summary>
-               ///   Adds a label to the current block. 
-               /// </summary>
-               ///
-               /// <returns>
-               ///   false if the name already exists in this block. true
-               ///   otherwise.
-               /// </returns>
-               ///
-               public bool AddLabel (string name, LabeledStatement target)
-               {
-                       if (labels == null)
-                               labels = new CaseInsensitiveHashtable ();
-                       if (labels.Contains (name))
-                               return false;
-                       
-                       labels.Add (name, target);
-                       return true;
-               }
-
-               public LabeledStatement LookupLabel (string name)
-               {
-                       if (labels != null){
-                               if (labels.Contains (name))
-                                       return ((LabeledStatement) labels [name]);
-                       }
-
-                       if (Parent != null)
-                               return Parent.LookupLabel (name);
-
-                       return null;
-               }
-
-               VariableInfo this_variable = null;
-
-               // <summary>
-               //   Returns the "this" instance variable of this block.
-               //   See AddThisVariable() for more information.
-               // </summary>
-               public VariableInfo ThisVariable {
-                       get {
-                               if (this_variable != null)
-                                       return this_variable;
-                               else if (Parent != null)
-                                       return Parent.ThisVariable;
-                               else
-                                       return null;
-                       }
-               }
-
-               Hashtable child_variable_names;
-
-               // <summary>
-               //   Marks a variable with name @name as being used in a child block.
-               //   If a variable name has been used in a child block, it's illegal to
-               //   declare a variable with the same name in the current block.
-               // </summary>
-               public void AddChildVariableName (string name)
-               {
-                       if (child_variable_names == null)
-                               child_variable_names = new CaseInsensitiveHashtable ();
-
-                       if (!child_variable_names.Contains (name))
-                               child_variable_names.Add (name, true);
-               }
-
-               // <summary>
-               //   Marks all variables from block @block and all its children as being
-               //   used in a child block.
-               // </summary>
-               public void AddChildVariableNames (Block block)
-               {
-                       if (block.Variables != null) {
-                               foreach (string name in block.Variables.Keys)
-                                       AddChildVariableName (name);
-                       }
-
-                       foreach (Block child in block.children) {
-                               if (child.Variables != null) {
-                                       foreach (string name in child.Variables.Keys)
-                                               AddChildVariableName (name);
-                               }
-                       }
-               }
-
-               // <summary>
-               //   Checks whether a variable name has already been used in a child block.
-               // </summary>
-               public bool IsVariableNameUsedInChildBlock (string name)
-               {
-                       if (child_variable_names == null)
-                               return false;
-
-                       return child_variable_names.Contains (name);
-               }
-
-               // <summary>
-               //   This is used by non-static `struct' constructors which do not have an
-               //   initializer - in this case, the constructor must initialize all of the
-               //   struct's fields.  To do this, we add a "this" variable and use the flow
-               //   analysis code to ensure that it's been fully initialized before control
-               //   leaves the constructor.
-               // </summary>
-               public VariableInfo AddThisVariable (TypeContainer tc, Location l)
-               {
-                       if (this_variable != null)
-                               return this_variable;
-
-                       this_variable = new VariableInfo (tc, ID, l);
-
-                       if (variables == null)
-                               variables = new CaseInsensitiveHashtable ();
-                       variables.Add ("this", this_variable);
-
-                       return this_variable;
-               }
-
-               public VariableInfo AddVariable (Expression type, string name, Parameters pars, Location l)
-               {
-                       if (variables == null)
-                               variables = new CaseInsensitiveHashtable ();
-
-                       VariableInfo vi = GetVariableInfo (name);
-                       if (vi != null) {
-                               if (vi.Block != ID)
-                                       Report.Error (30616, l, "A local variable named `" + name + "' " +
-                                                     "cannot be declared in this scope since it would " +
-                                                     "give a different meaning to `" + name + "', which " +
-                                                     "is already used in a `parent or current' scope to " +
-                                                     "denote something else");
-                               else
-                                       Report.Error (30290, l, "A local variable `" + name + "' is already " +
-                                                     "defined in this scope");
-                               return null;
-                       }
-
-                       if (IsVariableNameUsedInChildBlock (name)) {
-                               Report.Error (136, l, "A local variable named `" + name + "' " +
-                                             "cannot be declared in this scope since it would " +
-                                             "give a different meaning to `" + name + "', which " +
-                                             "is already used in a `child' scope to denote something " +
-                                             "else");
-                               return null;
-                       }
-
-                       if (pars != null) {
-                               int idx = 0;
-                               Parameter p = pars.GetParameterByName (name, out idx);
-                               if (p != null) {
-                                       Report.Error (30616, l, "A local variable named `" + name + "' " +
-                                                     "cannot be declared in this scope since it would " +
-                                                     "give a different meaning to `" + name + "', which " +
-                                                     "is already used in a `parent or current' scope to " +
-                                                     "denote something else");
-                                       return null;
-                               }
-                       }
-                       
-                       vi = new VariableInfo (type, name, ID, l);
-
-                       variables.Add (name, vi);
-
-                       if (variables_initialized)
-                               throw new Exception ();
-
-                       // Console.WriteLine ("Adding {0} to {1}", name, ID);
-                       return vi;
-               }
-
-               public bool AddConstant (Expression type, string name, Expression value, Parameters pars, Location l)
-               {
-                       if (AddVariable (type, name, pars, l) == null)
-                               return false;
-                       
-                       if (constants == null)
-                               constants = new CaseInsensitiveHashtable ();
-
-                       constants.Add (name, value);
-                       return true;
-               }
-
-               public Hashtable Variables {
-                       get {
-                               return variables;
-                       }
-               }
-
-               public VariableInfo GetVariableInfo (string name)
-               {
-                       if (variables != null) {
-                               object temp;
-                               temp = variables [name];
-
-                               if (temp != null){
-                                       return (VariableInfo) temp;
-                               }
-                       }
-
-                       if (Parent != null)
-                               return Parent.GetVariableInfo (name);
-
-                       return null;
-               }
-               
-               public Expression GetVariableType (string name)
-               {
-                       VariableInfo vi = GetVariableInfo (name);
-
-                       if (vi != null)
-                               return vi.Type;
-
-                       return null;
-               }
-
-               public Expression GetConstantExpression (string name)
-               {
-                       if (constants != null) {
-                               object temp;
-                               temp = constants [name];
-                               
-                               if (temp != null)
-                                       return (Expression) temp;
-                       }
-                       
-                       if (Parent != null)
-                               return Parent.GetConstantExpression (name);
-
-                       return null;
-               }
-               
-               /// <summary>
-               ///   True if the variable named @name has been defined
-               ///   in this block
-               /// </summary>
-               public bool IsVariableDefined (string name)
-               {
-                       // Console.WriteLine ("Looking up {0} in {1}", name, ID);
-                       if (variables != null) {
-                               if (variables.Contains (name))
-                                       return true;
-                       }
-                       
-                       if (Parent != null)
-                               return Parent.IsVariableDefined (name);
-
-                       return false;
-               }
-
-               /// <summary>
-               ///   True if the variable named @name is a constant
-               ///  </summary>
-               public bool IsConstant (string name)
-               {
-                       Expression e = null;
-                       
-                       e = GetConstantExpression (name);
-                       
-                       return e != null;
-               }
-               
-               /// <summary>
-               ///   Use to fetch the statement associated with this label
-               /// </summary>
-               public Statement this [string name] {
-                       get {
-                               return (Statement) labels [name];
-                       }
-               }
-
-               Parameters parameters = null;
-               public Parameters Parameters {
-                       get {
-                               if (Parent != null)
-                                       return Parent.Parameters;
-
-                               return parameters;
-                       }
-               }
-
-               /// <returns>
-               ///   A list of labels that were not used within this block
-               /// </returns>
-               public string [] GetUnreferenced ()
-               {
-                       // FIXME: Implement me
-                       return null;
-               }
-
-               public void AddStatement (Statement s)
-               {
-                       statements.Add (s);
-                       used = true;
-               }
-
-               public bool Used {
-                       get {
-                               return used;
-                       }
-               }
-
-               public void Use ()
-               {
-                       used = true;
-               }
-
-               bool variables_initialized = false;
-               int count_variables = 0, first_variable = 0;
-
-               void UpdateVariableInfo (EmitContext ec)
-               {
-                       DeclSpace ds = ec.DeclSpace;
-
-                       first_variable = 0;
-
-                       if (Parent != null)
-                               first_variable += Parent.CountVariables;
-
-                       count_variables = first_variable;
-                       if (variables != null) {
-                               foreach (VariableInfo vi in variables.Values) {
-                                       if (!vi.Resolve (ds)) {
-                                               vi.Number = -1;
-                                               continue;
-                                       }
-
-                                       vi.Number = ++count_variables;
-
-                                       if (vi.StructInfo != null)
-                                               count_variables += vi.StructInfo.Count;
-                               }
-                       }
-
-                       variables_initialized = true;
-               }
-
-               //
-               // <returns>
-               //   The number of local variables in this block
-               // </returns>
-               public int CountVariables
-               {
-                       get {
-                               if (!variables_initialized)
-                                       throw new Exception ();
-
-                               return count_variables;
-                       }
-               }
-
-               /// <summary>
-               ///   Emits the variable declarations and labels.
-               /// </summary>
-               /// <remarks>
-               ///   tc: is our typecontainer (to resolve type references)
-               ///   ig: is the code generator:
-               ///   toplevel: the toplevel block.  This is used for checking 
-               ///             that no two labels with the same name are used.
-               /// </remarks>
-               public void EmitMeta (EmitContext ec, Block toplevel)
-               {
-                       //DeclSpace ds = ec.DeclSpace;
-                       ILGenerator ig = ec.ig;
-
-                       if (!variables_initialized)
-                               UpdateVariableInfo (ec);
-
-                       //
-                       // Process this block variables
-                       //
-                       if (variables != null){
-                               local_builders = new CaseInsensitiveHashtable ();
-                               
-                               foreach (DictionaryEntry de in variables){
-                                       string name = (string) de.Key;
-                                       /*
-                                       if (!isLateBindingRequired) {
-                                               if (name.Equals (Block.lateBindingArgs) || 
-                                                   name.Equals (Block.lateBindingArgNames) ||
-                                                   name.Equals (Block.lateBindingCopyBack))
-                                                       continue;
-                                       }
-                                       */
-                                       VariableInfo vi = (VariableInfo) de.Value;
-
-                                       if (vi.VariableType == null)
-                                               continue;
-
-                                       vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
-
-                                       if (CodeGen.SymbolWriter != null)
-                                               vi.LocalBuilder.SetLocalSymInfo (name);
-
-                                       if (constants == null)
-                                               continue;
-
-                                       Expression cv = (Expression) constants [name];
-                                       if (cv == null)
-                                               continue;
-
-                                       Expression e = cv.Resolve (ec);
-                                       if (e == null)
-                                               continue;
-
-                                       if (!(e is Constant)){
-                                               Report.Error (133, vi.Location,
-                                                             "The expression being assigned to `" +
-                                                             name + "' must be constant (" + e + ")");
-                                               continue;
-                                       }
-
-                                       constants.Remove (name);
-                                       constants.Add (name, e);
-                               }
-                       }
-
-                       //
-                       // Now, handle the children
-                       //
-                       if (children != null){
-                               foreach (Block b in children)
-                                       b.EmitMeta (ec, toplevel);
-                       }
-               }
-
-               public void UsageWarning ()
-               {
-                       string name;
-                       
-                       if (variables != null){
-                               foreach (DictionaryEntry de in variables){
-                                       VariableInfo vi = (VariableInfo) de.Value;
-                                       
-                                       if (vi.Used)
-                                               continue;
-                                       
-                                       name = (string) de.Key;
-                                               
-                                       if (vi.Assigned){
-                                               Report.Warning (
-                                                       219, vi.Location, "The variable `" + name +
-                                                       "' is assigned but its value is never used");
-                                       } else {
-                                               Report.Warning (
-                                                       168, vi.Location, "The variable `" +
-                                                       name +
-                                                       "' is declared but never used");
-                                       } 
-                               }
-                       }
-
-                       if (children != null)
-                               foreach (Block b in children)
-                                       b.UsageWarning ();
-               }
-
-               bool has_ret = false;
-
-               public override bool Resolve (EmitContext ec)
-               {
-                       Block prev_block = ec.CurrentBlock;
-                       bool ok = true;
-
-                       ec.CurrentBlock = this;
-
-                       if (!variables_initialized)
-                               UpdateVariableInfo (ec);
-
-                       ec.StartFlowBranching (this);
-
-                       Report.Debug (1, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
-
-                       ArrayList new_statements = new ArrayList ();
-                       bool unreachable = false, warning_shown = false;
-
-                       foreach (Statement s in statements){
-                               if (unreachable && !(s is LabeledStatement)) {
-                                       if (!warning_shown && !(s is EmptyStatement)) {
-                                               warning_shown = true;
-                                               Warning_DeadCodeFound (s.loc);
-                                       }
-                                       continue;
-                               }
-
-                               if (s.Resolve (ec) == false) {
-                                       ok = false;
-                                       continue;
-                               }
-
-                               if (s is LabeledStatement)
-                                       unreachable = false;
-                               else
-                                       unreachable = ! ec.CurrentBranching.IsReachable ();
-
-                               new_statements.Add (s);
-                       }
-
-                       statements = new_statements;
-
-                       Report.Debug (1, "RESOLVE BLOCK DONE", StartLocation, ec.CurrentBranching);
-
-                       FlowReturns returns = ec.EndFlowBranching ();
-                       ec.CurrentBlock = prev_block;
-
-                       // If we're a non-static `struct' constructor which doesn't have an
-                       // initializer, then we must initialize all of the struct's fields.
-                       if ((this_variable != null) && (returns != FlowReturns.EXCEPTION) &&
-                           !this_variable.IsAssigned (ec, loc))
-                               ok = false;
-
-                       if ((labels != null) && (RootContext.WarningLevel >= 2)) {
-                               foreach (LabeledStatement label in labels.Values)
-                                       if (!label.HasBeenReferenced)
-                                               Report.Warning (164, label.Location,
-                                                               "This label has not been referenced");
-                       }
-
-                       if ((returns == FlowReturns.ALWAYS) ||
-                           (returns == FlowReturns.EXCEPTION) ||
-                           (returns == FlowReturns.UNREACHABLE))
-                               has_ret = true;
-
-                       return ok;
-               }
-               
-               protected override bool DoEmit (EmitContext ec)
-               {
-                       Block prev_block = ec.CurrentBlock;
-
-                       ec.CurrentBlock = this;
-
-                       ec.Mark (StartLocation);
-                       foreach (Statement s in statements)
-                               s.Emit (ec);
-                               
-                       ec.Mark (EndLocation); 
-                       
-                       ec.CurrentBlock = prev_block;
-                       return has_ret;
-               }
-       }
-
        public class StatementSequence : Expression {
                Block stmtBlock;
                ArrayList args, originalArgs;
                Expression expr;
                bool isRetValRequired;
                bool isLeftHandSide;
+               bool isIndexerAccess;
+               string memberName;
+               Expression type_expr;
+               bool is_resolved = false;
 
                public StatementSequence (Block parent, Location loc, Expression expr) 
                        : this (parent, loc, expr, null)
                { }
 
+               public StatementSequence (Block parent, Location loc, Expression expr, string name, 
+                                         Expression type_expr, ArrayList a, bool isRetValRequired,
+                                         bool isLeftHandSide) 
+                       : this (parent, loc, expr, a)
+               {
+                       this.memberName = name;
+                       this.type_expr = type_expr;
+                       this.isRetValRequired = isRetValRequired;
+                       this.isLeftHandSide = isLeftHandSide;
+               }
+
                public StatementSequence (Block parent, Location loc, Expression expr, ArrayList a,
                                          bool isRetValRequired, bool isLeftHandSide) 
                        : this (parent, loc, expr, a)
                {
                        this.isRetValRequired = isRetValRequired;
                        this.isLeftHandSide = isLeftHandSide;
+                       if (expr is MemberAccess) {
+                               this.expr = ((MemberAccess)expr).Expr;
+                               this.memberName = ((MemberAccess)expr).Identifier;
+                               this.isIndexerAccess = false;
+                       } else if (expr is IndexerAccess) {
+                               this.expr = ((IndexerAccess) expr).Instance;
+                               this.memberName = "";
+                               this.isIndexerAccess = true;
+                       }
                }
 
                public StatementSequence (Block parent, Location loc, Expression expr, ArrayList a) 
@@ -3485,6 +2900,8 @@ namespace Mono.MonoBASIC {
                        stmtBlock.IsLateBindingRequired = true;
                        this.loc = loc;
                        this.isRetValRequired = this.isLeftHandSide = false;
+                       this.memberName = "";
+                       this.type_expr = null;
                }
 
                public ArrayList Arguments {
@@ -3510,10 +2927,13 @@ namespace Mono.MonoBASIC {
                
                public override Expression DoResolve (EmitContext ec)
                {
+                       if (is_resolved)
+                               return this;
                        if (!stmtBlock.Resolve (ec))
                                return null;
                        eclass = ExprClass.Value;
                        type = TypeManager.object_type;
+                       is_resolved = true;
                        return this;
                }
 
@@ -3578,20 +2998,12 @@ namespace Mono.MonoBASIC {
                                stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) assign_stmt, loc));
                        }
 
-                       Expression tempExpr = expr;
-                       string memName = "";
-                       bool isIndexerAccess = true;
-                       if (expr is MemberAccess) {
-                               tempExpr = ((MemberAccess)expr).Expr;
-                               memName = ((MemberAccess)expr).Identifier;
-                               isIndexerAccess = false;
-                       } else if (expr is IndexerAccess) {
-                               tempExpr = ((IndexerAccess) expr).Instance;
-                       }
+                       //string memName = "";
+                       //bool isIndexerAccess = true;
 
                        ArrayList invocationArgs = new ArrayList ();
-                       if (isIndexerAccess) {
-                               invocationArgs.Add (new Argument (tempExpr, Argument.AType.Expression));
+                       if (isIndexerAccess || memberName == "") {
+                               invocationArgs.Add (new Argument (expr, Argument.AType.Expression));
                                invocationArgs.Add (new Argument (v1, Argument.AType.Expression));
                                invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
                                Expression tmp = null;
@@ -3604,9 +3016,16 @@ namespace Mono.MonoBASIC {
                                stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) invStmt, loc));
                                return;
                        }
-                       invocationArgs.Add (new Argument (tempExpr, Argument.AType.Expression));
-                       invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
-                       invocationArgs.Add (new Argument (new StringLiteral (memName), Argument.AType.Expression));
+
+                       if (expr != null)
+                               invocationArgs.Add (new Argument (expr, Argument.AType.Expression));
+                       else
+                               invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+                       if (type_expr != null)
+                               invocationArgs.Add (new Argument (type_expr, Argument.AType.Expression));
+                       else
+                               invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+                       invocationArgs.Add (new Argument (new StringLiteral (memberName), Argument.AType.Expression));
                        invocationArgs.Add (new Argument (v1, Argument.AType.Expression));
                        if (ArgumentNames != null && ArgumentNames.Count > 0)
                                invocationArgs.Add (new Argument (v2, Argument.AType.Expression));
@@ -3617,7 +3036,7 @@ namespace Mono.MonoBASIC {
                        bool isCopyBackRequired = false;
                        if (!isLeftHandSide) {
                                for (int i = 0; i < argCount; i++) {
-                                       Argument origArg = (Argument) originalArgs [i];
+                                       Argument origArg = (Argument) Arguments [i];
                                        Expression origExpr = origArg.Expr; 
                                        if (!(origExpr is Constant || origArg.ArgType == Argument.AType.NoArg)) 
                                                isCopyBackRequired = true;
@@ -3630,7 +3049,7 @@ namespace Mono.MonoBASIC {
                                rank_specifier.Add (new IntLiteral (argCount));
                                arrayInitializers = new ArrayList ();
                                for (int i = 0; i < argCount; i++) {
-                                       Argument a = (Argument) originalArgs [i];
+                                       Argument a = (Argument) Arguments [i];
                                        Expression origExpr = a.Expr;
                                        if (origExpr is Constant || a.ArgType == Argument.AType.NoArg || origExpr is New)
                                                arrayInitializers.Add (new BoolLiteral (false));
@@ -3661,7 +3080,10 @@ namespace Mono.MonoBASIC {
                        inv_stmt.IsLateBinding = true;
                        stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) inv_stmt, loc));
 
-                       for (int i = 0; i< argCount; i ++) {
+                       if (! isCopyBackRequired)
+                               return;
+
+                       for (int i = argCount - 1; i >= 0; i --) {
                                Argument arg = (Argument) originalArgs [i];
                                Expression origExpr = (Expression) arg.Expr;
                                if (arg.ArgType == Argument.AType.NoArg)
@@ -3686,13 +3108,18 @@ namespace Mono.MonoBASIC {
                public override void Emit (EmitContext ec)
                {
                        stmtBlock.Emit (ec);
-                       //ec.ig.Emit (OpCodes.Ldloc_0);
                }
        }
 
        public class SwitchLabel {
-               Expression label;
-               object converted;
+               public enum LabelType : byte {
+                       Operator, Range, Label, Else
+               }
+
+               Expression label, start, end;
+               LabelType label_type;
+               Expression label_condition, start_condition, end_condition;
+               Binary.Operator oper;
                public Location loc;
                public Label ILLabel;
                public Label ILLabelCode;
@@ -3700,10 +3127,23 @@ namespace Mono.MonoBASIC {
                //
                // if expr == null, then it is the default case.
                //
-               public SwitchLabel (Expression expr, Location l)
+               public SwitchLabel (Expression start, Expression end, LabelType ltype, Binary.Operator oper, Location l) {
+                       this.start = start;
+                       this.end = end;
+                       this.label_type = ltype;
+                       this.oper = oper;
+                       this.loc = l;
+                       label_condition = start_condition = end_condition = null;
+               }
+
+               public SwitchLabel (Expression expr, LabelType ltype, Binary.Operator oper, Location l)
                {
                        label = expr;
+                       start = end = null;
+                       label_condition = start_condition = end_condition = null;
                        loc = l;
+                       this.label_type = ltype;
+                       this.oper = oper;
                }
 
                public Expression Label {
@@ -3712,9 +3152,27 @@ namespace Mono.MonoBASIC {
                        }
                }
 
-               public object Converted {
+               public LabelType Type {
+                       get {
+                               return label_type;
+                       }
+               }
+
+               public Expression ConditionStart {
+                       get {
+                               return start_condition;
+                       }
+               }
+
+               public Expression ConditionEnd {
+                       get {
+                               return end_condition;
+                       }
+               }
+
+               public Expression ConditionLabel {
                        get {
-                               return converted;
+                               return label_condition;
                        }
                }
 
@@ -3722,37 +3180,55 @@ namespace Mono.MonoBASIC {
                // Resolves the expression, reduces it to a literal if possible
                // and then converts it to the requested type.
                //
-               public bool ResolveAndReduce (EmitContext ec, Type required_type)
+               public bool ResolveAndReduce (EmitContext ec, Expression expr)
                {
                        ILLabel = ec.ig.DefineLabel ();
                        ILLabelCode = ec.ig.DefineLabel ();
 
-                       if (label == null)
+                       Expression e = null;
+                       switch (label_type) {
+                       case LabelType.Label :
+                               if (label == null)
+                                       return false;
+                               e = label.Resolve (ec);
+                               if (e != null)
+                                       e = Expression.ConvertImplicit (ec, e, expr.Type, loc);
+                               if (e == null)
+                                       return false;
+                               label_condition = new Binary (Binary.Operator.Equality, expr, e, loc);
+                               if ((label_condition = label_condition.DoResolve (ec)) == null)
+                                       return false;
+                               return true;
+                       case LabelType.Operator :
+                               e = label.Resolve (ec);
+                               label_condition = new Binary (oper, expr, e, loc);
+                               if ((label_condition = label_condition.DoResolve (ec)) == null)
+                                       return false;
+                               return true;
+                       case LabelType.Range :
+                               if (start == null || end == null)
+                                       return false;
+                               e = start.Resolve (ec);
+                               if (e != null)
+                                       e = Expression.ConvertImplicit (ec, e, expr.Type, loc);
+                               if (e == null)
+                                       return false;
+                               start_condition = new Binary (Binary.Operator.GreaterThanOrEqual, expr, e, loc);
+                               start_condition = start_condition.Resolve (ec);
+                               e = end.Resolve (ec);
+                               if (e != null)
+                                       e = Expression.ConvertImplicit (ec, e, expr.Type, loc);
+                               if (e == null)
+                                       return false;
+                               end_condition = new Binary (Binary.Operator.LessThanOrEqual, expr, e, loc);
+                               end_condition = end_condition.Resolve (ec);
+                               if (start_condition == null || end_condition == null)
+                                       return false;
                                return true;
-                       
-                       Expression e = label.Resolve (ec);
-
-                       if (e == null)
-                               return false;
-
-                       if (!(e is Constant)){
-                               Console.WriteLine ("Value is: " + label);
-                               Report.Error (150, loc, "A constant value is expected");
-                               return false;
-                       }
 
-                       if (e is StringConstant || e is NullLiteral){
-                               if (required_type == TypeManager.string_type){
-                                       converted = e;
-                                       ILLabel = ec.ig.DefineLabel ();
-                                       return true;
-                               }
+                       case LabelType.Else :
+                               break;
                        }
-
-                       converted = Expression.ConvertIntLiteral ((Constant) e, required_type, loc);
-                       if (converted == null)
-                               return false;
-
                        return true;
                }
        }
@@ -3794,7 +3270,7 @@ namespace Mono.MonoBASIC {
                // The types allowed to be implicitly cast from
                // on the governing type
                //
-               static Type [] allowed_types;
+               //static Type [] allowed_types;
                
                public Switch (Expression e, ArrayList sects, Location l)
                {
@@ -3823,20 +3299,21 @@ namespace Mono.MonoBASIC {
                //
                Expression SwitchGoverningType (EmitContext ec, Type t)
                {
-                       if (t == TypeManager.int32_type ||
-                           t == TypeManager.uint32_type ||
-                           t == TypeManager.char_type ||
-                           t == TypeManager.byte_type ||
-                           t == TypeManager.sbyte_type ||
-                           t == TypeManager.ushort_type ||
+                       if (t == TypeManager.byte_type ||
                            t == TypeManager.short_type ||
-                           t == TypeManager.uint64_type ||
+                           t == TypeManager.int32_type ||
                            t == TypeManager.int64_type ||
+                           t == TypeManager.decimal_type ||
+                           t == TypeManager.float_type ||
+                           t == TypeManager.double_type ||
+                           t == TypeManager.date_type ||
+                           t == TypeManager.char_type ||
+                           t == TypeManager.object_type ||
                            t == TypeManager.string_type ||
                                t == TypeManager.bool_type ||
                                t.IsSubclassOf (TypeManager.enum_type))
                                return Expr;
-
+/*
                        if (allowed_types == null){
                                allowed_types = new Type [] {
                                        TypeManager.sbyte_type,
@@ -3869,19 +3346,21 @@ namespace Mono.MonoBASIC {
 
                                if (converted != null){
                                        Report.Error (-12, loc, "More than one conversion to an integral " +
-                                                     " type exists for type `" +
+                                                     " type exists for type '" +
                                                      TypeManager.MonoBASIC_Name (Expr.Type)+"'");
                                        return null;
                                } else
                                        converted = e;
                        }
                        return converted;
+*/
+                       return null;
                }
 
                void error152 (string n)
                {
                        Report.Error (
-                               152, "The label `" + n + ":' " +
+                               152, "The label '" + n + ":' " +
                                "is already present on this switch statement");
                }
                
@@ -3894,25 +3373,29 @@ namespace Mono.MonoBASIC {
                //
                bool CheckSwitch (EmitContext ec)
                {
-                       Type compare_type;
+                       //Type compare_type;
                        bool error = false;
                        Elements = new CaseInsensitiveHashtable ();
                                
                        got_default = false;
 
+/*
                        if (TypeManager.IsEnumType (SwitchType)){
                                compare_type = TypeManager.EnumToUnderlying (SwitchType);
                        } else
                                compare_type = SwitchType;
+*/
                        
-                       foreach (SwitchSection ss in Sections){
-                               foreach (SwitchLabel sl in ss.Labels){
-                                       if (!sl.ResolveAndReduce (ec, SwitchType)){
+                       for (int secIndex = 0; secIndex < Sections.Count; secIndex ++) {
+                               SwitchSection ss = (SwitchSection) Sections [secIndex];
+                               for (int labelIndex = 0; labelIndex < ss.Labels.Count; labelIndex ++) {
+                                       SwitchLabel sl  = (SwitchLabel) ss.Labels [labelIndex];
+                                       if (!sl.ResolveAndReduce (ec, Expr)){
                                                error = true;
                                                continue;
                                        }
 
-                                       if (sl.Label == null){
+                                       if (sl.Type == SwitchLabel.LabelType.Else){
                                                if (got_default){
                                                        error152 ("default");
                                                        error = true;
@@ -3920,111 +3403,6 @@ namespace Mono.MonoBASIC {
                                                got_default = true;
                                                continue;
                                        }
-                                       
-                                       object key = sl.Converted;
-
-                                       if (key is Constant)
-                                               key = ((Constant) key).GetValue ();
-
-                                       if (key == null)
-                                               key = NullLiteral.Null;
-                                       
-                                       string lname = null;
-                                       if (compare_type == TypeManager.uint64_type){
-                                               ulong v = (ulong) key;
-
-                                               if (Elements.Contains (v))
-                                                       lname = v.ToString ();
-                                               else
-                                                       Elements.Add (v, sl);
-                                       } else if (compare_type == TypeManager.int64_type){
-                                               long v = (long) key;
-
-                                               if (Elements.Contains (v))
-                                                       lname = v.ToString ();
-                                               else
-                                                       Elements.Add (v, sl);
-                                       } else if (compare_type == TypeManager.uint32_type){
-                                               uint v = (uint) key;
-
-                                               if (Elements.Contains (v))
-                                                       lname = v.ToString ();
-                                               else
-                                                       Elements.Add (v, sl);
-                                       } else if (compare_type == TypeManager.char_type){
-                                               char v = (char) key;
-                                               
-                                               if (Elements.Contains (v))
-                                                       lname = v.ToString ();
-                                               else
-                                                       Elements.Add (v, sl);
-                                       } else if (compare_type == TypeManager.byte_type){
-                                               byte v = (byte) key;
-                                               
-                                               if (Elements.Contains (v))
-                                                       lname = v.ToString ();
-                                               else
-                                                       Elements.Add (v, sl);
-                                       } else if (compare_type == TypeManager.sbyte_type){
-                                               sbyte v = (sbyte) key;
-                                               
-                                               if (Elements.Contains (v))
-                                                       lname = v.ToString ();
-                                               else
-                                                       Elements.Add (v, sl);
-                                       } else if (compare_type == TypeManager.short_type){
-                                               short v = (short) key;
-                                               
-                                               if (Elements.Contains (v))
-                                                       lname = v.ToString ();
-                                               else
-                                                       Elements.Add (v, sl);
-                                       } else if (compare_type == TypeManager.ushort_type){
-                                               ushort v = (ushort) key;
-                                               
-                                               if (Elements.Contains (v))
-                                                       lname = v.ToString ();
-                                               else
-                                                       Elements.Add (v, sl);
-                                       } else if (compare_type == TypeManager.string_type){
-                                               if (key is NullLiteral){
-                                                       if (Elements.Contains (NullLiteral.Null))
-                                                               lname = "null";
-                                                       else
-                                                               Elements.Add (NullLiteral.Null, null);
-                                               } else {
-                                                       string s = (string) key;
-
-                                                       if (Elements.Contains (s))
-                                                               lname = s;
-                                                       else
-                                                               Elements.Add (s, sl);
-                                               }
-                                       } else if (compare_type == TypeManager.int32_type) {
-                                               int v = (int) key;
-
-                                               if (Elements.Contains (v))
-                                                       lname = v.ToString ();
-                                               else
-                                                       Elements.Add (v, sl);
-                                       } else if (compare_type == TypeManager.bool_type) {
-                                               bool v = (bool) key;
-
-                                               if (Elements.Contains (v))
-                                                       lname = v.ToString ();
-                                               else
-                                                       Elements.Add (v, sl);
-                                       }
-                                       else
-                                       {
-                                               throw new Exception ("Unknown switch type!" +
-                                                                    SwitchType + " " + compare_type);
-                                       }
-
-                                       if (lname != null){
-                                               error152 ("case + " + lname);
-                                               error = true;
-                                       }
                                }
                        }
                        if (error)
@@ -4109,6 +3487,7 @@ namespace Mono.MonoBASIC {
                        }
                }
 
+/*
                /// <summary>
                /// This method emits code for a lookup-based switch statement (non-string)
                /// Basically it groups the cases into blocks that are at least half full,
@@ -4307,7 +3686,7 @@ namespace Mono.MonoBASIC {
                }
                //
                // This simple emit switch works, but does not take advantage of the
-               // `switch' opcode. 
+               // 'switch' opcode. 
                // TODO: remove non-string logic from here
                // TODO: binary search strings?
                //
@@ -4420,6 +3799,7 @@ namespace Mono.MonoBASIC {
                        
                        return all_return;
                }
+*/
 
                public override bool Resolve (EmitContext ec)
                {
@@ -4429,7 +3809,7 @@ namespace Mono.MonoBASIC {
 
                        new_expr = SwitchGoverningType (ec, Expr.Type);
                        if (new_expr == null){
-                               Report.Error (151, loc, "An integer type or string was expected for switch");
+                               Report.Error (30338, loc, "'Select' expression cannot be of type '" + Expr.Type +"'");
                                return false;
                        }
 
@@ -4468,15 +3848,7 @@ namespace Mono.MonoBASIC {
                
                protected override bool DoEmit (EmitContext ec)
                {
-                       // Store variable for comparission purposes
-                       LocalBuilder value = ec.ig.DeclareLocal (SwitchType);
-                       new_expr.Emit (ec);
-                       ec.ig.Emit (OpCodes.Stloc, value);
-
                        ILGenerator ig = ec.ig;
-
-                       default_target = ig.DefineLabel ();
-
                        //
                        // Setup the codegen context
                        //
@@ -4486,12 +3858,47 @@ namespace Mono.MonoBASIC {
                        ec.LoopEnd = ig.DefineLabel ();
                        ec.Switch = this;
 
-                       // Emit Code.
-                       bool all_return;
-                       if (SwitchType == TypeManager.string_type)
-                               all_return = SimpleSwitchEmit (ec, value);
-                       else
-                               all_return = TableSwitchEmit (ec, value);
+                       for (int secIndex = 0; secIndex < Sections.Count; secIndex ++) {
+                               SwitchSection section = (SwitchSection) Sections [secIndex];
+                               Label sLabel = ig.DefineLabel ();
+                               Label lLabel = ig.DefineLabel ();
+                               ArrayList Labels = section.Labels;
+                               for (int labelIndex = 0; labelIndex < Labels.Count; labelIndex ++) {
+                                       SwitchLabel sl = (SwitchLabel) Labels [labelIndex];
+                                       switch (sl.Type) {
+                                       case SwitchLabel.LabelType.Range :
+                                               if (labelIndex + 1 == Labels.Count) {
+                                                       EmitBoolExpression (ec, sl.ConditionStart, sLabel, false);
+                                                       EmitBoolExpression (ec, sl.ConditionEnd, sLabel, false);
+                                                       ig.Emit (OpCodes.Br, lLabel);
+                                               } else {
+                                                       Label newLabel = ig.DefineLabel ();
+                                                       EmitBoolExpression (ec, sl.ConditionStart, newLabel, false);
+                                                       EmitBoolExpression (ec, sl.ConditionEnd, newLabel, false);
+                                                       ig.Emit (OpCodes.Br, lLabel);
+                                                       ig.MarkLabel (newLabel);
+                                               }
+                                               break;
+                                       case SwitchLabel.LabelType.Else :
+                                               // Nothing to be done here
+                                               break;
+                                       case SwitchLabel.LabelType.Operator :
+                                               EmitBoolExpression (ec, sl.ConditionLabel, lLabel, true);
+                                               if (labelIndex + 1 == Labels.Count)
+                                                       ig.Emit (OpCodes.Br, sLabel);
+                                               break;
+                                       case SwitchLabel.LabelType.Label :
+                                               EmitBoolExpression (ec, sl.ConditionLabel, lLabel, true);
+                                               if (labelIndex + 1 == Labels.Count)
+                                                       ig.Emit (OpCodes.Br, sLabel);
+                                               break;
+                                       }
+
+                               }
+                               ig.MarkLabel (lLabel);
+                               section.Block.Emit (ec);
+                               ig.MarkLabel (sLabel);
+                       }
 
                        // Restore context state. 
                        ig.MarkLabel (ec.LoopEnd);
@@ -4501,8 +3908,7 @@ namespace Mono.MonoBASIC {
                        //
                        ec.LoopEnd = old_end;
                        ec.Switch = old_switch;
-                       
-                       return all_return;
+                       return true;
                }
        }
 
@@ -4530,7 +3936,7 @@ namespace Mono.MonoBASIC {
                        
                        if (type.IsValueType){
                                Report.Error (30582, loc, "lock statement requires the expression to be " +
-                                             " a reference type (type is: `" +
+                                             " a reference type (type is: '" +
                                              TypeManager.MonoBASIC_Name (type) + "'");
                                return false;
                        }
@@ -5061,11 +4467,13 @@ namespace Mono.MonoBASIC {
                protected override bool DoEmit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       Label finish = ig.DefineLabel ();;
                        bool returns;
 
                        ec.TryCatchLevel++;
-                       ig.BeginExceptionBlock ();
+                       Label finish = ig.BeginExceptionBlock ();
+                       ec.HasExitLabel = true;
+                       ec.ExitLabel = finish;
+
                        bool old_in_try = ec.InTry;
                        ec.InTry = true;
                        returns = Block.Emit (ec);
@@ -5135,7 +4543,6 @@ namespace Mono.MonoBASIC {
 
                        ec.InCatch = old_in_catch;
 
-                       ig.MarkLabel (finish);
                        if (Fini != null){
                                ig.BeginFinallyBlock ();
                                bool old_in_finally = ec.InFinally;
@@ -5150,8 +4557,204 @@ namespace Mono.MonoBASIC {
                        if (!returns || ec.InTry || ec.InCatch)
                                return returns;
 
+                       return true;
+               }
+       }
+       
+       public  class Pending_Assign {
+               Statement assign;
+               Block block_to_be_inserted;
+               int statement_index;
+               
+               public Pending_Assign (Block block, Statement assign, int index)
+               {
+                       this.assign = assign;
+                       this.block_to_be_inserted = block;
+                       this.statement_index = index;
+               }
+
+               public  void AddAssign()
+               {
+                       block_to_be_inserted.statements.Insert( statement_index, assign );
+               }       
+       }
+       
+       public class On_Error : Statement {
+               public readonly Block method_block;
+               ArrayList targets;
+               LabeledStatement[] labeledstatements;
+               
+               public On_Error (Block method_block, Location l)
+               {       
+                       //Goto
+                       this.method_block = method_block;
+                       base.loc = l;
+                       targets = new ArrayList();
+               }
+
+               public int AddTarget ( string target )
+               {                               
+                       int i = targets.IndexOf( target ) ;
+                       
+                       if ( i == -1 ) 
+                               return targets.Add ( target );
+                       else
+                               return i;
+               }
+
+               public ArrayList Targets {
+                       get {
+                               return targets;
+                       }
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       this.labeledstatements = new LabeledStatement[targets.Count];
+                       
+                       bool ok = true;
+                       
+                       ec.StartFlowBranching (FlowBranchingType.EXCEPTION, method_block.StartLocation);
+
+                       Report.Debug (1, "START OF TRY BLOCK", method_block.StartLocation);
+
+                       bool old_in_try = ec.InTry;
+                       ec.InTry = true;
+
+                       if (!method_block.Resolve (ec))
+                               ok = false;
+
+                       ec.InTry = old_in_try;
+
+                       FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector;
+
+                       ec.EndFlowBranching ();
+
+                       ec.CurrentBranching.CurrentUsageVector.Or (vector);
+
+                       Report.Debug (1, "END OF TRY", ec.CurrentBranching);
+
+                       //This statement has more than one label in cases of more than one 'on error goto' specification.
+                       for ( int i = 0 ; i < targets.Count ; i++ )
+                       {
+                               labeledstatements[i] = method_block.Parent.LookupLabel ((string) targets[i]);
+
+                               // If this is a forward goto.
+                               if (!labeledstatements[i].IsDefined)
+                                       labeledstatements[i].AddUsageVector (ec.CurrentBranching.CurrentUsageVector);
+
+                               labeledstatements[i].AddReference ();
+                       }
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       
+                       return ok;
+               }
+               protected override bool DoEmit (EmitContext ec)
+               {       
+                       ILGenerator ig = ec.ig;
+                               
+                       //Try
+
+                       bool returns;
+
+                       ec.TryCatchLevel++;
+                       
+                       Label finish = ig.BeginExceptionBlock ();
+                               ec.HasExitLabel = true;
+                               ec.ExitLabel = finish;
+                               
+                               bool old_in_try = ec.InTry;
+                               ec.InTry = true;
+                               returns = method_block.Emit (ec);
+                               ec.InTry = old_in_try;
+                               bool old_in_catch = ec.InCatch;
+                               ec.InCatch = true;
+
+                       Label error = ig.DefineLabel();
+                       Label endfilter = ig.DefineLabel();
+                       Label verification = ig.DefineLabel();
+                       
+                       ig.BeginExceptFilterBlock();
+                               ig.Emit (OpCodes.Isinst, Type.GetType("System.Exception") );
+                               ig.Emit (OpCodes.Brtrue_S, verification );
+
+                               ig.Emit (OpCodes.Br_S, error);
+                       
+                               ig.MarkLabel ( verification );  
+                               ig.Emit (OpCodes.Ldloc_0);
+                               ig.Emit (OpCodes.Brfalse_S, error);
+                               
+                               ig.Emit (OpCodes.Ldloc_1);
+                               ig.Emit (OpCodes.Brtrue_S, error);
+
+                               ig.Emit (OpCodes.Ldc_I4_1);
+                               ig.Emit (OpCodes.Br_S, endfilter);
+                               
+                               ig.MarkLabel (error);   
+                               ig.Emit (OpCodes.Ldc_I4_0);
+
+                               ig.MarkLabel ( endfilter );     
+                       
+                       
+                       Label endcatch = ig.DefineLabel();              
+                       Label verification2 = ig.DefineLabel();
+                       
+                       ig.BeginCatchBlock (null);
+                               ig.Emit (OpCodes.Castclass, Type.GetType("System.Exception"));
+                               ig.Emit (OpCodes.Dup);
+
+                               Type t = typeof(Microsoft.VisualBasic.CompilerServices.ProjectData);
+                               MethodInfo mi = t.GetMethod("SetProjectError", new Type[] { typeof(System.Exception) } );
+                               ig.Emit (OpCodes.Call, mi);
+                               ig.Emit (OpCodes.Stloc_3);
+                               ig.Emit (OpCodes.Ldloc_1);
+                               ig.Emit (OpCodes.Brfalse_S, verification2 );
+                               ig.Emit (OpCodes.Leave_S, finish );
+                               ig.MarkLabel ( verification2 );
+                               ig.Emit (OpCodes.Ldc_I4_M1);
+                               ig.Emit (OpCodes.Stloc_1);
+                               ig.Emit (OpCodes.Ldloc_0);
+
+                               Label[] lbswitch = new Label[targets.Count + 1];
+                               for ( int i = 0; i <= targets.Count; i++ )
+                                       lbswitch[i] = ig.DefineLabel();
+                               
+                               ig.Emit (OpCodes.Switch, lbswitch);     
+                               ig.MarkLabel ( lbswitch[0] ) ;
+                               ig.Emit (OpCodes.Leave_S, endcatch);    
+                                                               
+                               Label[] labels = new Label[targets.Count];
+                               for ( int i = 0; i < targets.Count; i++ )
+                               {
+                                       labels[i] = labeledstatements[i].LabelTarget(ec);
+
+                                       ig.MarkLabel ( lbswitch[i+1] ) ;
+                                       ig.Emit ( OpCodes.Leave, labels[i] );
+                               }
+
+                               ig.MarkLabel ( endcatch );
+                               ig.Emit ( OpCodes.Rethrow );    
+
+                       ec.InCatch = old_in_catch;
+
+                       ig.EndExceptionBlock ();
+                       ec.TryCatchLevel--;
+
+                       Label end = ig.DefineLabel();
+                       //ig.MarkLabel ( finish ) ;
+                       ig.Emit (OpCodes.Ldloc_1);
+                       ig.Emit (OpCodes.Brfalse_S, end );
+                               
+                       mi = t.GetMethod("ClearProjectError");
+                       ig.Emit (OpCodes.Call, mi);
+
+                       ig.MarkLabel(end) ;
+                       
+                       if (!returns)
+                               return returns;
+
                        // Unfortunately, System.Reflection.Emit automatically emits a leave
-                       // to the end of the finally block.  This is a problem if `returns'
+                       // to the end of the finally block.  This is a problem if 'returns'
                        // is true since we may jump to a point after the end of the method.
                        // As a workaround, emit an explicit ret here.
 
@@ -5161,6 +4764,7 @@ namespace Mono.MonoBASIC {
 
                        return true;
                }
+               
        }
 
        public class Using : Statement {
@@ -5359,7 +4963,7 @@ namespace Mono.MonoBASIC {
        }
 
        /// <summary>
-       ///   Implementation of the foreach C# statement
+       ///   Implementation of the for each statement
        /// </summary>
        public class Foreach : Statement {
                Expression type;
@@ -5394,6 +4998,19 @@ namespace Mono.MonoBASIC {
                        if (expr == null)
                                return false;
 
+                       if ( variable.VariableInfo.Alias != null )
+                       {
+                               FieldBase fb = variable.VariableInfo.GetFieldAlias(ec);
+
+                               if ( fb == null )
+                               {
+                                       Report.Error (451, loc,"Name '" + variable.VariableInfo.Name  + "' is not declared.");
+                                       return false;
+                               }
+                               else
+                               type = fb.Type;
+                       }
+                                               
                        var_type = ec.DeclSpace.ResolveType (type, false, loc);
                        if (var_type == null)
                                return false;
@@ -5451,12 +5068,12 @@ namespace Mono.MonoBASIC {
                                return false;
 
                        //FlowReturns returns = ec.EndFlowBranching ();
-
+                       ec.EndFlowBranching ();
                        return true;
                }
                
                //
-               // Retrieves a `public bool MoveNext ()' method from the Type `t'
+               // Retrieves a 'public bool MoveNext ()' method from the Type 't'
                //
                static MethodInfo FetchMethodMoveNext (Type t)
                {
@@ -5483,7 +5100,7 @@ namespace Mono.MonoBASIC {
                }
                
                //
-               // Retrieves a `public T get_Current ()' method from the Type `t'
+               // Retrieves a 'public T get_Current ()' method from the Type 't'
                //
                static MethodInfo FetchMethodGetCurrent (Type t)
                {
@@ -5581,7 +5198,7 @@ namespace Mono.MonoBASIC {
 
                        //
                        // Ok, we can access it, now make sure that we can do something
-                       // with this `GetEnumerator'
+                       // with this 'GetEnumerator'
                        //
 
                        if (mi.ReturnType == TypeManager.ienumerator_type ||
@@ -5627,7 +5244,7 @@ namespace Mono.MonoBASIC {
                 void error1579 (Type t)
                 {
                         Report.Error (1579, loc,
-                                      "foreach statement cannot operate on variables of type `" +
+                                      "foreach statement cannot operate on variables of type '" +
                                       t.FullName + "' because that class does not provide a " +
                                       " GetEnumerator method or it is inaccessible");
                 }
@@ -5687,7 +5304,7 @@ namespace Mono.MonoBASIC {
 
                //
                // FIXME: possible optimization.
-               // We might be able to avoid creating `empty' if the type is the sam
+               // We might be able to avoid creating 'empty' if the type is the sam
                //
                bool EmitCollectionForeach (EmitContext ec)
                {
@@ -5724,8 +5341,10 @@ namespace Mono.MonoBASIC {
                        //
                        bool old_in_try = ec.InTry;
 
-                       if (hm.is_disposable)
+                       if (hm.is_disposable) {
+                               ig.BeginExceptionBlock ();
                                ec.InTry = true;
+                       }
                        
                        Label end_try = ig.DefineLabel ();
                        
@@ -5733,9 +5352,25 @@ namespace Mono.MonoBASIC {
                        ig.Emit (OpCodes.Ldloc, enumerator);
                        ig.Emit (OpCodes.Callvirt, hm.move_next);
                        ig.Emit (OpCodes.Brfalse, end_try);
+                       
+                       
+                       FieldBase fb = null;
+                       if ( variable.VariableInfo.Alias != null )
+                       {
+                               fb = variable.VariableInfo.GetFieldAlias(ec);
+                               
+                               if( (fb.ModFlags & Modifiers.STATIC) == 0 )
+                                       ig.Emit (OpCodes.Ldarg_0);
+                       }       
+                                       
                        ig.Emit (OpCodes.Ldloc, enumerator);
                        ig.Emit (OpCodes.Callvirt, hm.get_current);
-                       variable.EmitAssign (ec, conv);
+                       
+                       if ( fb == null)
+                               variable.EmitAssign (ec, conv);
+                       else
+                               variable.EmitAssign (ec, conv, fb);
+                       
                        statement.Emit (ec);
                        ig.Emit (OpCodes.Br, ec.LoopBegin);
                        ig.MarkLabel (end_try);
@@ -5775,7 +5410,7 @@ namespace Mono.MonoBASIC {
 
                //
                // FIXME: possible optimization.
-               // We might be able to avoid creating `empty' if the type is the sam
+               // We might be able to avoid creating 'empty' if the type is the sam
                //
                bool EmitArrayForeach (EmitContext ec)
                {
@@ -5803,11 +5438,23 @@ namespace Mono.MonoBASIC {
                                loop = ig.DefineLabel ();
                                ig.MarkLabel (loop);
 
+                               FieldBase fb = null;
+                               if ( variable.VariableInfo.Alias != null )
+                               {
+                                       fb = variable.VariableInfo.GetFieldAlias(ec);
+
+                                       if( (fb.ModFlags & Modifiers.STATIC) == 0 )
+                                               ig.Emit (OpCodes.Ldarg_0);
+                               }       
+                                       
                                ig.Emit (OpCodes.Ldloc, copy);
                                ig.Emit (OpCodes.Ldloc, counter);
                                ArrayAccess.EmitLoadOpcode (ig, var_type);
 
-                               variable.EmitAssign (ec, conv);
+                               if ( fb == null)
+                                       variable.EmitAssign (ec, conv);
+                               else
+                                       variable.EmitAssign (ec, conv, fb);
 
                                statement.Emit (ec);
 
@@ -5856,7 +5503,7 @@ namespace Mono.MonoBASIC {
                                        ig.Emit (OpCodes.Ldloc, dim_count [dim]);
 
                                //
-                               // FIXME: Maybe we can cache the computation of `get'?
+                               // FIXME: Maybe we can cache the computation of 'get'?
                                //
                                Type [] args = new Type [rank];
                                MethodInfo get;
@@ -5933,7 +5580,7 @@ namespace Mono.MonoBASIC {
                public AddHandler (Expression evt_id, Expression evt_handler, Location l)
                {
                        EvtId = evt_id;
-                       EvtHandler = evt_handler;
+                       EvtHandler = Parser.SetAddressOf (evt_handler);
                        loc = l;
                        resolved = false;
                        //Console.WriteLine ("Adding handler '" + evt_handler + "' for Event '" + evt_id +"'");
@@ -6015,7 +5662,7 @@ namespace Mono.MonoBASIC {
                public RemoveHandler (Expression evt_id, Expression evt_handler, Location l)
                {
                        EvtId = evt_id;
-                       EvtHandler = evt_handler;
+                       EvtHandler = Parser.SetAddressOf (evt_handler);
                        loc = l;
                }
 
@@ -6069,23 +5716,100 @@ namespace Mono.MonoBASIC {
        }
 
        public class RedimClause {
-               public Expression Expr;
-               public ArrayList NewIndexes;
+               private Expression RedimTarget;
+               private ArrayList NewIndexes;
+               private Expression AsType;
                
-               public RedimClause (Expression e, ArrayList args)
+               private LocalTemporary localTmp = null;
+               private Expression origRedimTarget = null;
+               private StatementExpression ReDimExpr;
+
+               public RedimClause (Expression e, ArrayList args, Expression e_as)
                {
-                       Expr = e;
+                       if (e is SimpleName)
+                               ((SimpleName) e).IsInvocation = false;
+                       if (e is MemberAccess)
+                               ((MemberAccess) e).IsInvocation = false;
+               
+                       RedimTarget = e;
+                       NewIndexes = args;
+                       AsType = e_as;
+               }
+
+               public bool Resolve (EmitContext ec, bool Preserve, Location loc)
+               {
+                       RedimTarget = RedimTarget.Resolve (ec);
+
+                       if (AsType != null) {
+                               Report.Error (30811, loc, "'ReDim' statements can no longer be used to declare array variables");
+                               return false;
+                       }
+                       
+                       if (!RedimTarget.Type.IsArray) {
+                               Report.Error (49, loc, "'ReDim' statement requires an array");
+                               return false;
+                       }
+
+                       ArrayList args = new ArrayList();
+                       foreach (Argument a in NewIndexes) {
+                               if (a.Resolve(ec, loc))
+                                       args.Add (a.Expr);
+                       }
+
+                       for (int x = 0; x < args.Count; x++) {
+                               args[x] = new Binary (Binary.Operator.Addition,
+                                                       (Expression) args[x], new IntLiteral (1), Location.Null);       
+                       }
+
                        NewIndexes = args;
+                       if (RedimTarget.Type.GetArrayRank() != NewIndexes.Count) {
+                               Report.Error (30415, loc, "'ReDim' cannot change the number of dimensions of an array.");
+                               return false;
+                       }
+                       
+                       Type BaseType = RedimTarget.Type.GetElementType();
+                       Expression BaseTypeExpr = MonoBASIC.Parser.DecomposeQI(BaseType.FullName.ToString(), Location.Null);
+                       ArrayCreation acExpr = new ArrayCreation (BaseTypeExpr, NewIndexes, "", null, Location.Null);   
+                       if (Preserve)
+                       {
+                               ExpressionStatement PreserveExpr = null;
+                               if (RedimTarget is PropertyGroupExpr) {
+                                       localTmp = new LocalTemporary (ec, RedimTarget.Type);
+                                       PropertyGroupExpr pe = RedimTarget as PropertyGroupExpr;
+                                       origRedimTarget = new PropertyGroupExpr (pe.Properties, pe.Arguments, pe.InstanceExpression, loc);
+                                       if ((origRedimTarget = origRedimTarget.Resolve (ec)) == null)  {
+                                               Report.Error (-1, loc, "'ReDim' vs PropertyGroup");
+                                               return false;
+                                       }
+                                       PreserveExpr = (ExpressionStatement) new Preserve(localTmp, acExpr, loc);
+                               } else
+                                       PreserveExpr = (ExpressionStatement) new Preserve(RedimTarget, acExpr, loc);
+                               ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, PreserveExpr, loc), loc);
+                       }
+                       else
+                               ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, acExpr, loc), loc);
+                       ReDimExpr.Resolve(ec);  
+                       return true;            
                }
+
+               public void DoEmit (EmitContext ec)
+               {
+                       if (ReDimExpr == null)
+                               return;
+                               
+                       if (localTmp != null && origRedimTarget != null) {
+                               origRedimTarget.Emit (ec);
+                               localTmp.Store (ec);
+                       }
+                       ReDimExpr.Emit(ec);
+               }               
+
        }
 
        public class ReDim : Statement {
                ArrayList RedimTargets;
-               Type BaseType;
                bool Preserve;
 
-               private StatementExpression ReDimExpr;
-
                public ReDim (ArrayList targets, bool opt_preserve, Location l)
                {
                        loc = l;
@@ -6095,51 +5819,16 @@ namespace Mono.MonoBASIC {
 
                public override bool Resolve (EmitContext ec)
                {
-                       Expression RedimTarget;
-                       ArrayList NewIndexes;
-
-                       foreach (RedimClause rc in RedimTargets) {
-                               RedimTarget = rc.Expr;
-                               NewIndexes = rc.NewIndexes;
-
-                               RedimTarget = RedimTarget.Resolve (ec);
-                               if (!RedimTarget.Type.IsArray)
-                                       Report.Error (49, "'ReDim' statement requires an array");
-
-                               ArrayList args = new ArrayList();
-                               foreach (Argument a in NewIndexes) {
-                                       if (a.Resolve(ec, loc))
-                                               args.Add (a.Expr);
-                               }
-
-                               for (int x = 0; x < args.Count; x++) {
-                                       args[x] = new Binary (Binary.Operator.Addition,
-                                                               (Expression) args[x], new IntLiteral (1), Location.Null);       
-                               }
-
-                               NewIndexes = args;
-                               if (RedimTarget.Type.GetArrayRank() != args.Count)
-                                       Report.Error (30415, "'ReDim' cannot change the number of dimensions of an array.");
-
-                               BaseType = RedimTarget.Type.GetElementType();
-                               Expression BaseTypeExpr = MonoBASIC.Parser.DecomposeQI(BaseType.FullName.ToString(), Location.Null);
-                               ArrayCreation acExpr = new ArrayCreation (BaseTypeExpr, NewIndexes, "", null, Location.Null);   
-                               // TODO: we are in a foreach we probably can't reuse ReDimExpr, must turn it into an array(list)
-                               if (Preserve)
-                               {
-                                       ExpressionStatement PreserveExpr = (ExpressionStatement) new Preserve(RedimTarget, acExpr, loc);
-                                       ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, PreserveExpr, loc), loc);
-                               }
-                               else
-                                       ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, acExpr, loc), loc);
-                               ReDimExpr.Resolve(ec);
-                       }
-                       return true;
+                       bool result = true;
+                       foreach (RedimClause rc in RedimTargets)
+                               result = rc.Resolve(ec, Preserve, loc) && result;
+                       return result;
                }
                                
                protected override bool DoEmit (EmitContext ec)
                {
-                       ReDimExpr.Emit(ec);
+                       foreach (RedimClause rc in RedimTargets)
+                               rc.DoEmit(ec);
                        return false;
                }