Switch to compiler-tester
[mono.git] / mcs / mbas / statement.cs
index a451f8c6e9fd81f00566a8366a20d3c3367d7829..889bcc852fab7aff74ae93be46291cefe7063fec 100644 (file)
@@ -5,6 +5,8 @@
 //   Miguel de Icaza (miguel@ximian.com)
 //   Martin Baulig (martin@gnome.org)
 //      Anirban Bhattacharjee (banirban@novell.com)
+//   Manjula GHM (mmanjula@novell.com)
+//   Satya Sudha K (ksathyasudha@novell.com)
 //
 // (C) 2001, 2002 Ximian, Inc.
 //
@@ -58,7 +60,7 @@ namespace Mono.MonoBASIC {
 
                        if (e == null){
                                Report.Error (
-                                       31, loc, "Can not convert the expression to a boolean");
+                                       30311, loc, "Can not convert the expression to a boolean");
                        }
 
                        ec.Mark (loc);
@@ -460,35 +462,183 @@ namespace Mono.MonoBASIC {
        }
 
        public class For : Statement {
-               Expression Test;
-               readonly Statement InitStatement;
-               readonly Statement Increment;
-               readonly Statement Statement;
+               Expression LoopControlVar;
+               Expression Start;
+               Expression Limit;
+               Expression StepValue;
+               Statement statement, Increment;
                bool may_return, infinite, empty;
+               private Statement InitStatement;
+               // required when loop control var is of type 'Object'
+               Expression Test, AddnTest;
+               LocalTemporary ltmp;
+               bool is_lcv_object;
                
-               public For (Statement initStatement,
-                           Expression test,
-                           Statement increment,
+               public For (Expression loopVar,
+                           Expression start,
+                           Expression limit,
+                           Expression stepVal,
                            Statement statement,
                            Location l)
                {
-                       InitStatement = initStatement;
-                       Test = test;
-                       Increment = increment;
-                       Statement = statement;
+                       LoopControlVar = loopVar;
+                       Start = start;
+                       Limit = limit;
+                       StepValue = stepVal;
+                       this.statement = statement;
                        loc = l;
+                       ltmp = null;
+
+                       InitStatement = new StatementExpression ((ExpressionStatement) (new Assign (LoopControlVar, Start, loc)), loc);
+                       Increment = new StatementExpression (
+                                               (ExpressionStatement) (new CompoundAssign (Binary.Operator.Addition, 
+                                                                       LoopControlVar, StepValue, loc)), loc);
+                       AddnTest = null;
+                       is_lcv_object = false;
                }
-               
 
                public override bool Resolve (EmitContext ec)
                {
                        bool ok = true;
 
+                       LoopControlVar = LoopControlVar.Resolve (ec);
+                       if (LoopControlVar == null)
+                               return false;
+
+                       Start = Start.Resolve (ec);
+                       Limit = Limit.Resolve (ec);
+                       StepValue = StepValue.Resolve (ec);
+                       if (StepValue == null || Start == null || Limit == null)
+                               return false;
+
+                       double value = 0;
+                       if (StepValue is Constant) {
+
+                               value = GetValue (StepValue);
+                               if (value > 0) // Positive Step value
+                                       Test = new Binary (Binary.Operator.LessThanOrEqual, LoopControlVar, Limit, loc);
+                               else if (value < 0)
+                                       Test = new Binary (Binary.Operator.GreaterThanOrEqual, LoopControlVar, Limit, loc);
+                       }
+
+                       if (Start is Constant && Limit is Constant) {
+                               if (value > 0)
+                                       AddnTest = ConstantFold.BinaryFold (ec, Binary.Operator.LessThanOrEqual,
+                                                                           (Constant) Start, (Constant) Limit, loc);
+                               else  if (value < 0)
+                                       AddnTest = ConstantFold.BinaryFold (ec, Binary.Operator.GreaterThanOrEqual,
+                                                                           (Constant) Start, (Constant) Limit, loc);
+                       }
+
+
+                       string method_to_call = null;
+                       Binary left, right;
+                       left = right = null;
+
+                       switch (Type.GetTypeCode (LoopControlVar.Type)) {
+                       case TypeCode.Boolean :
+                       case TypeCode.Char :
+                       case TypeCode.DateTime :
+                       case TypeCode.String :
+                               Report.Error (30337,loc,"'For' loop control variable cannot be of type '" + LoopControlVar.Type + "'");
+                               return false;
+                       case TypeCode.Byte :
+                               if (Test == null)
+                                       Test = new Binary (Binary.Operator.LessThanOrEqual, LoopControlVar, Limit, loc);
+                               break;
+                       case TypeCode.Int16 :
+                               if (Test == null) {
+                                       left = new Binary (Binary.Operator.ExclusiveOr, 
+                                                          new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (15), loc),
+                                                          LoopControlVar, 
+                                                          loc);
+                                       right = new Binary (Binary.Operator.ExclusiveOr, 
+                                                           new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (15), loc),
+                                                           Limit, 
+                                                           loc);
+                                       Test = new Binary (Binary.Operator.LessThanOrEqual, left, right, loc);
+                               }
+                               break;
+                       case TypeCode.Int32 :
+                               if (Test == null) {
+                                       left = new Binary (Binary.Operator.ExclusiveOr, 
+                                                          new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (31), loc),
+                                                          LoopControlVar, 
+                                                          loc);
+                                       right = new Binary (Binary.Operator.ExclusiveOr, 
+                                                           new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (31), loc),
+                                                           Limit, 
+                                                           loc);
+                                       Test = new Binary (Binary.Operator.LessThanOrEqual, left, right, loc);
+                               }
+                               break;
+                       case TypeCode.Int64 :
+                               if (Test == null) {
+                                       left = new Binary (Binary.Operator.ExclusiveOr, 
+                                                          new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (63), loc),
+                                                          LoopControlVar, 
+                                                          loc);
+                                       right = new Binary (Binary.Operator.ExclusiveOr, 
+                                                           new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (63), loc),
+                                                           Limit, 
+                                                           loc);
+                                       Test = new Binary (Binary.Operator.LessThanOrEqual, left, right, loc);
+                               }
+                               break;
+                       case TypeCode.Decimal :
+                               method_to_call = "Microsoft.VisualBasic.CompilerServices.FlowControl.ForNextCheckDec";
+                               break;
+                       case TypeCode.Single :
+                               method_to_call = "Microsoft.VisualBasic.CompilerServices.FlowControl.ForNextCheckR4";
+                               break;
+                       case TypeCode.Double :
+                               method_to_call = "Microsoft.VisualBasic.CompilerServices.FlowControl.ForNextCheckR8";
+                               break;
+                       case TypeCode.Object :
+                               is_lcv_object = true;
+                               ArrayList initArgs = new ArrayList ();
+                               initArgs.Add (new Argument (LoopControlVar, Argument.AType.Expression));
+                               initArgs.Add (new Argument (Start, Argument.AType.Expression));
+                               initArgs.Add (new Argument (Limit, Argument.AType.Expression));
+                               initArgs.Add (new Argument (StepValue, Argument.AType.Expression));
+                               ltmp = new LocalTemporary (ec, TypeManager.object_type);
+                               initArgs.Add (new Argument (ltmp, Argument.AType.Ref));
+                               initArgs.Add (new Argument (LoopControlVar, Argument.AType.Ref));
+                               Expression sname  = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.FlowControl.ForLoopInitObj", loc);
+                               AddnTest = new Invocation (sname, initArgs, loc);
+                               //AddnTest = new Binary (Binary.Operator.Inequality, inv, new BoolLiteral (false), loc);
+                               ArrayList args = new ArrayList ();
+                               args.Add (new Argument (LoopControlVar, Argument.AType.Expression));
+                               args.Add (new Argument (ltmp, Argument.AType.Expression));
+                               args.Add (new Argument (LoopControlVar, Argument.AType.Ref));
+                               sname  = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.FlowControl.ForNextCheckObj", loc);
+                               Test = new Invocation (sname, args, loc);
+                               //Test = new Binary (Binary.Operator.Inequality, inv, new BoolLiteral (false), loc);
+                               break;
+                       }
+
+                       if (method_to_call != null && !method_to_call.Equals ("")) {
+                               ArrayList args = null;
+                               args = new ArrayList ();
+                               args.Add (new Argument (LoopControlVar, Argument.AType.Expression));
+                               args.Add (new Argument (Limit, Argument.AType.Expression));
+                               args.Add (new Argument (StepValue, Argument.AType.Expression));
+                               Expression sname = Parser.DecomposeQI (method_to_call, loc);
+                               Test = new Invocation (sname, args, loc);
+                               //Test = new Binary (Binary.Operator.Inequality, invocation, new BoolLiteral (false), loc);
+                       }
+
                        if (InitStatement != null){
                                if (!InitStatement.Resolve (ec))
                                        ok = false;
                        }
 
