2001-11-18 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / expression.cs
index 234cf58b6c47730931ca7e1cb9524b91c19d5e11..5cf7fdb86541dfc754c26b3f3b46d4565786a7e5 100755 (executable)
@@ -1937,7 +1937,6 @@ namespace CIR {
 
                                return (ParameterData) ip;
                        } else {
-                               Console.WriteLine ("Getting parameters for: " + mb);
                                ParameterInfo [] pi = mb.GetParameters ();
                                ReflectionParameters rp = new ReflectionParameters (pi);
                                method_parameter_cache [mb] = rp;
@@ -2601,17 +2600,20 @@ namespace CIR {
                        string array_type = t.FullName + "[]";
                        LocalBuilder array;
                        
-                       array = ec.GetTemporaryStorage (Type.GetType (array_type));
+                       array = ig.DeclareLocal (Type.GetType (array_type));
                        IntLiteral.EmitInt (ig, count);
                        ig.Emit (OpCodes.Newarr, t);
                        ig.Emit (OpCodes.Stloc, array);
 
                        int top = arguments.Count;
                        for (int j = idx; j < top; j++){
+                               a = (Argument) arguments [j];
+                               
                                ig.Emit (OpCodes.Ldloc, array);
                                IntLiteral.EmitInt (ig, j - idx);
                                a.Emit (ec);
-                               ig.Emit (OpCodes.Stelem_Ref);
+                               
+                               ArrayAccess.EmitStoreOpcode (ig, t);
                        }
                        ig.Emit (OpCodes.Ldloc, array);
                }
@@ -2687,7 +2689,7 @@ namespace CIR {
                                                        Type t = instance_expr.Type;
                                                        
                                                        instance_expr.Emit (ec);
-                                                       LocalBuilder temp = ec.GetTemporaryStorage (t);
+                                                       LocalBuilder temp = ig.DeclareLocal (t);
                                                        ig.Emit (OpCodes.Stloc, temp);
                                                        ig.Emit (OpCodes.Ldloca, temp);
                                                }
@@ -2889,6 +2891,8 @@ namespace CIR {
                
                bool IsBuiltinType = false;
 
+               int dimensions = 0;
+
                public ArrayCreation (string requested_type, ArrayList exprs,
                                      string rank, ArrayList initializers, Location l)
                {
@@ -2907,9 +2911,14 @@ namespace CIR {
                public ArrayCreation (string requested_type, string rank, ArrayList initializers, Location l)
                {
                        RequestedType = requested_type;
-                       Rank = rank;
                        Initializers = initializers;
                        loc = l;
+
+                       Rank = rank.Substring (0, rank.LastIndexOf ("["));
+
+                       string tmp = rank.Substring (rank.LastIndexOf ("["));
+
+                       dimensions = tmp.Length - 1;
                }
 
                public static string FormArrayType (string base_type, int idx_count, string rank)
@@ -2941,12 +2950,111 @@ namespace CIR {
 
                        return val.Substring (0, val.LastIndexOf ("["));
                }
+
+               void error178 ()
+               {
+                       Report.Error (178, loc, "Incorrectly structured array initializer");
+               }
+
+               bool ValidateInitializers (EmitContext ec)
+               {
+                       if (Initializers == null)
+                               return true;
+
+                       Type underlying_type = ec.TypeContainer.LookupType (RequestedType, false);
+
+                       ArrayList probe = Initializers;
+
+                       if (Arguments != null) {
+                               for (int i = 0; i < Arguments.Count; i++) {
+                                       Argument a = (Argument) Arguments [i];
+                                       
+                                       Expression e = Expression.Reduce (ec, a.Expr);
+                                       
+                                       if (!(e is Literal)) {
+                                               Report.Error (150, loc, "A constant value is expected");
+                                               return false;
+                                       }
+                                       
+                                       int value = (int) ((Literal) e).GetValue ();
                
+                                       if (probe == null) {
+                                               error178 ();
+                                               return false;
+                                       }
+                                               
+                                       if (value != probe.Count) {
+                                               error178 ();
+                                               return false;
+                                       }
+
+                                       if (probe [0] is ArrayList)
+                                               probe = (ArrayList) probe [0];
+                                       else {
+                                               for (int j = 0; j < probe.Count; ++j) {
+                                                       Expression tmp = (Expression) probe [j];
+                                                       
+                                                       tmp = tmp.Resolve (ec);
+
+                                                       Expression conv = ConvertImplicitRequired (ec, tmp,
+                                                                                                  underlying_type, loc);
 
+                                                       if (conv == null)
+                                                               return false;
+                                               }
+
+                                               probe = null;
+                                       }
+                               }
+
+                       } else {
+                               //
+                               // Here is where we update dimension info in the case
+                               // that the user skips doing that
+                               //
+
+                               Arguments = new ArrayList ();
+                               
+                               for (probe = Initializers; probe != null; ) {
+                                       Expression e = new IntLiteral (probe.Count);
+
+                                       Arguments.Add (new Argument (e, Argument.AType.Expression));
+
+                                       if (probe [0] is ArrayList)
+                                               probe = (ArrayList) probe [0];
+                                       else {
+                                               for (int j = 0; j < probe.Count; ++j) {
+                                                       Expression tmp = (Expression) probe [j];
+                                                       
+                                                       tmp = tmp.Resolve (ec);
+
+                                                       Expression conv = ConvertImplicitRequired (ec, tmp,
+                                                                                                  underlying_type, loc);
+
+                                                       if (conv == null)
+                                                               return false;
+                                               }
+                                               
+                                               probe = null;
+                                       }
+                               }
+
+                               if (Arguments.Count != dimensions) {
+                                       error178 ();
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+               
                public override Expression DoResolve (EmitContext ec)
                {
                        int arg_count;
-                       
+
+                       if (!ValidateInitializers (ec))
+                               return null;
+
                        if (Arguments == null)
                                arg_count = 0;
                        else
@@ -3558,6 +3666,30 @@ namespace CIR {
                        else
                                ig.Emit (OpCodes.Ldelem_Ref);
                }
+
+               // <summary>
+               //    Emits the right opcode to store an object of Type `t'
+               //    from an array of T.  
+               // </summary>
+               static public void EmitStoreOpcode (ILGenerator ig, Type t)
+               {
+                       if (t == TypeManager.byte_type || t == TypeManager.sbyte_type)
+                               ig.Emit (OpCodes.Stelem_I1);
+                       else if (t == TypeManager.short_type || t == TypeManager.ushort_type)
+                               ig.Emit (OpCodes.Stelem_I2);
+                       else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
+                               ig.Emit (OpCodes.Stelem_I4);
+                       else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
+                               ig.Emit (OpCodes.Stelem_I8);
+                       else if (t == TypeManager.float_type)
+                               ig.Emit (OpCodes.Stelem_R4);
+                       else if (t == TypeManager.double_type)
+                               ig.Emit (OpCodes.Stelem_R8);
+                       else if (t == TypeManager.intptr_type)
+                               ig.Emit (OpCodes.Stelem_I);
+                       else
+                               ig.Emit (OpCodes.Stelem_Ref);
+               }
                
                public override void Emit (EmitContext ec)
                {
@@ -3604,24 +3736,9 @@ namespace CIR {
                        source.Emit (ec);
 
                        Type t = source.Type;
-                       if (rank == 1){
-                               if (t == TypeManager.byte_type || t == TypeManager.sbyte_type)
-                                       ig.Emit (OpCodes.Stelem_I1);
-                               else if (t == TypeManager.short_type || t == TypeManager.ushort_type)
-                                       ig.Emit (OpCodes.Stelem_I2);
-                               else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
-                                       ig.Emit (OpCodes.Stelem_I4);
-                               else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
-                                       ig.Emit (OpCodes.Stelem_I8);
-                               else if (t == TypeManager.float_type)
-                                       ig.Emit (OpCodes.Stelem_R4);
-                               else if (t == TypeManager.double_type)
-                                       ig.Emit (OpCodes.Stelem_R8);
-                               else if (t == TypeManager.intptr_type)
-                                       ig.Emit (OpCodes.Stelem_I);
-                               else
-                                       ig.Emit (OpCodes.Stelem_Ref);
-                       } else {
+                       if (rank == 1)
+                               EmitStoreOpcode (ig, t);
+                       else {
                                ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
                                Type [] args = new Type [ea.Arguments.Count + 1];
                                MethodInfo set;