- Fixed baseline aligning calcs
[mono.git] / mcs / mbas / statement.cs
index 8d612d6912d3d3291af140f033519cc7024f9c4f..de580cd2f01c40c5f683eb422f6d8f51f5cb0ee9 100644 (file)
@@ -4,6 +4,7 @@
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
 //   Martin Baulig (martin@gnome.org)
+//      Anirban Bhattacharjee (banirban@novell.com)
 //
 // (C) 2001, 2002 Ximian, Inc.
 //
@@ -14,7 +15,7 @@ using System.Reflection;
 using System.Reflection.Emit;
 using System.Diagnostics;
 
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
 
        using System.Collections;
        
@@ -673,7 +674,7 @@ namespace Mono.CSharp {
                        } else {
                                if (Expr == null){
                                        Report.Error (126, loc, "An object of type `" +
-                                                     TypeManager.CSharpName (ec.ReturnType) + "' is " +
+                                                     TypeManager.MonoBASIC_Name (ec.ReturnType) + "' is " +
                                                      "expected for the return statement");
                                        return true;
                                }
@@ -936,7 +937,7 @@ namespace Mono.CSharp {
                                if ((t != TypeManager.exception_type) &&
                                    !t.IsSubclassOf (TypeManager.exception_type) &&
                                    !(expr is NullLiteral)) {
-                                       Report.Error (155, loc,
+                                       Report.Error (30665, loc,
                                                      "The type caught or thrown must be derived " +
                                                      "from System.Exception");
                                        return false;
@@ -1032,16 +1033,44 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
 
-                       if (ec.InLoop == false && ec.Switch == null){
-                               Report.Error (139, loc, "No enclosing loop or switch to continue to");
-                               return false;
-                       }
+                       if (type != ExitType.SUB && type != ExitType.FUNCTION && 
+                               type != ExitType.PROPERTY && type != ExitType.TRY) {
+                               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
+                                               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");
+                                       if (type == ExitType.SELECT)
+                                               Report.Error (30099, loc, "No enclosing SELECT to exit from");
 
-                       if (ec.InTry || ec.InCatch)
-                               ig.Emit (OpCodes.Leave, ec.LoopEnd);
-                       else
-                               ig.Emit (OpCodes.Br, ec.LoopEnd);
+                                       return false;
+                               }
 
+                               if (ec.InTry || ec.InCatch)
+                                       ig.Emit (OpCodes.Leave, ec.LoopEnd);
+                               else
+                                       ig.Emit (OpCodes.Br, ec.LoopEnd);
+                       } else {                        
+                               if (ec.InFinally){
+                                       Report.Error (30393, loc, 
+                                               "Control can not leave the body of the finally block");
+                                       return false;
+                               }
+                       
+                               if (ec.InTry || ec.InCatch) {
+                                       if (!ec.HasReturnLabel) {
+                                               ec.ReturnLabel = ec.ig.DefineLabel ();
+                                               ec.HasReturnLabel = true;
+                                       }
+                                       ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
+                               } else
+                                       ec.ig.Emit (OpCodes.Ret);
+
+                               return true; 
+                       }
+                       
                        return false;
                }
        }       
@@ -2506,7 +2535,7 @@ namespace Mono.CSharp {
 
                                        FieldInfo field = struct_info [i];
                                        Report.Error (171, loc,
-                                                     "Field `" + TypeManager.CSharpName (VariableType) +
+                                                     "Field `" + TypeManager.MonoBASIC_Name (VariableType) +
                                                      "." + field.Name + "' must be fully initialized " +
                                                      "before control leaves the constructor");
                                        return false;
@@ -3404,7 +3433,7 @@ namespace Mono.CSharp {
                                if (converted != null){
                                        Report.Error (-12, loc, "More than one conversion to an integral " +
                                                      " type exists for type `" +
-                                                     TypeManager.CSharpName (Expr.Type)+"'");
+                                                     TypeManager.MonoBASIC_Name (Expr.Type)+"'");
                                        return null;
                                } else
                                        converted = e;
@@ -4065,7 +4094,7 @@ namespace Mono.CSharp {
                        if (type.IsValueType){
                                Report.Error (185, loc, "lock statement requires the expression to be " +
                                              " a reference type (type is: `" +
-                                             TypeManager.CSharpName (type) + "'");
+                                             TypeManager.MonoBASIC_Name (type) + "'");
                                return false;
                        }
 
@@ -4420,16 +4449,19 @@ namespace Mono.CSharp {
        public class Catch {
                public readonly string Name;
                public readonly Block  Block;
+               public Expression Clause;
                public readonly Location Location;
 
                Expression type_expr;
+               //Expression clus_expr;
                Type type;
                
-               public Catch (Expression type, string name, Block block, Location l)
+               public Catch (Expression type, string name, Block block, Expression clause, Location l)
                {
                        type_expr = type;
                        Name = name;
                        Block = block;
+                       Clause = clause;
                        Location = l;
                }
 
@@ -4453,7 +4485,7 @@ namespace Mono.CSharp {
                                        return false;
 
                                if (type != TypeManager.exception_type && !type.IsSubclassOf (TypeManager.exception_type)){
-                                       Report.Error (155, Location,
+                                       Report.Error (30665, Location,
                                                      "The type caught or thrown must be derived " +
                                                      "from System.Exception");
                                        return false;
@@ -4461,6 +4493,13 @@ namespace Mono.CSharp {
                        } else
                                type = null;
 
+                       if (Clause != null)     {
+                               Clause = Statement.ResolveBoolean (ec, Clause, Location);
+                               if (Clause == null) {
+                                       return false;
+                               }
+                       }
+
                        if (!Block.Resolve (ec))
                                return false;
 
@@ -4622,17 +4661,47 @@ namespace Mono.CSharp {
                                        ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
                                } else
                                        ig.Emit (OpCodes.Pop);
-                               
-                               if (!c.Block.Emit (ec))
-                                       returns = false;
+
+                               //
+                               // if when clause is there
+                               //
+                               if (c.Clause != null) {
+                                       if (c.Clause is BoolConstant) {
+                                               bool take = ((BoolConstant) c.Clause).Value;
+
+                                               if (take) 
+                                                       if (!c.Block.Emit (ec))
+                                                               returns = false;
+                                       } else {
+                                               EmitBoolExpression (ec, c.Clause, finish, false);
+                                               if (!c.Block.Emit (ec))
+                                                       returns = false;
+                                       }
+                               } else 
+                                       if (!c.Block.Emit (ec))
+                                               returns = false;
                        }
 
                        if (General != null){
                                ig.BeginCatchBlock (TypeManager.object_type);
                                ig.Emit (OpCodes.Pop);
-                               if (!General.Block.Emit (ec))
-                                       returns = false;
+
+                               if (General.Clause != null) {
+                                       if (General.Clause is BoolConstant) {
+                                               bool take = ((BoolConstant) General.Clause).Value;
+                                               if (take) 
+                                                       if (!General.Block.Emit (ec))
+                                                               returns = false;
+                                       } else {
+                                               EmitBoolExpression (ec, General.Clause, finish, false);
+                                               if (!General.Block.Emit (ec))
+                                                       returns = false;
+                                       }
+                               } else 
+                                       if (!General.Block.Emit (ec))
+                                               returns = false;
                        }
+
                        ec.InCatch = old_in_catch;
 
                        ig.MarkLabel (finish);
@@ -4940,7 +5009,7 @@ namespace Mono.CSharp {
                        // Although it is not as important in this case, as the type
                        // will not likely be object (what the enumerator will return).
                        //
-                       conv = Expression.ConvertExplicit (ec, empty, var_type, loc);
+                       conv = Expression.ConvertExplicit (ec, empty, var_type, false, loc);
                        if (conv == null)
                                return false;
 
@@ -5427,25 +5496,36 @@ namespace Mono.CSharp {
        public class AddHandler : Statement {
                Expression EvtId;
                Expression EvtHandler;
-               Expression EvtTarget;
 
-               public AddHandler (Expression evt_id, Expression evt_handler, 
-                                                       Expression evt_target, Location l)
+               //
+               // keeps track whether EvtId is already resolved
+               //
+               bool resolved;
+
+               public AddHandler (Expression evt_id, Expression evt_handler, Location l)
                {
                        EvtId = evt_id;
                        EvtHandler = evt_handler;
-                       EvtTarget = evt_target;
                        loc = l;
+                       resolved = false;
                        //Console.WriteLine ("Adding handler '" + evt_handler + "' for Event '" + evt_id +"'");
                }
 
                public override bool Resolve (EmitContext ec)
                {
+                       //
+                       // if EvetId is of EventExpr type that means
+                       // this is already resolved 
+                       //
+                       if (EvtId is EventExpr) {
+                               resolved = true;
+                               return true;
+                       }
+
                        EvtId = EvtId.Resolve(ec);
                        EvtHandler = EvtHandler.Resolve(ec,ResolveFlags.MethodGroup);
-                       EvtTarget = EvtTarget.Resolve (ec,ResolveFlags.VariableOrValue);
                        if (EvtId == null || (!(EvtId is EventExpr))) {
-                               Report.Error (999, "'AddHandler' statement needs an event designator.");
+                               Report.Error (30676, "Need an event designator.");
                                return false;
                        }
 
@@ -5454,20 +5534,25 @@ namespace Mono.CSharp {
                                Report.Error (999, "'AddHandler' statement needs an event handler.");
                                return false;
                        }
-                       //EventExpr ee = (EventExpr) EvtId;
-                       //MethodGroupExpr me = (MethodGroupExpr) EvtHandler;
-                       //bool b = EvtId.Type.IsSubclassOf (TypeManager.delegate_type);
-                       //ee.EventInfo.AddEventHandler(EvtTarget, new System.Delegate())
+
                        return true;
                }
 
                protected override bool DoEmit (EmitContext ec)
                {
+                       //
+                       // Already resolved and emitted don't do anything
+                       //
+                       if (resolved)
+                               return true;
+
                        Expression e, d;
                        ArrayList args = new ArrayList();
                        Argument arg = new Argument (EvtHandler, Argument.AType.Expression);
                        args.Add (arg);
                        
+                       
+
                        // The even type was already resolved to a delegate, so
                        // we must un-resolve its name to generate a type expression
                        string ts = (EvtId.Type.ToString()).Replace ('+','.');
@@ -5489,51 +5574,138 @@ namespace Mono.CSharp {
 
                        return false;
                }
-       }       
-       
-       public class ReDim : Statement {
-               Expression RedimTarget;
-               ArrayList NewIndexes;
-               ArrayList Initializers;
-               Type BaseType;
-               
-               private StatementExpression ReDimExpr;
-               
-               public ReDim (Expression expr, ArrayList args, bool opt_preserve, ArrayList inits, Location l)
+       }
+
+       /// <summary>
+       ///   RemoveHandler statement
+       /// </summary>
+       public class RemoveHandler : Statement \r
+       {
+               Expression EvtId;
+               Expression EvtHandler;
+
+               public RemoveHandler (Expression evt_id, Expression evt_handler, Location l)
                {
+                       EvtId = evt_id;
+                       EvtHandler = evt_handler;
                        loc = l;
-                       RedimTarget = expr;
-                       NewIndexes = args;
-                       Initializers = inits;
                }
-               
+
                public override bool Resolve (EmitContext ec)
                {
-                       RedimTarget = RedimTarget.Resolve (ec);
-                       if (!RedimTarget.Type.IsArray) 
-                               Report.Error (49, "'ReDim' statement requires an array");
+                       EvtId = EvtId.Resolve(ec);
+                       EvtHandler = EvtHandler.Resolve(ec,ResolveFlags.MethodGroup);
+                       if (EvtId == null || (!(EvtId is EventExpr))) \r
+                       {
+                               Report.Error (30676, "Need an event designator.");
+                               return false;
+                       }
 
-                       ArrayList args = new ArrayList();
-                       foreach (Argument a in NewIndexes) {
-                               if (a.Resolve(ec, loc))
-                                       args.Add (a.Expr);
+                       if (EvtHandler == null) 
+                       {
+                               Report.Error (999, "'AddHandler' statement needs an event handler.");
+                               return false;
                        }
+                       return true;
+               }
+
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       Expression e, d;
+                       ArrayList args = new ArrayList();
+                       Argument arg = new Argument (EvtHandler, Argument.AType.Expression);
+                       args.Add (arg);
                        
-                       for (int x = 0; x < args.Count; x++) {
-                               args[x] = new Binary (Binary.Operator.Addition, 
-                                                       (Expression) args[x], new IntLiteral (1), Location.Null);       
+                       // The even type was already resolved to a delegate, so
+                       // we must un-resolve its name to generate a type expression
+                       string ts = (EvtId.Type.ToString()).Replace ('+','.');
+                       Expression dtype = Mono.MonoBASIC.Parser.DecomposeQI (ts, Location.Null);
+
+                       // which we can use to declare a new event handler
+                       // of the same type
+                       d = new New (dtype, args, Location.Null);
+                       d = d.Resolve(ec);
+                       // detach the event
+                       e = new CompoundAssign(Binary.Operator.Subtraction, EvtId, d, Location.Null);
+
+                       // we resolve it all and emit the code
+                       e = e.Resolve(ec);
+                       if (e != null) 
+                       {
+                               e.Emit(ec);
+                               return true;
                        }
 
+                       return false;
+               }
+       }
+
+       public class RedimClause {
+               public Expression Expr;
+               public ArrayList NewIndexes;
+               
+               public RedimClause (Expression e, ArrayList args)
+               {
+                       Expr = e;
                        NewIndexes = args;
-                       if (RedimTarget.Type.GetArrayRank() != args.Count) 
-                               Report.Error (415, "'ReDim' cannot change the number of dimensions of an array.");
-
-                       BaseType = RedimTarget.Type.GetElementType();
-                       Expression BaseTypeExpr = MonoBASIC.Parser.DecomposeQI(BaseType.FullName.ToString(), Location.Null);
-                       ArrayCreation acExpr = new ArrayCreation (BaseTypeExpr, NewIndexes, "", Initializers, Location.Null);   
-                       ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, acExpr, loc), loc);
-                       ReDimExpr.Resolve(ec);
-                       
+               }
+       }
+
+       public class ReDim : Statement {
+               ArrayList RedimTargets;
+               Type BaseType;
+               bool Preserve;
+
+               private StatementExpression ReDimExpr;
+
+               public ReDim (ArrayList targets, bool opt_preserve, Location l)
+               {
+                       loc = l;
+                       RedimTargets = targets;
+                       Preserve = opt_preserve;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       Expression RedimTarget;
+                       ArrayList NewIndexes;
+
+                       foreach (RedimClause rc in RedimTargets) {
+                               RedimTarget = rc.Expr;
+                               NewIndexes = rc.NewIndexes;
+
+                               RedimTarget = RedimTarget.Resolve (ec);
+                               if (!RedimTarget.Type.IsArray)
+                                       Report.Error (49, "'ReDim' statement requires an array");
+
+                               ArrayList args = new ArrayList();
+                               foreach (Argument a in NewIndexes) {
+                                       if (a.Resolve(ec, loc))
+                                               args.Add (a.Expr);
+                               }
+
+                               for (int x = 0; x < args.Count; x++) {
+                                       args[x] = new Binary (Binary.Operator.Addition,
+                                                               (Expression) args[x], new IntLiteral (1), Location.Null);       
+                               }
+
+                               NewIndexes = args;
+                               if (RedimTarget.Type.GetArrayRank() != args.Count)
+                                       Report.Error (415, "'ReDim' cannot change the number of dimensions of an array.");
+
+                               BaseType = RedimTarget.Type.GetElementType();
+                               Expression BaseTypeExpr = MonoBASIC.Parser.DecomposeQI(BaseType.FullName.ToString(), Location.Null);
+                               ArrayCreation acExpr = new ArrayCreation (BaseTypeExpr, NewIndexes, "", null, Location.Null);   
+                               // TODO: we are in a foreach we probably can't reuse ReDimExpr, must turn it into an array(list)
+                               if (Preserve)
+                               {
+                                       ExpressionStatement PreserveExpr = (ExpressionStatement) new Preserve(RedimTarget, acExpr, loc);
+                                       ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, PreserveExpr, loc), loc);
+                               }
+                               else
+                                       ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, acExpr, loc), loc);
+                               ReDimExpr.Resolve(ec);
+                       }
                        return true;
                }
                                
@@ -5544,4 +5716,37 @@ namespace Mono.CSharp {
                }               
                
        }
+       
+       public class Erase : Statement {
+               Expression EraseTarget;
+               
+               private StatementExpression EraseExpr;
+               
+               public Erase (Expression expr, Location l)
+               {
+                       loc = l;
+                       EraseTarget = expr;
+               }
+               
+               public override bool Resolve (EmitContext ec)
+               {
+                       EraseTarget = EraseTarget.Resolve (ec);
+                       if (!EraseTarget.Type.IsArray) 
+                               Report.Error (49, "'Erase' statement requires an array");
+
+                       EraseExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (EraseTarget, NullLiteral.Null, loc), loc);
+                       EraseExpr.Resolve(ec);
+                       
+                       return true;
+               }
+                               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       EraseExpr.Emit(ec);
+                       return false;
+               }               
+               
+       }
+       
+       
 }