svn path=/branches/mono-1-1-9/mcs/; revision=51212
[mono.git] / mcs / mbas / ecore.cs
index c7638e2b57de5b3193e0c78170916c6ea0086220..7e5b20829d86bce2439fdcd595cd5bf05eb3b950 100644 (file)
@@ -504,8 +504,10 @@ namespace Mono.MonoBASIC {
                                return new CharConstant ((char)v);
                        else if (t == TypeManager.bool_type)
                                return new BoolConstant ((bool) v);
+                       else if (t == TypeManager.decimal_type)
+                               return new DecimalConstant ((decimal)v);
                        else if (TypeManager.IsEnumType (t)){
-                               Constant e = Constantify (v, TypeManager.TypeToCoreType (v.GetType ()));
+                               Constant e = Constantify (v, TypeManager.EnumToUnderlying (v.GetType ()));
 
                                return new EnumConstant (e, t);
                        } else
@@ -585,12 +587,15 @@ namespace Mono.MonoBASIC {
 
                        int count = mi.Length;
 
-                       if (count > 1)
-                               return new MethodGroupExpr (mi, loc);
-
                        if (mi [0] is MethodBase)
                                return new MethodGroupExpr (mi, loc);
 
+                       if (mi [0] is PropertyInfo)
+                               return new PropertyGroupExpr (mi, loc);
+
+                       if (count > 1)
+                               return null;
+
                        return ExprClassFromMemberInfo (ec, mi [0], loc);
                }
 
@@ -960,22 +965,6 @@ namespace Mono.MonoBASIC {
                                if (real_target_type == TypeManager.float_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
                                                               OpCodes.Conv_R4);        
-                       } else if (expr_type == TypeManager.char_type){
-                               //
-                               // From char to ushort, int, uint, long, ulong, float, double
-                               // 
-                               if ((real_target_type == TypeManager.ushort_type) ||
-                                   (real_target_type == TypeManager.int32_type) ||
-                                   (real_target_type == TypeManager.uint32_type))
-                                       return new EmptyCast (expr, target_type);
-                               if (real_target_type == TypeManager.uint64_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
-                               if (real_target_type == TypeManager.int64_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
-                               if (real_target_type == TypeManager.float_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
-                               if (real_target_type == TypeManager.double_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
                        } else if (expr_type == TypeManager.string_type){
 
                                if (real_target_type == TypeManager.bool_type)
@@ -1023,8 +1012,6 @@ namespace Mono.MonoBASIC {
                                        return RTConversionExpression(ec, "System.Convert", ".ToSingle", expr, loc);
                                if (real_target_type == TypeManager.double_type)
                                        return RTConversionExpression(ec, "System.Convert", ".ToDouble", expr, loc);
-                               if (real_target_type == TypeManager.char_type)
-                                       return RTConversionExpression(ec, "System.Convert", ".ToChar", expr, loc);
                        }
 
                        return null;
@@ -1249,21 +1236,6 @@ namespace Mono.MonoBASIC {
                                    (target_type == TypeManager.decimal_type))
                                        return true;
                                    
-                       } else if (expr_type == TypeManager.char_type){
-                               //
-                               // From char to ushort, int, uint, long, ulong, float, double
-                               // 
-                               if ((target_type == TypeManager.ushort_type) ||
-                                   (target_type == TypeManager.int32_type) ||
-                                   (target_type == TypeManager.uint32_type) ||
-                                   (target_type == TypeManager.uint64_type) ||
-                                   (target_type == TypeManager.int64_type) ||
-                                   (target_type == TypeManager.float_type) ||
-                                   (target_type == TypeManager.double_type) ||
-                                   (target_type == TypeManager.string_type) ||
-                                   (target_type == TypeManager.decimal_type))
-                                       return true;
-
                        } else if (expr_type == TypeManager.decimal_type) {
                                if (target_type == TypeManager.float_type ||
                                    target_type == TypeManager.double_type)
@@ -1283,6 +1255,7 @@ namespace Mono.MonoBASIC {
                        if (ImplicitReferenceConversionExists (expr, expr_type, target_type))
                                return true;
                        
+/*
                        if (expr is IntConstant){
                                int value = ((IntConstant) expr).Value;
 
@@ -1325,6 +1298,7 @@ namespace Mono.MonoBASIC {
                                if (v > 0)
                                        return true;
                        }
+*/
                        
                        if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){
                                IntLiteral i = (IntLiteral) expr;
@@ -1898,22 +1872,6 @@ namespace Mono.MonoBASIC {
                                    (expr_type == TypeManager.decimal_type))
                                        return true;
                                    
-                       } else if (target_type == TypeManager.char_type){
-                               //
-                               // To char from ushort, int, uint, long, ulong, float, double, decimal,string
-                               // 
-                               if ((expr_type == TypeManager.ushort_type) ||
-                                   (expr_type == TypeManager.int32_type) ||
-                                   (expr_type == TypeManager.uint32_type) ||
-                                   (expr_type == TypeManager.uint64_type) ||
-                                   (expr_type == TypeManager.int64_type) ||
-                                   (expr_type == TypeManager.float_type) ||
-                                   (expr_type == TypeManager.double_type) ||
-                                   (expr_type == TypeManager.decimal_type) ||
-                                   (expr_type == TypeManager.string_type))
-
-                                       return true;
-
                        } else if (target_type == TypeManager.decimal_type){
                                if (expr_type == TypeManager.float_type ||
                                    expr_type == TypeManager.double_type)
@@ -2088,30 +2046,6 @@ namespace Mono.MonoBASIC {
                                        Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
                                        return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I8);
                                }
-                                   
-                       } else if (target_type == TypeManager.char_type){
-                               //
-                               // To char from ushort, int, uint, long, ulong, float, double
-                               // 
-                               if (expr_type == TypeManager.ushort_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_CH);
-                               if (expr_type == TypeManager.int32_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_CH);
-                               if (expr_type == TypeManager.uint32_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_CH);
-                               if (expr_type == TypeManager.uint64_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_CH);
-                               if (expr_type == TypeManager.int64_type) 
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_CH);
-
-                               if (expr_type == TypeManager.float_type) {
-                                       Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
-                                       return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_CH);
-                               }
-                               if (expr_type == TypeManager.double_type) {
-                                       Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
-                                       return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_CH);
-                               }
 
                        } else if (target_type == TypeManager.float_type){
                                //
@@ -2236,9 +2170,16 @@ namespace Mono.MonoBASIC {
                                        }
                                        break;  
                                case TypeCode.Byte:
-                                       // Ok, this *is* broken
-                                       e = RTConversionExpression(ec, "ByteType.FromObject", expr, loc);
-                                       break;  
+                                       
+                                       switch (src_type) {                                             
+                                               case TypeCode.String:                           
+                                                       e = RTConversionExpression(ec, "BooleanType.FromString", expr, loc);
+                                                       break;          
+                                               case TypeCode.Object:                           
+                                                       e = RTConversionExpression(ec, "ByteType.FromObject", expr, loc);
+                                                       break;  
+                                       }
+                                       break;
                                case TypeCode.Boolean:  
                                        switch (src_type) {                                             
                                                case TypeCode.String:                           
@@ -2354,6 +2295,12 @@ namespace Mono.MonoBASIC {
                        if (e != null)
                                return e;
 
+                       if (expr is StringConstant && target_type == TypeManager.char_type)
+                               return new CharConstant (((StringConstant) expr).Value [0]);
+
+                       if (expr is CharConstant && target_type == TypeManager.string_type)
+                               return new StringConstant (((CharConstant) expr).Value.ToString ());
+
                        e = ImplicitReferenceConversion (expr, target_type);
                        if (e != null)
                                return e;
@@ -2557,16 +2504,12 @@ namespace Mono.MonoBASIC {
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U4);
                                if (real_target_type == TypeManager.uint64_type)
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U8);
-                               if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_CH);
                        } else if (expr_type == TypeManager.byte_type){
                                //
                                // From byte to sbyte and char
                                //
                                if (real_target_type == TypeManager.sbyte_type)
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_I1);
-                               if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_CH);
                        } else if (expr_type == TypeManager.short_type){
                                //
                                // From short to sbyte, byte, ushort, uint, ulong, char
@@ -2581,8 +2524,6 @@ namespace Mono.MonoBASIC {
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U4);
                                if (real_target_type == TypeManager.uint64_type)
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U8);
-                               if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_CH);
                        } else if (expr_type == TypeManager.ushort_type){
                                //
                                // From ushort to sbyte, byte, short, char
@@ -2593,8 +2534,6 @@ namespace Mono.MonoBASIC {
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_U1);
                                if (real_target_type == TypeManager.short_type)
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I2);
-                               if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_CH);
                        } else if (expr_type == TypeManager.int32_type){
                                //
                                // From int to sbyte, byte, short, ushort, uint, ulong, char
@@ -2611,8 +2550,6 @@ namespace Mono.MonoBASIC {
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U4);
                                if (real_target_type == TypeManager.uint64_type)
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U8);
-                               if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_CH);
                        } else if (expr_type == TypeManager.uint32_type){
                                //
                                // From uint to sbyte, byte, short, ushort, int, char
@@ -2627,8 +2564,6 @@ namespace Mono.MonoBASIC {
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U2);
                                if (real_target_type == TypeManager.int32_type)
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I4);
-                               if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_CH);
                        } else if (expr_type == TypeManager.int64_type){
                                //
                                // From long to sbyte, byte, short, ushort, int, uint, ulong, char
@@ -2647,8 +2582,6 @@ namespace Mono.MonoBASIC {
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4);
                                if (real_target_type == TypeManager.uint64_type)
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U8);
-                               if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_CH);
                        } else if (expr_type == TypeManager.uint64_type){
                                //
                                // From ulong to sbyte, byte, short, ushort, int, uint, long, char
@@ -2667,18 +2600,6 @@ namespace Mono.MonoBASIC {
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U4);
                                if (real_target_type == TypeManager.int64_type)
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I8);
-                               if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_CH);
-                       } else if (expr_type == TypeManager.char_type){
-                               //
-                               // From char to sbyte, byte, short
-                               //
-                               if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_I1);
-                               if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_U1);
-                               if (real_target_type == TypeManager.short_type)
-                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_I2);
                        } else if (expr_type == TypeManager.float_type){
                                //
                                // From float to sbyte, byte, short,
@@ -2702,8 +2623,6 @@ namespace Mono.MonoBASIC {
                                        return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I8);
                                if (real_target_type == TypeManager.uint64_type)
                                        return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U8);
