Switch to compiler-tester
[mono.git] / mcs / mbas / statement.cs
index c5325da00b51d70e51a041dc8e504fcf3bba28b3..889bcc852fab7aff74ae93be46291cefe7063fec 100644 (file)
@@ -462,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)
@@ -499,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;
@@ -507,7 +655,7 @@ namespace Mono.MonoBASIC {
                        } else
                                infinite = true;
 
-                       if (Increment != null){
+                       if (Increment != null) {
                                if (!Increment.Resolve (ec))
                                        ok = false;
                        }
@@ -516,7 +664,7 @@ namespace Mono.MonoBASIC {
                        if (!infinite)
                                ec.CurrentBranching.CreateSibling ();
 
-                       if (!Statement.Resolve (ec))
+                       if (!statement.Resolve (ec))
                                ok = false;
 
                        if (empty)
@@ -543,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);
 
@@ -552,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);
@@ -579,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;
@@ -590,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 {
@@ -652,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;
@@ -746,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;
                }
@@ -754,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;
@@ -763,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;
                }
 
@@ -1100,8 +1277,12 @@ namespace Mono.MonoBASIC {
                                        }
                                        ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
                                } 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);
+                                       }
 
                                }
 
@@ -1937,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>
@@ -2037,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;
 
@@ -2127,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.
@@ -2207,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;
@@ -2689,7 +2817,7 @@ 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";
@@ -2765,7 +2893,7 @@ namespace Mono.MonoBASIC {
                                return isLateBindingRequired;
                        }
                        set {
-                               isLateBindingRequired = true;
+                               isLateBindingRequired = value;
                        }
                }
 
@@ -3158,7 +3286,7 @@ 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;
@@ -3331,31 +3459,79 @@ namespace Mono.MonoBASIC {
 
        public class StatementSequence : Expression {
                Block stmtBlock;
-               ArrayList args;
+               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 {
@@ -3373,46 +3549,110 @@ namespace Mono.MonoBASIC {
                        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;
-                       // Arguments for call Microsoft.VisualBasic.CompilerServices.LateBinding.LateCall
-                       ArrayList invocationArgs = new ArrayList ();
-                       invocationArgs.Add (new Argument (((MemberAccess)expr).Expr, Argument.AType.Expression));
-                       invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
-                       invocationArgs.Add (new Argument (new StringLiteral (((MemberAccess)expr).Identifier), Argument.AType.Expression));
-                       // __LateBindingArgs = new Object () {arg1, arg2 ...}
                        ArrayList arrayInitializers = new ArrayList ();
-                       ArrayList originalArgs = new ArrayList ();
+                       ArrayList ArgumentNames = null;
                        if (args != null) {
                                //arrayInitializers = new ArrayList ();
                                argCount = args.Count;
-                               foreach (Argument a in args) {
-                                       arrayInitializers.Add (a.Expr);
-                                       originalArgs.Add (a.Expr);
+                               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));
-                       invocationArgs.Add (new Argument (v1, Argument.AType.Expression));
+                       // __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));
+                       }
 
-                       // __LateBindingArgNames = nothing
-                       //LocalVariableReference v2 = new LocalVariableReference (stmtBlock, Block.lateBindingArgNames, loc);
-                       //assign_stmt = new Assign (v2, NullLiteral.Null, loc);
-                       //stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) assign_stmt, loc));
+                       //string memName = "";
+                       //bool isIndexerAccess = true;
 
-                       invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+                       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;
-                       for (int i = 0; i < argCount; i++) {
-                               if (!(((Argument)args[i]).Expr is Constant)) 
-                                       isCopyBackRequired = true;
+                       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);
@@ -3421,7 +3661,9 @@ namespace Mono.MonoBASIC {
                                rank_specifier.Add (new IntLiteral (argCount));
                                arrayInitializers = new ArrayList ();
                                for (int i = 0; i < argCount; i++) {
-                                       if (((Argument)args[i]).Expr is Constant)
+                                       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));
@@ -3431,13 +3673,14 @@ namespace Mono.MonoBASIC {
                                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 {
+                       } 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);
@@ -3449,17 +3692,25 @@ namespace Mono.MonoBASIC {
                        inv_stmt.IsLateBinding = true;
                        stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) inv_stmt, loc));
 
-                       for (int i = 0; i< argCount; i ++) {
-                               Expression thisArg = (Expression) originalArgs [i];
-                               if (thisArg is Constant)
+                       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 varRef = (Expression) (originalArgs [i]);
                                Expression value = new Invocation (new SimpleName (Block.lateBindingArgs, loc), argsLocal, loc);
-                               assign_stmt = new Assign (varRef, value,  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);
@@ -3469,13 +3720,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;
@@ -3483,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 {
@@ -3495,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;
                        }
                }
 
@@ -3505,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;
                }
        }
@@ -3577,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)
                {
@@ -3606,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,
@@ -3659,6 +3965,8 @@ namespace Mono.MonoBASIC {
                                        converted = e;
                        }
                        return converted;
+*/
+                       return null;
                }
 
                void error152 (string n)
@@ -3677,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;
@@ -3703,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)
@@ -3892,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,
@@ -4203,6 +4411,7 @@ namespace Mono.MonoBASIC {
                        
                        return all_return;
                }
+*/
 
                public override bool Resolve (EmitContext ec)
                {
@@ -4212,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;
                        }
 
@@ -4251,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
                        //
@@ -4269,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);
@@ -4284,8 +4520,7 @@ namespace Mono.MonoBASIC {
                        //
                        ec.LoopEnd = old_end;
                        ec.Switch = old_switch;
-                       
-                       return all_return;
+                       return true;
                }
        }
 
@@ -4834,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);
@@ -5147,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;
@@ -5239,7 +5469,7 @@ namespace Mono.MonoBASIC {
                                return false;
 
                        //FlowReturns returns = ec.EndFlowBranching ();
-
+                       ec.EndFlowBranching ();
                        return true;
                }
                
@@ -5512,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 ();