+                       if (AddnTest != null) {
+                               AddnTest = ResolveBoolean (ec, AddnTest, loc);
+                               if (AddnTest == null)
+                                       ok = false;
+                       }
+
                        if (Test != null){
                                Test = ResolveBoolean (ec, Test, loc);
                                if (Test == null)
@@ -497,7 +647,7 @@ namespace Mono.MonoBASIC {
                                        BoolConstant bc = (BoolConstant) Test;
 
                                        if (bc.Value == false){
-                                               Warning_DeadCodeFound (Statement.loc);
+                                               Warning_DeadCodeFound (statement.loc);
                                                empty = true;
                                        } else
                                                infinite = true;
@@ -505,7 +655,7 @@ namespace Mono.MonoBASIC {
                        } else
                                infinite = true;
 
-                       if (Increment != null){
+                       if (Increment != null) {
                                if (!Increment.Resolve (ec))
                                        ok = false;
                        }
@@ -514,7 +664,7 @@ namespace Mono.MonoBASIC {
                        if (!infinite)
                                ec.CurrentBranching.CreateSibling ();
 
-                       if (!Statement.Resolve (ec))
+                       if (!statement.Resolve (ec))
                                ok = false;
 
                        if (empty)
@@ -541,7 +691,7 @@ namespace Mono.MonoBASIC {
                        Label loop = ig.DefineLabel ();
                        Label test = ig.DefineLabel ();
                        
-                       if (InitStatement != null)
+                       if (!is_lcv_object && InitStatement != null)
                                if (! (InitStatement is EmptyStatement))
                                        InitStatement.Emit (ec);
 
@@ -550,12 +700,23 @@ namespace Mono.MonoBASIC {
                        ec.InLoop = true;
                        ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
 
-                       ig.Emit (OpCodes.Br, test);
+                       if (AddnTest != null) {
+                               if (AddnTest is BoolConstant) {
+                                       if (!((BoolConstant) AddnTest).Value)
+                                               // We can actually branch to the end of the loop,
+                                               // but vbc does it this way
+                                               ig.Emit (OpCodes.Br, test);
+                               } else if (is_lcv_object)
+                                       EmitBoolExpression (ec, AddnTest, ec.LoopEnd, false);
+                               else 
+                                       EmitBoolExpression (ec, AddnTest, test, false);
+                       } else 
+                               ig.Emit (OpCodes.Br, test);
                        ig.MarkLabel (loop);
-                       Statement.Emit (ec);
+                       statement.Emit (ec);
 
                        ig.MarkLabel (ec.LoopBegin);
-                       if (!(Increment is EmptyStatement))
+                       if (!is_lcv_object && !(Increment is EmptyStatement))
                                Increment.Emit (ec);
 
                        ig.MarkLabel (test);
@@ -577,6 +738,9 @@ namespace Mono.MonoBASIC {
                        //
                        // Inform whether we are infinite or not
                        //
+
+                       if (ltmp != null)
+                               ltmp.Release (ec);
                        if (Test != null){
                                if (Test is BoolConstant){
                                        BoolConstant bc = (BoolConstant) Test;
@@ -588,6 +752,20 @@ namespace Mono.MonoBASIC {
                        } else
                                return may_return == false;
                }
+
+               private double GetValue (Expression e) {
+                       if (e is DoubleConstant)
+                               return ((DoubleConstant) e).Value;
+                       if (e is FloatConstant)
+                               return (double)((FloatConstant) e).Value;
+                       if (e is IntConstant)
+                               return (double)((IntConstant) e).Value;
+                       if (e is LongConstant)
+                               return (double)((LongConstant) e).Value;
+                       if (e is DecimalConstant)
+                               return (double)((DecimalConstant) e).Value;
+                       return 0;
+               }
        }
        
        public class StatementExpression : Statement {
@@ -613,7 +791,8 @@ namespace Mono.MonoBASIC {
                                ((ExpressionStatement) expr).EmitStatement (ec);
                        else {
                                expr.Emit (ec);
-                               ig.Emit (OpCodes.Pop);
+                               if (! (expr is StatementSequence))
+                                       ig.Emit (OpCodes.Pop);
                        }
 
                        return false;
@@ -649,8 +828,6 @@ namespace Mono.MonoBASIC {
 
                        if (ec.CurrentBranching.InTryBlock ())
                                ec.CurrentBranching.AddFinallyVector (vector);
-                       else
-                               vector.CheckOutParameters (ec.CurrentBranching);
 
                        vector.Returns = FlowReturns.ALWAYS;
                        vector.Breaks = FlowReturns.ALWAYS;
@@ -713,7 +890,7 @@ namespace Mono.MonoBASIC {
                        label = block.LookupLabel (target);
                        if (label == null){
                                Report.Error (
-                                       159, loc,
+                                       30132, loc,
                                        "No such label `" + target + "' in this scope");
                                return false;
                        }
@@ -743,7 +920,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;
                }
@@ -751,7 +931,7 @@ namespace Mono.MonoBASIC {
 
        public class LabeledStatement : Statement {
                public readonly Location Location;
-               string label_name;
+               //string label_name;
                bool defined;
                bool referenced;
                Label label;
@@ -760,7 +940,7 @@ namespace Mono.MonoBASIC {
                
                public LabeledStatement (string label_name, Location l)
                {
-                       this.label_name = label_name;
+                       //this.label_name = label_name;
                        this.Location = l;
                }
 
@@ -842,7 +1022,7 @@ namespace Mono.MonoBASIC {
                        }
 
                        if (!ec.Switch.GotDefault){
-                               Report.Error (159, loc, "No default target on switch statement");
+                               Report.Error (30132, loc, "No default target on switch statement");
                                return false;
                        }
                        ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
@@ -875,7 +1055,7 @@ namespace Mono.MonoBASIC {
                                return false;
 
                        if (!(expr is Constant)){
-                               Report.Error (159, loc, "Target expression for goto case is not constant");
+                               Report.Error (30132, loc, "Target expression for goto case is not constant");
                                return false;
                        }
 
@@ -889,7 +1069,7 @@ namespace Mono.MonoBASIC {
 
                        if (sl == null){
                                Report.Error (
-                                       159, loc,
+                                       30132, loc,
                                        "No such label 'case " + val + "': for the goto case");
                        }
 
@@ -969,6 +1149,39 @@ namespace Mono.MonoBASIC {
                }
        }
 
+       // Support 'End' Statement which terminates execution immediately
+
+         public class End : Statement {
+
+                public End (Location l)
+                {
+                        loc = l;
+                }
+
+                public override bool Resolve (EmitContext ec)
+                {
+                        return true;
+                }
+
+                protected override bool DoEmit (EmitContext ec)
+                {
+                       Expression e = null;
+                        Expression tmp = Mono.MonoBASIC.Parser.DecomposeQI (
+                                                "Microsoft.VisualBasic.CompilerServices.ProjectData.EndApp",
+                                                        Location.Null);
+
+                       e = new Invocation (tmp, null, loc);
+                       e.Resolve (ec);
+
+                       if (e == null)
+                               return false;
+                       e.Emit (ec);
+
+                        return true;
+                }
+        }
+
+
        public class Break : Statement {
                
                public Break (Location l)
@@ -1036,7 +1249,7 @@ namespace Mono.MonoBASIC {
                                if (ec.InLoop == false && ec.Switch == null){
                                        if (type == ExitType.FOR)
                                                Report.Error (30096, loc, "No enclosing FOR loop to exit from");
-                                       if (type == ExitType.WHILE) \r
+                                       if (type == ExitType.WHILE) 
                                                Report.Error (30097, loc, "No enclosing WHILE loop to exit from");
                                        if (type == ExitType.DO)
                                                Report.Error (30089, loc, "No enclosing DO loop to exit from");
@@ -1063,8 +1276,15 @@ namespace Mono.MonoBASIC {
                                                ec.HasReturnLabel = true;
                                        }
                                        ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
-                               } else
-                                       ec.ig.Emit (OpCodes.Ret);
+                               } else {
+                                       if(type == ExitType.SUB) {   
+                                                ec.ig.Emit (OpCodes.Ret);
+                                        } else {
+                                               ec.ig.Emit (OpCodes.Ldloc_0);
+                                               ec.ig.Emit (OpCodes.Ret);
+                                       }
+
+                               }
 
                                return true; 
                        }
@@ -1898,13 +2118,6 @@ namespace Mono.MonoBASIC {
 
                                Report.Debug (1, "MERGING FINALLY ORIGIN DONE", this);
                        }
-
-                       public void CheckOutParameters (FlowBranching branching)
-                       {
-                               if (parameters != null)
-                                       branching.CheckOutParameters (parameters, branching.Location);
-                       }
-
                        // <summary>
                        //   Performs an `or' operation on the locals and the parameters.
                        // </summary>
@@ -1998,10 +2211,10 @@ 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;
+                       //      if ((mod & Parameter.Modifier.OUT) == 0)
+                       //              continue;
 
                                param_map [i] = ++num_params;
 
@@ -2088,50 +2301,6 @@ namespace Mono.MonoBASIC {
                        CurrentUsageVector.MergeFinallyOrigins (finally_vectors);
                }
 
-               // <summary>
-               //   Check whether all `out' parameters have been assigned.
-               // </summary>
-               public void CheckOutParameters (MyBitVector parameters, Location loc)
-               {
-                       if (InTryBlock ())
-                               return;
-
-                       for (int i = 0; i < param_map.Length; i++) {
-                               int index = param_map [i];
-
-                               if (index == 0)
-                                       continue;
-
-                               if (parameters [index - 1])
-                                       continue;
-
-                               // If it's a struct, we must ensure that all its fields have
-                               // been assigned.  If the struct has any non-public fields, this
-                               // can only be done by assigning the whole struct.
-
-                               MyStructInfo struct_info = struct_params [index - 1];
-                               if ((struct_info == null) || struct_info.HasNonPublicFields) {
-                                       Report.Error (
-                                               177, loc, "The out parameter `" +
-                                               param_info.ParameterName (i) + "' must be " +
-                                               "assigned before control leave the current method.");
-                                       param_map [i] = 0;
-                                       continue;
-                               }
-
-
-                               for (int j = 0; j < struct_info.Count; j++) {
-                                       if (!parameters [index + j]) {
-                                               Report.Error (
-                                                       177, loc, "The out parameter `" +
-                                                       param_info.ParameterName (i) + "' must be " +
-                                                       "assigned before control leave the current method.");
-                                               param_map [i] = 0;
-                                               break;
-                                       }
-                               }
-                       }
-               }
 
                // <summary>
                //   Merge a child branching.
@@ -2168,8 +2337,6 @@ namespace Mono.MonoBASIC {
                        Report.Debug (1, "MERGING TOP BLOCK DONE", Location, vector);
 
                        if (vector.Breaks != FlowReturns.EXCEPTION) {
-                               if (!vector.AlwaysBreaks)
-                                       CheckOutParameters (CurrentUsageVector.Parameters, Location);
                                return vector.AlwaysBreaks ? FlowReturns.ALWAYS : vector.Returns;
                        } else
                                return FlowReturns.EXCEPTION;
@@ -2650,7 +2817,14 @@ namespace Mono.MonoBASIC {
                //
                // Maps variable names to ILGenerator.LocalBuilders
                //
-               CaseInsensitiveHashtable local_builders;
+               //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;
 
@@ -2688,6 +2862,21 @@ namespace Mono.MonoBASIC {
                {
                        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;
@@ -2699,6 +2888,15 @@ namespace Mono.MonoBASIC {
                        statements = new ArrayList ();
                }
 
+               public bool IsLateBindingRequired {
+                       get {
+                               return isLateBindingRequired;
+                       }
+                       set {
+                               isLateBindingRequired = value;
+                       }
+               }
+
                public int ID {
                        get {
                                return this_id;
@@ -2843,13 +3041,13 @@ namespace Mono.MonoBASIC {
                        VariableInfo vi = GetVariableInfo (name);
                        if (vi != null) {
                                if (vi.Block != ID)
-                                       Report.Error (136, l, "A local variable named `" + name + "' " +
+                                       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 (128, l, "A local variable `" + name + "' is already " +
+                                       Report.Error (30290, l, "A local variable `" + name + "' is already " +
                                                      "defined in this scope");
                                return null;
                        }
@@ -2867,7 +3065,7 @@ namespace Mono.MonoBASIC {
                                int idx = 0;
                                Parameter p = pars.GetParameterByName (name, out idx);
                                if (p != null) {
-                                       Report.Error (136, l, "A local variable named `" + name + "' " +
+                                       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 " +
@@ -3088,10 +3286,18 @@ namespace Mono.MonoBASIC {
                        // Process this block variables
                        //
                        if (variables != null){
-                               local_builders = new CaseInsensitiveHashtable ();
+                               //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)
@@ -3173,13 +3379,14 @@ namespace Mono.MonoBASIC {
                        bool ok = true;
 
                        ec.CurrentBlock = this;
-                       ec.StartFlowBranching (this);
-
-                       Report.Debug (1, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
 
                        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;
 
@@ -3189,7 +3396,6 @@ namespace Mono.MonoBASIC {
                                                warning_shown = true;
                                                Warning_DeadCodeFound (s.loc);
                                        }
-
                                        continue;
                                }
 
@@ -3251,9 +3457,281 @@ namespace Mono.MonoBASIC {
                }
        }
 
+       public class StatementSequence : Expression {
+               Block stmtBlock;
+               ArrayList args, originalArgs;
+               Expression expr;
+               bool isRetValRequired;
+               bool isLeftHandSide;
+               bool isIndexerAccess;
+               string memberName;
+               Expression type_expr;
+
+               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) 
+               {
+                       stmtBlock = new Block (parent);
+                       args = a;
+                       originalArgs = new ArrayList ();
+                       if (args != null) {
+                               for (int index = 0; index < a.Count; index ++) {
+                                       Argument argument = (Argument) args [index];
+                                       originalArgs.Add (new Argument (argument.Expr, argument.ArgType));
+                               }
+                       }
+
+                       this.expr = expr;
+                       stmtBlock.IsLateBindingRequired = true;
+                       this.loc = loc;
+                       this.isRetValRequired = this.isLeftHandSide = false;
+                       this.memberName = "";
+                       this.type_expr = null;
+               }
+
+               public ArrayList Arguments {
+                       get {
+                               return args;
+                       }
+                       set {
+                               args = value;
+                       }
+               }
+
+               public bool IsLeftHandSide {
+                       set {
+                               isLeftHandSide = value;
+                       }
+               }
+
+               public Block StmtBlock {
+                       get {
+                               return stmtBlock;
+                       }
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (!stmtBlock.Resolve (ec))
+                               return null;
+                       eclass = ExprClass.Value;
+                       type = TypeManager.object_type;
+                       return this;
+               }
+
+               public bool ResolveArguments (EmitContext ec) {
+               
+                       bool argNamesFound = false;
+                       if (Arguments != null)
+                       {
+                               for (int index = 0; index < Arguments.Count; index ++)
+                               {
+                                       Argument a = (Argument) Arguments [index];
+                                       if (a.ParamName == null || a.ParamName == "") {
+                                               if (argNamesFound) {
+                                                       Report.Error (30241, loc, "Named Argument expected");
+                                                       return false;
+                                               }
+                                       } else
+                                               argNamesFound = true;
+                                       if (a.ArgType == Argument.AType.NoArg)
+                                               a = new Argument (Parser.DecomposeQI ("System.Reflection.Missing.Value", loc), Argument.AType.Expression);
+                                       if (!a.Resolve (ec, loc))
+                                               return false;                           
+                                       Arguments [index] = a;
+                               }
+                       }
+                       return true;
+               }
+                       
+               public void GenerateLateBindingStatements ()
+               {
+                       int argCount = 0;
+                       ArrayList arrayInitializers = new ArrayList ();
+                       ArrayList ArgumentNames = null;
+                       if (args != null) {
+                               //arrayInitializers = new ArrayList ();
+                               argCount = args.Count;
+                               for (int index = 0; index < args.Count; index ++) {
+                                       Argument a = (Argument) args [index];
+                                       Expression argument = a.Expr;
+                                       arrayInitializers.Add (argument);
+                                       if (a.ParamName != null && a.ParamName != "") {
+                                               if (ArgumentNames == null)
+                                                       ArgumentNames = new ArrayList ();
+                                               ArgumentNames.Add (new StringLiteral (a.ParamName));
+                                       }
+                               }
+                       }
+
+                       // __LateBindingArgs = new Object () {arg1, arg2 ...}
+                       ArrayCreation new_expr = new ArrayCreation (Parser.DecomposeQI ("System.Object",  loc), "[]", arrayInitializers, loc);
+                       Assign assign_stmt = null;
+
+                       LocalVariableReference v1 = new LocalVariableReference (stmtBlock, Block.lateBindingArgs, loc);
+                       assign_stmt = new Assign (v1, new_expr, loc);
+                       stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) assign_stmt, loc));
+                       // __LateBindingArgNames = new string () { argument names}
+                       LocalVariableReference v2 = null;
+                       if (ArgumentNames != null && ArgumentNames.Count > 0) {
+                               new_expr = new ArrayCreation (Parser.DecomposeQI ("System.String",  loc), "[]", ArgumentNames, loc);
+                               v2 = new LocalVariableReference (stmtBlock, Block.lateBindingArgNames, loc);
+                               assign_stmt = new Assign (v2, new_expr, loc);
+                               stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) assign_stmt, loc));
+                       }
+
+                       //string memName = "";
+                       //bool isIndexerAccess = true;
+
+                       ArrayList invocationArgs = new ArrayList ();
+                       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;
+                               if (!isLeftHandSide)
+                                       tmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexGet", loc);
+                               else
+                                       tmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexSet", loc);
+                               Invocation invStmt = new Invocation (tmp, invocationArgs, Location.Null);
+                               invStmt.IsLateBinding = true;
+                               stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) invStmt, loc));
+                               return;
+                       }
+
+                       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));
+                       else
+                               invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+
+                       // __LateBindingCopyBack = new Boolean (no_of_args) {}
+                       bool isCopyBackRequired = false;
+                       if (!isLeftHandSide) {
+                               for (int i = 0; i < argCount; i++) {
+                                       Argument origArg = (Argument) Arguments [i];
+                                       Expression origExpr = origArg.Expr; 
+                                       if (!(origExpr is Constant || origArg.ArgType == Argument.AType.NoArg)) 
+                                               isCopyBackRequired = true;
+                               }
+                       }
+
+                       LocalVariableReference v3 = new LocalVariableReference (stmtBlock, Block.lateBindingCopyBack, loc);
+                       if (isCopyBackRequired) {
+                               ArrayList rank_specifier = new ArrayList ();
+                               rank_specifier.Add (new IntLiteral (argCount));
+                               arrayInitializers = new ArrayList ();
+                               for (int i = 0; i < argCount; 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));
+                                       else 
+                                               arrayInitializers.Add (new BoolLiteral (true));
+                               }
+       
+                               new_expr = new ArrayCreation (Parser.DecomposeQI ("System.Boolean",  loc), "[]", arrayInitializers, loc);
+                               assign_stmt = new Assign (v3, new_expr, loc);
+                               stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) assign_stmt, loc));
+                               invocationArgs.Add (new Argument (v3, Argument.AType.Expression));
+                       } else if (! isLeftHandSide) {
+                               invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+                       }
+
+                       Expression etmp = null;
+                       if (isLeftHandSide) {
+                               // LateSet
+                               etmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.LateBinding.LateSet", loc);
+                       } else if (isRetValRequired) {
+                               // Late Get
+                               etmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.LateBinding.LateGet", loc);
+                       }  else {
+                               etmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.LateBinding.LateCall", loc);
+                       }
+
+                       Invocation inv_stmt = new Invocation (etmp, invocationArgs, Location.Null);
+                       inv_stmt.IsLateBinding = true;
+                       stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) inv_stmt, loc));
+
+                       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)
+                                       continue;
+                               if (origExpr is Constant)
+                                       continue;
+                               if (origExpr is New)
+                                       continue;
+
+                               Expression intExpr = new IntLiteral (i);
+                               ArrayList argsLocal = new ArrayList ();
+                               argsLocal.Add (new Argument (intExpr, Argument.AType.Expression));
+                               Expression indexExpr = new Invocation (new SimpleName (Block.lateBindingCopyBack, loc), argsLocal, loc);
+                               Expression value = new Invocation (new SimpleName (Block.lateBindingArgs, loc), argsLocal, loc);
+                               assign_stmt = new Assign (origExpr, value,  loc);
+                               Expression boolExpr = new Binary (Binary.Operator.Inequality, indexExpr, new BoolLiteral (false), loc);
+                               Statement ifStmt = new If (boolExpr, new StatementExpression ((ExpressionStatement) assign_stmt, loc), loc);
+                               stmtBlock.AddStatement (ifStmt);
+                       }
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       stmtBlock.Emit (ec);
+               }
+       }
+
        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;
@@ -3261,10 +3739,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 {
@@ -3273,9 +3764,27 @@ namespace Mono.MonoBASIC {
                        }
                }
 
-               public object Converted {
+               public LabelType Type {
+                       get {
+                               return label_type;
+                       }
+               }
+
+               public Expression ConditionStart {
                        get {
-                               return converted;
+                               return start_condition;
+                       }
+               }
+
+               public Expression ConditionEnd {
+                       get {
+                               return end_condition;
+                       }
+               }
+
+               public Expression ConditionLabel {
+                       get {
+                               return label_condition;
                        }
                }
 
@@ -3283,37 +3792,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;
                }
        }
@@ -3355,7 +3882,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)
                {
@@ -3384,20 +3911,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,
@@ -3437,6 +3965,8 @@ namespace Mono.MonoBASIC {
                                        converted = e;
                        }
                        return converted;
+*/
+                       return null;
                }
 
                void error152 (string n)
@@ -3455,25 +3985,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;
@@ -3481,111 +4015,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)
@@ -3670,6 +4099,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,
@@ -3981,6 +4411,7 @@ namespace Mono.MonoBASIC {
                        
                        return all_return;
                }
+*/
 
                public override bool Resolve (EmitContext ec)
                {
@@ -3990,7 +4421,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;
                        }
 
@@ -4029,15 +4460,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
                        //
@@ -4047,12 +4470,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);
@@ -4062,8 +4520,7 @@ namespace Mono.MonoBASIC {
                        //
                        ec.LoopEnd = old_end;
                        ec.Switch = old_switch;
-                       
-                       return all_return;
+                       return true;
                }
        }
 