-                               if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_CH);
                        } else if (expr_type == TypeManager.double_type){
                                //
                                // From double to byte, byte, short,
@@ -2727,8 +2646,6 @@ namespace Mono.MonoBASIC {
                                        return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I8);
                                if (real_target_type == TypeManager.uint64_type)
                                        return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U8);
-                               if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_CH);
                                if (real_target_type == TypeManager.float_type)
                                        return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
                        } 
@@ -3154,7 +3071,7 @@ namespace Mono.MonoBASIC {
                
                static void Error_ConstantValueCannotBeConverted (Location l, string val, Type t)
                {
-                       Report.Error (31, l, "Constant value '" + val + "' cannot be converted to " +
+                       Report.Error (30439, l, "Constant value '" + val + "' not representable in type " +
                                      TypeManager.MonoBASIC_Name (t));
                }
 
@@ -3198,9 +3115,6 @@ namespace Mono.MonoBASIC {
                                if (target_type == TypeManager.uint32_type){
                                        if (v >= 0)
                                                return (uint) v;
-                               } else if (target_type == TypeManager.char_type){
-                                       if (v >= Char.MinValue && v <= Char.MaxValue)
-                                               return (char) v;
                                } else if (target_type == TypeManager.byte_type){
                                        if (v >= Byte.MinValue && v <= Byte.MaxValue)
                                                return (byte) v;
@@ -3227,9 +3141,6 @@ namespace Mono.MonoBASIC {
                                if (target_type == TypeManager.int32_type){
                                        if (v <= Int32.MaxValue)
                                                return (int) v;
-                               } else if (target_type == TypeManager.char_type){
-                                       if (v >= Char.MinValue && v <= Char.MaxValue)
-                                               return (char) v;
                                } else if (target_type == TypeManager.byte_type){
                                        if (v <= Byte.MaxValue)
                                                return (byte) v;
@@ -3256,9 +3167,6 @@ namespace Mono.MonoBASIC {
                                } else if (target_type == TypeManager.uint32_type){
                                        if (v >= 0 && v <= UInt32.MaxValue)
                                                return (uint) v;
-                               } else if (target_type == TypeManager.char_type){
-                                       if (v >= Char.MinValue && v <= Char.MaxValue)
-                                               return (char) v;
                                } else if (target_type == TypeManager.byte_type){
                                        if (v >= Byte.MinValue && v <= Byte.MaxValue)
                                                return (byte) v;
@@ -3285,9 +3193,6 @@ namespace Mono.MonoBASIC {
                                } else if (target_type == TypeManager.uint32_type){
                                        if (v <= UInt32.MaxValue)
                                                return (uint) v;
-                               } else if (target_type == TypeManager.char_type){
-                                       if (v >= Char.MinValue && v <= Char.MaxValue)
-                                               return (char) v;
                                } else if (target_type == TypeManager.byte_type){
                                        if (v >= Byte.MinValue && v <= Byte.MaxValue)
                                                return (byte) v;
@@ -3312,8 +3217,6 @@ namespace Mono.MonoBASIC {
                                        return (int) v;
                                else if (target_type == TypeManager.uint32_type)
                                        return (uint) v;
-                               else if (target_type == TypeManager.char_type)
-                                       return (char) v;
                                else if (target_type == TypeManager.sbyte_type){
                                        if (v <= SByte.MaxValue)
                                                return (sbyte) v;
@@ -3334,9 +3237,6 @@ namespace Mono.MonoBASIC {
                                else if (target_type == TypeManager.uint32_type){
                                        if (v >= 0)
                                                return (uint) v;
-                               } else if (target_type == TypeManager.char_type){
-                                       if (v >= 0)
-                                               return (char) v;
                                } else if (target_type == TypeManager.byte_type){
                                        if (v >= 0)
                                                return (byte) v;
@@ -3360,9 +3260,6 @@ namespace Mono.MonoBASIC {
                                } else if (target_type == TypeManager.uint32_type){
                                        if (v >= 0)
                                                return (uint) v;
-                               } else if (target_type == TypeManager.char_type){
-                                       if (v >= 0)
-                                               return (char) v;
                                } else if (target_type == TypeManager.byte_type){
                                        if (v >= Byte.MinValue && v <= Byte.MaxValue)
                                                return (byte) v;
@@ -3385,10 +3282,7 @@ namespace Mono.MonoBASIC {
                                        return (int) v;
                                else if (target_type == TypeManager.uint32_type)
                                        return (uint) v;
-                               else if (target_type == TypeManager.char_type){
-                                       if (v >= Char.MinValue && v <= Char.MaxValue)
-                                               return (char) v;
-                               } else if (target_type == TypeManager.byte_type){
+                               else if (target_type == TypeManager.byte_type){
                                        if (v >= Byte.MinValue && v <= Byte.MaxValue)
                                                return (byte) v;
                                } else if (target_type == TypeManager.sbyte_type){
@@ -3437,9 +3331,6 @@ namespace Mono.MonoBASIC {
                                 } else if (target_type == TypeManager.byte_type){
                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
                                                return new ByteConstant ((byte) System.Math.Round (v));
-                                } else if (target_type == TypeManager.char_type){
-                                        if (v >= Char.MinValue && v <= Char.MaxValue)
-                                               return (char) v;
                                 } else if (target_type == TypeManager.short_type){
                                         if (v >= Int16.MinValue && v <= Int16.MaxValue)
                                                return new ShortConstant ((short) System.Math.Round (v));
@@ -4263,6 +4154,20 @@ namespace Mono.MonoBASIC {
        /// </remarks>
        public class SimpleName : Expression, ITypeExpression {
                public readonly string Name;
+               bool is_invocation = false;
+               bool is_addressof = false;
+
+               public bool IsInvocation {
+                       set {
+                               is_invocation = value;
+                       }
+               }
+
+               public bool IsAddressOf {
+                       set {
+                               is_addressof = value;
+                       }
+               }
                
                public SimpleName (string name, Location l)
                {
@@ -4392,7 +4297,7 @@ namespace Mono.MonoBASIC {
                        if (ec.InvokingOwnOverload == false && current_block != null && current_block.IsVariableDefined (Name)){
                                LocalVariableReference var;
 
-                               var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
+                               var = new LocalVariableReference (current_block, Name, loc);
 
                                if (right_side != null)
                                        return var.ResolveLValue (ec, right_side);
@@ -4452,7 +4357,6 @@ namespace Mono.MonoBASIC {
 // #52067 - Start - Trying to solve
 
                        if (e == null) {
-                               
                                ArrayList lookups = new ArrayList();
                                ArrayList typelookups = new ArrayList();
                                
@@ -4492,17 +4396,50 @@ namespace Mono.MonoBASIC {
 
 // #52067 - End
 
-                       if (e == null)
-                               return DoResolveType (ec);
-
+                       if (e == null) {
+                       
+               /* preparing to support automatic definition of variables on first usage with Option Explicit Off
+                       
+                       Isn't good enough to enable just now (tries to define some internal links and breaks on emit)
+                       
+                               if (Name.IndexOf ('.') == -1 && current_block != null && !Mono.MonoBASIC.Parser.OptionExplicit) {
+                               
+                                       // while looking for a real solution
+                                       if (Name != "anything")
+                                               return DoResolveType (ec);
+                                               
+                                       Console.WriteLine("Implicitly adding a variable named '{0}'", Name);
+                                       
+                                       // TODO: look at type-suffixes to correct name and type
+                                       Expression type = Mono.MonoBASIC.Parser.DecomposeQI("System.Object", loc);
+                                       
+                                       current_block.AddVariable(ec, type, Name, loc);
+                               
+                                       LocalVariableReference var = new LocalVariableReference (current_block, Name, loc);
+                                       if (right_side != null)
+                                               return var.ResolveLValue (ec, right_side);
+                                       else
+                                               return var.Resolve (ec);
+                               } else
+               */
+                                       return DoResolveType (ec);
+                       }
+                       
                        if (e is TypeExpr)
                                return e;
 
                        if (e is IMemberExpr) {
+                               if ((e is MethodGroupExpr) && !is_invocation && !is_addressof) {
+                                       Expression inv = new Invocation (this, new ArrayList (), loc);
+                                       return inv.Resolve (ec);
+                               }
                                e = MemberAccess.ResolveMemberAccess (ec, e, null, loc, this);
                                if (e == null)
                                        return null;
 
+                               if (e is PropertyGroupExpr && is_invocation) // We dont know the arguments yet
+                                       return e;
+
                                IMemberExpr me = e as IMemberExpr;
                                if (me == null)
                                        return e;
@@ -4523,21 +4460,26 @@ namespace Mono.MonoBASIC {
                                        return null;
                                }
 */
+                               bool isPropertyGroup = (e is PropertyGroupExpr);
                                if (right_side != null)
                                        e = e.DoResolveLValue (ec, right_side);
                                else
                                        e = e.DoResolve (ec);
 
+                               if (e == null && isPropertyGroup && !is_invocation)
+                                        Error (30057, "Property '" + Name + "' cannot be invoked with given arguments");
+                                        
                                return e;
                        }
 
-                       if (ec.IsStatic || ec.IsFieldInitializer){
+                       if (ec.IsStatic || ec.IsFieldInitializer) {
                                if (allow_static)
                                        return e;
 
                                return MemberStaticCheck (ec, e);
-                       } else
-                               return e;
+                       }
+
+                       return e;
                }
                
                public override void Emit (EmitContext ec)
@@ -4557,6 +4499,36 @@ namespace Mono.MonoBASIC {
                        return Name;
                }
        }
+
+       public class DecoratedIdentifier : Expression {
+               Expression id;
+               Type decoration;
+
+               public DecoratedIdentifier (Expression id, Type decoration)
+               {
+                       this.id = id;
+                       this.decoration = decoration;
+               }
+
+               override public Expression DoResolve (EmitContext ec)
+               {
+                       if (id == null || decoration == null)
+                               return null;
+                       
+                       Expression ret = id.DoResolve (ec);
+                       if (ret.Type != TypeManager.TypeToCoreType (decoration)) {
+                               Report.Error (30277, id.Location, "Type character '" + decoration + "' does not match declared type '" + ret.Type  + "'."); 
+                               return null;
+                       }
+
+                       return ret;
+               }
+               
+               override public void Emit (EmitContext ec)
+               {
+                       throw new InternalErrorException ("Should never be called");
+               }
+       }
        
        /// <summary>
        ///   Fully resolved expression that evaluates to a type
@@ -4779,6 +4751,264 @@ namespace Mono.MonoBASIC {
                }
        }
 
+       /// <summary>
+       ///   Property Group Expression.
+       ///  
+       /// </summary>
+       public class PropertyGroupExpr : ExpressionStatement, IMemberExpr {
+               public PropertyInfo [] Properties;
+               Expression instance_expression = null;
+               bool is_explicit_impl = false;
+               MethodBase method = null;
+               bool indexer_access_req = false;
+               ArrayList arguments = null;
+               
+               public PropertyGroupExpr (MemberInfo [] mi, Location l)
+               {
+                       Properties = new PropertyInfo [mi.Length];
+                       mi.CopyTo (Properties, 0);
+                       eclass = ExprClass.PropertyAccess;
+                       type = TypeManager.object_type;
+                       loc = l;
+               }
+
+               public PropertyGroupExpr (MemberInfo [] mi, ArrayList args, Expression expr, Location l)
+                       : this (mi, l)
+               {
+                       arguments = args;
+                       instance_expression = expr;
+               }
+
+               public PropertyGroupExpr (ArrayList list, Location l)
+               {
+                       Properties = new PropertyInfo [list.Count];
+
+                       try {
+                               list.CopyTo (Properties, 0);
+                       } catch {
+                               foreach (MemberInfo m in list){
+                                       if (!(m is PropertyInfo)){
+                                               Console.WriteLine ("Name " + m.Name);
+                                               Console.WriteLine ("Found a: " + m.GetType ().FullName);
+                                       }
+                               }
+                               throw;
+                       }
+                       loc = l;
+                       eclass = ExprClass.PropertyAccess;
+                       type = TypeManager.object_type;
+               }
+
+               public ArrayList Arguments {
+                       get {
+                               return arguments;
+                       }
+                       set {
+                               arguments = value;
+                       }
+               }
+
+               public Type DeclaringType {
+                       get {
+                               return Properties [0].DeclaringType;
+                       }
+               }
+
+               public bool IndexerAccessRequired {
+                       get {
+                               return indexer_access_req;
+                       }
+               }
+
+               //
+               // 'A method group may have associated an instance expression' 
+               // 
+               public Expression InstanceExpression {
+                       get {
+                               return instance_expression;
+                       }
+
+                       set {
+                               instance_expression = value;
+                       }
+               }
+
+               public bool IsExplicitImpl {
+                       get {
+                               return is_explicit_impl;
+                       }
+
+                       set {
+                               is_explicit_impl = value;
+                       }
+               }
+
+               public string Name {
+                       get {
+                               return Properties [0].Name;
+                       }
+               }
+
+               public bool IsInstance {
+                       get {
+                               foreach (PropertyInfo pi in Properties) {
+                                       MethodInfo mi = pi.GetGetMethod ();
+                                       if (mi != null && !mi.IsStatic)
+                                               return true;
+                                       mi = pi.GetSetMethod ();
+                                       if (mi != null && !mi.IsStatic)
+                                               return true;
+                               }               
+                               return false;
+                       }
+               }
+
+               public bool IsStatic {
+                       get {
+                               return (!IsInstance);
+                       }
+               }
+               
+               public ArrayList GetAccessors () {
+                       ArrayList GetAccessors = new ArrayList ();
+                       foreach (PropertyInfo pi in Properties) {
+                               if (pi.GetGetMethod () != null)
+                                       GetAccessors.Add (pi.GetGetMethod ());
+/*
+                               else if (pi.GetGetMethod (true) != null)
+                                       GetAccessors.Add (pi.GetGetMethod (true));
+*/
+                                       
+                       }
+                       return GetAccessors;
+               }
+               
+               public ArrayList SetAccessors () {
+                       ArrayList SetAccessors = new ArrayList ();
+                       foreach (PropertyInfo pi in Properties) {
+                               if (pi.GetSetMethod () != null)
+                                       SetAccessors.Add (pi.GetSetMethod ());
+/*
+                               else if (pi.GetSetMethod (true) != null)
+                                       SetAccessors.Add (pi.GetSetMethod (true));
+*/
+                       }
+                       return SetAccessors;
+               }
+
+               override public Expression DoResolve (EmitContext ec)
+               {
+                       if (instance_expression != null) {
+                               instance_expression = instance_expression.DoResolve (ec);
+                               if (instance_expression == null)
+                                       return null;
+                       }
+
+                       ArrayList members = GetAccessors ();
+                       if (members == null || members.Count == 0) {
+                               Report.Error (30524, loc, "Property '" + Name + "' lacks a 'get' accesor");
+                               return null;
+                       }
+
+                       MethodGroupExpr m_expr = new MethodGroupExpr (members, loc);
+                       method = Invocation.OverloadResolve (ec, m_expr, ref arguments, loc);
+                       if ((method as MethodInfo) != null) {
+                               MethodInfo mi = method as MethodInfo;
+                               type = TypeManager.TypeToCoreType (mi.ReturnType);
+                               indexer_access_req = false;
+                               eclass = ExprClass.Value;
+                               return this;
+                       } else {
+                               // find a get method that doesnt take any arguments. Check the return type of
+                               // that method to find out if indexer access is required. Leave the rest to
+                               // 'Invocation's Resolve'
+                               method = Invocation.OverloadResolve (ec, m_expr, null, loc);
+                               if (method != null) {
+                                       MethodInfo mi = method as MethodInfo;
+                                       Type ret_type = mi.ReturnType;
+                                       if (ret_type.IsArray)
+                                               indexer_access_req = true;
+                                       else {
+                                               Indexers list = Indexers.GetIndexersForType (ec.ContainerType, ret_type, loc);
+                                               if (list != null && list.getters.Count > 0)
+                                                       indexer_access_req = true;
+                                               else 
+                                                       return null;
+                                       }
+                                       Arguments = null;
+                                       type = mi.ReturnType;
+                                       return this;
+                               }
+                       }
+
+                       return null;
+               }
+
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side) {
+                       if (instance_expression != null) {
+                               instance_expression = instance_expression.DoResolve (ec);
+                               if (instance_expression == null)
+                                       return null;
+                       }
+
+                       ArrayList members = SetAccessors ();
+                       if (members == null || members.Count == 0) {
+                               Report.Error (30524, loc, "Property '" + Name + "' lacks a 'set' accesor");
+                               return null;
+                       }
+
+                       MethodGroupExpr m_expr = new MethodGroupExpr (members, loc);
+                       if (arguments == null)
+                               arguments = new ArrayList ();
+                       arguments.Add (new Argument (right_side, Argument.AType.Expression));
+                       method = Invocation.OverloadResolve (ec, m_expr, ref arguments, loc);
+                       if (method != null) {
+                               //MethodInfo mi = method as MethodInfo;
+                               type = TypeManager.void_type; //TypeManager.TypeToCoreType (mi.ReturnType);
+                               eclass = ExprClass.Value;
+                               indexer_access_req = false;
+                               return this;
+                       } else {
+                               // Look for properties that do not take any arguments.
+                               // Check if the return type has any indexers
+                               arguments = null;
+                               DoResolve (ec);
+                               if (method != null) {
+                                       MethodInfo mi = method as MethodInfo;
+                                       Type ret_type = mi.ReturnType;
+                                       if (ret_type.IsArray)
+                                               indexer_access_req = true;
+                                       else {
+
+                                               Indexers list = Indexers.GetIndexersForType (ec.ContainerType, 
+                                                                       ret_type, loc);
+                                               if (list != null && list.setters.Count > 0)
+                                                       indexer_access_req = true;
+                                               else 
+                                                       return null;
+                                       }
+                                       type = mi.ReturnType;
+                                       return this;
+                               }
+                       }
+
+                       return null;
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       if (Arguments == null)
+                               Arguments = new ArrayList ();
+                       Invocation.EmitCall (ec, false, IsStatic, instance_expression, method, null, Arguments, loc);
+               }
+
+               override public void EmitStatement (EmitContext ec) 
+               {
+                       Emit (ec);
+               }
+
+       }
+
        /// <summary>
        ///   Fully resolved expression that evaluates to a Field
        /// </summary>