@@ -4090,7 +4547,7 @@ namespace Mono.MonoBASIC {
                        bool val;
                        
                        if (type.IsValueType){
-                               Report.Error (185, loc, "lock statement requires the expression to be " +
+                               Report.Error (30582, loc, "lock statement requires the expression to be " +
                                              " a reference type (type is: `" +
                                              TypeManager.MonoBASIC_Name (type) + "'");
                                return false;
@@ -4105,7 +4562,7 @@ namespace Mono.MonoBASIC {
                        ig.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object);
 
                        // try
-                       //Label end = ig.BeginExceptionBlock ();
+                       ig.BeginExceptionBlock ();
                        bool old_in_try = ec.InTry;
                        ec.InTry = true;
                        Label finish = ig.DefineLabel ();
@@ -4612,11 +5069,6 @@ namespace Mono.MonoBASIC {
                        FlowBranching.UsageVector f_vector = ec.CurrentBranching.CurrentUsageVector;
 
                        Report.Debug (1, "END OF FINALLY", ec.CurrentBranching, returns, vector, f_vector);
-
-                       if ((returns == FlowReturns.SOMETIMES) || (returns == FlowReturns.ALWAYS)) {
-                               ec.CurrentBranching.CheckOutParameters (f_vector.Parameters, loc);
-                       }
-
                        ec.CurrentBranching.CurrentUsageVector.Or (vector);
 
                        Report.Debug (1, "END OF TRY", ec.CurrentBranching);
@@ -4925,7 +5377,7 @@ namespace Mono.MonoBASIC {
        }
 
        /// <summary>
-       ///   Implementation of the foreach C# statement
+       ///   Implementation of the for each statement
        /// </summary>
        public class Foreach : Statement {
                Expression type;
@@ -5017,7 +5469,7 @@ namespace Mono.MonoBASIC {
                                return false;
 
                        //FlowReturns returns = ec.EndFlowBranching ();
-
+                       ec.EndFlowBranching ();
                        return true;
                }
                
@@ -5290,8 +5742,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 ();
                        
@@ -5685,7 +6139,7 @@ namespace Mono.MonoBASIC {
 
                                NewIndexes = args;
                                if (RedimTarget.Type.GetArrayRank() != args.Count)
-                                       Report.Error (415, "'ReDim' cannot change the number of dimensions of an array.");
+                                       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);