Import changes from mainline
authorMiguel de Icaza <miguel@gnome.org>
Fri, 8 Aug 2003 05:49:37 +0000 (05:49 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Fri, 8 Aug 2003 05:49:37 +0000 (05:49 -0000)
svn path=/trunk/mcs/; revision=17186

17 files changed:
mcs/gmcs/ChangeLog
mcs/gmcs/Makefile
mcs/gmcs/assign.cs
mcs/gmcs/attribute.cs
mcs/gmcs/class.cs
mcs/gmcs/codegen.cs
mcs/gmcs/convert.cs
mcs/gmcs/cs-parser.jay
mcs/gmcs/cs-tokenizer.cs
mcs/gmcs/driver.cs
mcs/gmcs/ecore.cs
mcs/gmcs/expression.cs
mcs/gmcs/iterators.cs
mcs/gmcs/namespace.cs
mcs/gmcs/statement.cs
mcs/gmcs/support.cs
mcs/gmcs/typemanager.cs

index 790707e69d05242ef6730f1b60d5366d6f532d8b..88ab72582401a7067c2d3ba1b896622dd54388f0 100755 (executable)
@@ -1,3 +1,185 @@
+2003-08-08  Martin Baulig  <martin@ximian.com>
+
+       * flowanalysis.cs (FlowReturns): This is now nested in the
+       `FlowBranching' class.
+       (MyBitVector): Moved this here from statement.cs.
+       (FlowBranching.SiblingType): New enum type.
+       (FlowBranching.CreateSibling): Added `SiblingType' argument.
+
+2003-08-07  Martin Baulig  <martin@ximian.com>
+
+       * flowanalysis.cs (FlowBranchingType): This is now nested in the
+       `FlowBranching' class and called `BranchingType'.
+
+2003-08-07  Martin Baulig  <martin@ximian.com>
+
+       * flowanalysis.cs: Moved all the control flow analysis code into
+       its own file.
+
+2003-08-07  Martin Baulig  <martin@ximian.com>
+
+       * assign.cs (Assign.DoResolve): `target' must either be an
+       IAssignMethod or an EventAccess; report a CS0131 otherwise.  Fixes
+       #37319.
+
+2003-08-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (BinaryMethod): This kind of expression is created by the
+       Binary class if it determines that the operator has to be handled
+       by a method.
+
+       (BinaryDelegate): This kind of expression is created if we are
+       dealing with a + or - operator on delegates.
+
+       (Binary): remove method, argumetns, and DelegateOperator: when
+       dealing with methods, 
+       
+       * ecore.cs (EventExpr.EmitAddOrRemove): Update to new layout.
+
+       * statement.cs (Block): use bitfields for the three extra booleans
+       we had in use.   Remove unused topblock parameter.
+
+       * codegen.cs: Remove unecessary argument to Block.EmitTopBlock
+
+       * assign.cs: Drop extra unneeded tests.
+
+2003-08-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * iterators.cs (Mapvariable): provide a mechanism to use prefixes.
+
+       * statement.cs (Foreach): Use VariableStorage instead of
+       LocalBuilders.   
+
+       * codegen.cs (VariableStorage): New class used by clients that
+       require a variable stored: locals or fields for variables that
+       need to live across yield.
+
+       Maybe provide a convenience api for EmitThis+EmitLoad?
+
+       (GetTemporaryLocal, FreeTemporaryLocal): Recycle
+       these bad boys.
+
+2003-08-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs (RemapLocal, RemapLocalLValue, RemapParameter,
+       RemapParameterLValue): New methods that are used to turn a
+       precomputed FieldInfo into an expression like this:
+
+               instance.FieldInfo
+
+       The idea is to use this instead of making LocalVariableReference
+       have more than one meaning.
+
+       * cs-parser.jay: Add error production to BASE.
+
+       * ecore.cs: Deal with TypeManager.GetField returning null, which
+       is now a valid return value.
+
+       (FieldExprNoAddress): New expression for Fields whose address can
+       not be taken.
+
+       * expression.cs (LocalVariableReference): During the resolve
+       phases, create new expressions if we are in a remapping context.
+       Remove code that dealt with remapping here.
+
+       (ParameterReference): same.
+
+       (ProxyInstance): New expression, like the `This' expression, but
+       it is born fully resolved.  We know what we are doing, so remove
+       the errors that are targeted to user-provided uses of `this'.
+
+       * statement.cs (Foreach): our variable is now stored as an
+       Expression;  During resolution, follow the protocol, dont just
+       assume it will return this.
+       
+2003-08-06  Martin Baulig  <martin@ximian.com>
+
+       * support.cs (SeekableStreamReader.cs): New public class.
+
+       * cs-tokenizer.cs, cs-parser.jay, driver.cs: Use the new
+       SeekableStreamReader instead of the normal StreamReader.
+
+2003-08-04  Martin Baulig  <martin@ximian.com>
+
+       * cs-parser.jay (CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST,
+       CLOSE_PARENS_OPEN_PARENS, CLOSE_PARENS_MINUS): New tokens to
+       deambiguate casts and delegate invocations.
+       (parenthesized_expression): Use the new tokens to ensure this is
+       not a cast of method invocation.
+
+       * cs-tokenizer.cs (is_punct): Return one of the new special tokens
+       when reading a `)' and Deambiguate_CloseParens () was previously
+       called.
+
+       * expression.cs (ParenthesizedExpression): New class.  This is
+       just used for the CS0075 test.
+       (Binary.DoResolve): Check for CS0075.   
+
+2003-07-29  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Invocation.MakeUnionSet): Patch from Lluis
+       Sanchez : use TypeManager.ArrayContainsMethod instead of a direct
+       reference comparison.
+
+       (TypeManager.ArrayContainsMethod): When we have a MethodInfo, also
+       examine the ReturnType for equality - this is necessary in the
+       cases of implicit and explicit operators whose signature also
+       includes the return type.
+
+2003-07-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * namespace.cs: Cache the result of the namespace computation,
+       instead of computing it every time.
+
+2003-07-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * decl.cs: Use a global arraylist that we reuse over invocations
+       to avoid excesive memory consumption.  Reduces memory usage on an
+       mcs compile by one meg (45 average).
+
+       * typemanager.cs (LookupTypeReflection): In .NET pointers are
+       private, work around that.
+
+2003-07-23  Miguel de Icaza  <miguel@ximian.com>
+
+       * literal.cs (IntLiteral): Define Zero and One static literals. 
+
+       * cs-parser.jay (integer_literal): use static literals to reduce
+       memory usage for the most used literals (0, 1 and -1).  211kb
+       reduced in memory usage.
+
+       Replace all calls to `new ArrayList' with `new
+       ArrayList(4)' which is a good average number for most allocations,
+       and also requires only 16 bytes of memory for its buffer by
+       default. 
+
+       This reduced MCS memory usage in seven megabytes for the RSS after
+       bootstrapping.
+
+2003-07-28  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Invocation.OverloadResolve): Fix the algorithm to
+       handle params methods the correct way by forming only one
+       applicable set with params and normal methods in them. Earlier we
+       were looking at params methods only if we found no normal methods
+       which was not the correct thing to do.
+
+       (Invocation.BetterFunction): Take separate arguments indicating
+       when candidate and the best method are params methods in their
+       expanded form.
+
+       This fixes bugs #43367 and #46199.
+
+       * attribute.cs: Documentation updates.
+
+       (CheckAttribute): Rename to CheckAttributeTarget.
+       (GetValidPlaces): Rename to GetValidTargets.
+
+       * expression.cs (Invocation.IsParamsMethodApplicable): Fix trivial
+       bug - use Convert.ImplicitConversion, not ImplicitUserConversion!
+
+       Fixes bug #44468.
+
 2003-07-28  Miguel de Icaza  <miguel@ximian.com>
 
        * codegen.cs: Compute IsGeneric correctly.
index 0374b1e90cd81a599238ce174d846b1784734e21..d16d330b4929957e8c3425815950bea04e699255 100644 (file)
@@ -20,6 +20,7 @@ COMPILER_SOURCES = \
        enum.cs                         \
        ecore.cs                        \
        expression.cs                   \
+       flowanalysis.cs                 \
        generic.cs                      \
        interface.cs                    \
        iterators.cs                    \
@@ -84,3 +85,6 @@ mcs2.exe: gmcs.exe
 
 mcs3.exe: mcs2.exe
        $(TIME) $(RUNTIME) ./mcs2.exe $(USE_MCS_FLAGS) /target:exe /out:$@ $(all_sources)
+
+response:
+       echo $(all_sources) > res
index 9153f63d59def71fec28121667946c6913bfc180..b489fc60d27e8bc2642ded2c169535689b764c69 100755 (executable)
@@ -64,12 +64,12 @@ namespace Mono.CSharp {
                        type = t;
                        eclass = ExprClass.Value;
                        loc = Location.Null;
-                       builder = ec.GetTemporaryStorage (t);
+                       builder = ec.GetTemporaryLocal (t);
                }
 
                public void Release (EmitContext ec)
                {
-                       ec.FreeTemporaryStorage (builder);
+                       ec.FreeTemporaryLocal (builder, type);
                        builder = null;
                }
                
@@ -235,17 +235,10 @@ namespace Mono.CSharp {
                                        // it will appear as a FieldExpr in that case.
                                        //
                                        
-                                       if (!(source is Binary)) {
+                                       if (!(source is BinaryDelegate)) {
                                                error70 (ei, loc);
                                                return null;
-                                       } else {
-                                               Binary tmp = ((Binary) source);
-                                               if (tmp.Oper != Binary.Operator.Addition &&
-                                                   tmp.Oper != Binary.Operator.Subtraction) {
-                                                       error70 (ei, loc);
-                                                       return null;
-                                               }
-                                       }
+                                       } 
                                }
                        }
                        
@@ -259,8 +252,7 @@ namespace Mono.CSharp {
                                        return null;
                        }
 
-                       if (target.eclass != ExprClass.Variable && target.eclass != ExprClass.EventAccess &&
-                           target.eclass != ExprClass.IndexerAccess && target.eclass != ExprClass.PropertyAccess){
+                       if (!(target is IAssignMethod) && (target.eclass != ExprClass.EventAccess)) {
                                Report.Error (131, loc,
                                              "Left hand of an assignment must be a variable, " +
                                              "a property or an indexer");
@@ -288,7 +280,7 @@ namespace Mono.CSharp {
                                CompoundAssign a = (CompoundAssign) this;
                                
                                Binary b = source as Binary;
-                               if (b != null && b.IsBuiltinOperator){
+                               if (b != null){
                                        //
                                        // 1. if the source is explicitly convertible to the
                                        //    target_type
index 9f9c3c144ef2ac005dba99bc85339f5d08f12767..9a2c11243237472007a183ffc80716bc4be06d64 100644 (file)
@@ -30,7 +30,7 @@ namespace Mono.CSharp {
                \r
                //\r
                // The following are only meaningful when the attribute\r
-               // being emitted is one of the builtin ones\r
+               // being emitted is an AttributeUsage attribute\r
                //\r
                AttributeTargets Targets;\r
                bool AllowMultiple;\r
@@ -42,7 +42,7 @@ namespace Mono.CSharp {
                UnmanagedType     UnmanagedType;\r
                CustomAttributeBuilder cb;\r
        \r
-               /* non-null if named args present after Resolve () is called */\r
+               // non-null if named args present after Resolve () is called\r
                PropertyInfo [] prop_info_arr;\r
                FieldInfo [] field_info_arr;\r
                object [] field_values_arr;\r
@@ -81,7 +81,10 @@ namespace Mono.CSharp {
                        Report.Error (\r
                                -202, loc, "Can not use a type parameter in an attribute");\r
                }\r
-               \r
+\r
+               /// <summary>\r
+                ///   Tries to resolve the type of the attribute. Flags an error if it can't.\r
+                /// </summary>\r
                private Type CheckAttributeType (EmitContext ec) {\r
                        Type t;\r
                        bool isattributeclass = true;\r
@@ -167,6 +170,12 @@ namespace Mono.CSharp {
                        UsageAttr = false;\r
 \r
                        bool DoCompares = true;\r
+\r
+                        //\r
+                        // If we are a certain special attribute, we\r
+                        // set the information accordingly\r
+                        //\r
+                        \r
                        if (Type == TypeManager.attribute_usage_type)\r
                                UsageAttr = true;\r
                        else if (Type == TypeManager.methodimpl_attr_type)\r
@@ -425,7 +434,8 @@ namespace Mono.CSharp {
                                // Don't know what to do here\r
                                //\r
                                Report.Warning (\r
-                                       -100, Location, "NullReferenceException while trying to create attribute. Something's wrong!");\r
+                                       -100, Location, "NullReferenceException while trying to create attribute." +\r
+                                        "Something's wrong!");\r
                        } catch (Exception e) {\r
                                //\r
                                // Sample:\r
@@ -442,7 +452,10 @@ namespace Mono.CSharp {
                        return cb;\r
                }\r
 \r
-               static string GetValidPlaces (Attribute attr)\r
+                /// <summary>\r
+                ///   Get a string containing a list of valid targets for the attribute 'attr'\r
+                /// </summary>\r
+               static string GetValidTargets (Attribute attr)\r
                {\r
                        StringBuilder sb = new StringBuilder ();\r
                        AttributeTargets targets = 0;\r
@@ -523,10 +536,13 @@ namespace Mono.CSharp {
                        Report.Error (\r
                                592, loc, "Attribute '" + a.Name +\r
                                "' is not valid on this declaration type. " +\r
-                               "It is valid on " + GetValidPlaces (a) + "declarations only.");\r
+                               "It is valid on " + GetValidTargets (a) + "declarations only.");\r
                }\r
 \r
-               public static bool CheckAttribute (Attribute a, object element)\r
+                /// <summary>\r
+                ///   Ensure that Attribute 'a' is being applied to the right target\r
+                /// </summary>\r
+               public static bool CheckAttributeTarget (Attribute a, object element)\r
                {\r
                        TypeContainer attr = TypeManager.LookupAttr (a.Type);\r
                        AttributeTargets targets = 0;\r
@@ -742,7 +758,8 @@ namespace Mono.CSharp {
                        return ((StringConstant) arg.Expr).Value;\r
                }\r
 \r
-               static object GetFieldValue (Attribute a, string name) {\r
+               static object GetFieldValue (Attribute a, string name)\r
+                {\r
                        int i;\r
                        if (a.field_info_arr == null)\r
                                return null;\r
@@ -755,11 +772,13 @@ namespace Mono.CSharp {
                        return null;\r
                }\r
 \r
-               static UnmanagedMarshal GetMarshal (Attribute a) {\r
+               static UnmanagedMarshal GetMarshal (Attribute a)\r
+                {\r
                        UnmanagedMarshal marshal;\r
 \r
                        if (a.UnmanagedType == UnmanagedType.CustomMarshaler) {\r
-                               MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom", BindingFlags.Static | BindingFlags.Public);\r
+                               MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",\r
+                                                                       BindingFlags.Static | BindingFlags.Public);\r
                                if (define_custom == null) {\r
                                        return null;\r
                                }\r
@@ -778,9 +797,9 @@ namespace Mono.CSharp {
                        return marshal;\r
                }\r
 \r
-               //\r
-               // Applies the attributes to the `builder'.\r
-               //\r
+               /// <summary>\r
+               ///   Applies the attributes specified on target 'kind' to the `builder'.\r
+               /// </summary>\r
                public static void ApplyAttributes (EmitContext ec, object builder, object kind,\r
                                                    Attributes opt_attrs)\r
                {\r
@@ -815,7 +834,7 @@ namespace Mono.CSharp {
                                                continue;\r
                                        \r
                                        if (!(kind is TypeContainer))\r
-                                               if (!CheckAttribute (a, kind)) {\r
+                                               if (!CheckAttributeTarget (a, kind)) {\r
                                                        Error_AttributeNotValidForElement (a, loc);\r
                                                        return;\r
                                                }\r
@@ -898,7 +917,7 @@ namespace Mono.CSharp {
                                                        }\r
 \r
                                                } else {\r
-                                                       if (!CheckAttribute (a, kind)) {\r
+                                                       if (!CheckAttributeTarget (a, kind)) {\r
                                                                Error_AttributeNotValidForElement (a, loc);\r
                                                                return;\r
                                                        }\r
@@ -928,7 +947,7 @@ namespace Mono.CSharp {
                                                        return;\r
                                                }\r
 \r
-                                               if (!CheckAttribute (a, kind)) {\r
+                                               if (!CheckAttributeTarget (a, kind)) {\r
                                                        Error_AttributeNotValidForElement (a, loc);\r
                                                        return;\r
                                                }\r
index 90634591501c4885092db214c93095a28bd18dbf..c80cb78877c0bed0d1a1c7428d94450c4f971aa2 100755 (executable)
@@ -2304,7 +2304,8 @@ namespace Mono.CSharp {
 
                                                if (par_attr == ParameterAttributes.Out){
                                                        if (attr.Contains (TypeManager.in_attribute_type))
-                                                               Report.Error (36, Location, "Can not use [In] attribute on out parameter");
+                                                               Report.Error (36, Location,
+                                                                    "Can not use [In] attribute on out parameter");
                                                }
                                        }
                                }
@@ -2356,7 +2357,8 @@ namespace Mono.CSharp {
                                } catch (ArgumentOutOfRangeException) {
                                        Report.Warning (
                                                -24, Location,
-                                               ".NET SDK 1.0 does not permit to set custom attributes to the return type of a method");
+                                               ".NET SDK 1.0 does not permit setting custom attributes" +
+                                                " on the return type of a method");
                                }
                        }
                }
index 96d58cbb76319eef8fcd42b915ac79ea2e4da91f..7293f99df5a4ba2d4a1538ee6076b01420162e76 100755 (executable)
@@ -119,6 +119,52 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // Provides "local" store across code that can yield: locals
+       // or fields, notice that this should not be used by anonymous
+       // methods to create local storage, those only require
+       // variable mapping.
+       //
+       public class VariableStorage {
+               ILGenerator ig;
+               FieldBuilder fb;
+               LocalBuilder local;
+               
+               static int count;
+               
+               public VariableStorage (EmitContext ec, Type t)
+               {
+                       count++;
+                       if (ec.InIterator)
+                               fb = IteratorHandler.Current.MapVariable ("s_", count.ToString (), t);
+                       else
+                               local = ec.ig.DeclareLocal (t);
+                       ig = ec.ig;
+               }
+
+               public void EmitThis ()
+               {
+                       if (fb != null)
+                               ig.Emit (OpCodes.Ldarg_0);
+               }
+
+               public void EmitStore ()
+               {
+                       if (fb == null)
+                               ig.Emit (OpCodes.Stloc, local);
+                       else
+                               ig.Emit (OpCodes.Stfld, fb);
+               }
+
+               public void EmitLoad ()
+               {
+                       if (fb == null)
+                               ig.Emit (OpCodes.Ldloc, local);
+                       else 
+                               ig.Emit (OpCodes.Ldfld, fb);
+               }
+       }
+       
        /// <summary>
        ///   An Emit Context is created for each body of code (from methods,
        ///   properties bodies, indexer bodies or constructor bodies)
@@ -344,7 +390,7 @@ namespace Mono.CSharp {
                //   Starts a new code branching.  This inherits the state of all local
                //   variables and parameters from the current branching.
                // </summary>
-               public FlowBranching StartFlowBranching (FlowBranchingType type, Location loc)
+               public FlowBranching StartFlowBranching (FlowBranching.BranchingType type, Location loc)
                {
                        FlowBranching cfb = new FlowBranching (CurrentBranching, type, null, loc);
 
@@ -359,12 +405,12 @@ namespace Mono.CSharp {
                public FlowBranching StartFlowBranching (Block block)
                {
                        FlowBranching cfb;
-                       FlowBranchingType type;
+                       FlowBranching.BranchingType type;
 
-                       if (CurrentBranching.Type == FlowBranchingType.SWITCH)
-                               type = FlowBranchingType.SWITCH_SECTION;
+                       if (CurrentBranching.Type == FlowBranching.BranchingType.Switch)
+                               type = FlowBranching.BranchingType.SwitchSection;
                        else
-                               type = FlowBranchingType.BLOCK;
+                               type = FlowBranching.BranchingType.Block;
 
                        cfb = new FlowBranching (CurrentBranching, type, block, block.StartLocation);
 
@@ -377,7 +423,7 @@ namespace Mono.CSharp {
                //   Ends a code branching.  Merges the state of locals and parameters
                //   from all the children of the ending branching.
                // </summary>
-               public FlowReturns EndFlowBranching ()
+               public FlowBranching.FlowReturns EndFlowBranching ()
                {
                        FlowBranching cfb = (FlowBranching) FlowStack.Pop ();
 
@@ -404,7 +450,7 @@ namespace Mono.CSharp {
                            try {
                                int errors = Report.Errors;
 
-                               block.EmitMeta (this, ip, block);
+                               block.EmitMeta (this, ip);
 
                                if (Report.Errors == errors){
                                        bool old_do_flow_analysis = DoFlowAnalysis;
@@ -420,15 +466,15 @@ namespace Mono.CSharp {
                                        }
 
                                        cfb = (FlowBranching) FlowStack.Pop ();
-                                       FlowReturns returns = cfb.MergeTopBlock ();
+                                       FlowBranching.FlowReturns returns = cfb.MergeTopBlock ();
 
                                        DoFlowAnalysis = old_do_flow_analysis;
 
                                        has_ret = block.Emit (this);
 
-                                       if ((returns == FlowReturns.ALWAYS) ||
-                                           (returns == FlowReturns.EXCEPTION) ||
-                                           (returns == FlowReturns.UNREACHABLE))
+                                       if ((returns == FlowBranching.FlowReturns.Always) ||
+                                           (returns == FlowBranching.FlowReturns.Exception) ||
+                                           (returns == FlowBranching.FlowReturns.Unreachable))
                                                has_ret = true;
 
                                        if (Report.Errors == errors){
@@ -508,24 +554,60 @@ namespace Mono.CSharp {
                ///   Returns a temporary storage for a variable of type t as 
                ///   a local variable in the current body.
                /// </summary>
-               public LocalBuilder GetTemporaryStorage (Type t)
+               public LocalBuilder GetTemporaryLocal (Type t)
                {
-                       LocalBuilder location;
+                       LocalBuilder location = null;
                        
                        if (temporary_storage != null){
-                               location = (LocalBuilder) temporary_storage [t];
-                               if (location != null)
-                                       return location;
+                               object o = temporary_storage [t];
+                               if (o != null){
+                                       if (o is ArrayList){
+                                               ArrayList al = (ArrayList) o;
+                                               
+                                               for (int i = 0; i < al.Count; i++){
+                                                       if (al [i] != null){
+                                                               location = (LocalBuilder) al [i];
+                                                               al [i] = null;
+                                                               break;
+                                                       }
+                                               }
+                                       } else
+                                               location = (LocalBuilder) o;
+                                       if (location != null)
+                                               return location;
+                               }
                        }
                        
-                       location = ig.DeclareLocal (t);
-                       
-                       return location;
+                       return ig.DeclareLocal (t);
                }
 
-               public void FreeTemporaryStorage (LocalBuilder b)
+               public void FreeTemporaryLocal (LocalBuilder b, Type t)
                {
-                       // Empty for now.
+                       if (temporary_storage == null){
+                               temporary_storage = new Hashtable ();
+                               temporary_storage [t] = b;
+                               return;
+                       }
+                       object o = temporary_storage [t];
+                       if (o == null){
+                               temporary_storage [t] = b;
+                               return;
+                       }
+                       if (o is ArrayList){
+                               ArrayList al = (ArrayList) o;
+                               for (int i = 0; i < al.Count; i++){
+                                       if (al [i] == null){
+                                               al [i] = b;
+                                               return;
+                                       }
+                               }
+                               al.Add (b);
+                               return;
+                       }
+                       ArrayList replacement = new ArrayList ();
+                       replacement.Add (o);
+                       temporary_storage.Remove (t);
+                       temporary_storage [t] = replacement;
                }
 
                /// <summary>
@@ -583,12 +665,44 @@ namespace Mono.CSharp {
                public FieldBuilder MapVariable (string name, Type t)
                {
                        if (InIterator){
-                               return IteratorHandler.Current.MapVariable (name, t);
+                               return IteratorHandler.Current.MapVariable ("v_", name, t);
                        }
 
                        throw new Exception ("MapVariable for an unknown state");
                }
 
+               //
+               // Invoke this routine to remap a VariableInfo into the
+               // proper MemberAccess expression
+               //
+               public Expression RemapLocal (LocalInfo local_info)
+               {
+                       FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc);
+                       fe.InstanceExpression = new ProxyInstance ();
+                       return fe.DoResolve (this);
+               }
+
+               public Expression RemapLocalLValue (LocalInfo local_info, Expression right_side)
+               {
+                       FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc);
+                       fe.InstanceExpression = new ProxyInstance ();
+                       return fe.DoResolveLValue (this, right_side);
+               }
+
+               public Expression RemapParameter (int idx)
+               {
+                       FieldExpr fe = new FieldExprNoAddress (IteratorHandler.Current.parameter_fields [idx], loc);
+                       fe.InstanceExpression = new ProxyInstance ();
+                       return fe.DoResolve (this);
+               }
+
+               public Expression RemapParameterLValue (int idx, Expression right_side)
+               {
+                       FieldExpr fe = new FieldExprNoAddress (IteratorHandler.Current.parameter_fields [idx], loc);
+                       fe.InstanceExpression = new ProxyInstance ();
+                       return fe.DoResolveLValue (this, right_side);
+               }
+               
                //
                // Emits the proper object to address fields on a remapped
                // variable/parameter to field in anonymous-method/iterator proxy classes.
@@ -605,22 +719,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               public void EmitArgument (int idx)
-               {
-                       if (InIterator)
-                               ig.Emit (OpCodes.Ldfld, IteratorHandler.Current.parameter_fields [idx]);
-                       else
-                               throw new Exception ("EmitStoreArgument for an unknown state");
-               }
-               
-               public void EmitStoreArgument (int idx)
-               {
-                       if (InIterator)
-                               ig.Emit (OpCodes.Stfld, IteratorHandler.Current.parameter_fields [idx]);
-                       else
-                               throw new Exception ("EmitStoreArgument for an unknown state");
-               }
-               
                public Expression GetThis (Location loc)
                {
                        This my_this;
index ad577caa190f13a314dcbe4d41d8ec67cea14cf8..b6dfab95c44ad295fac7eada0dd024e9e429ffdc 100644 (file)
@@ -431,8 +431,6 @@ namespace Mono.CSharp {
                        if (expr_type == target_type)
                                return true;
 
-                        //Console.WriteLine ("No !!");
-
                        // First numeric conversions 
 
                        if (expr_type == TypeManager.sbyte_type){
@@ -928,13 +926,7 @@ namespace Mono.CSharp {
                                return null;
                        
                        Type most_specific_source, most_specific_target;
-#if BLAH
-                       foreach (MethodBase m in union.Methods){
-                               Console.WriteLine ("Name: " + m.Name);
-                               Console.WriteLine ("    : " + ((MethodInfo)m).ReturnType);
-                       }
-#endif
-                       
+
                        most_specific_source = FindMostSpecificSource (union, source, look_for_explicit, loc);
                        if (most_specific_source == null)
                                return null;
index 450cd28f2a2de4444c4376e5f99e480fb0c32e29..b6d36d0b5a2a0cbf9904c9754ede6164e19255ae 100755 (executable)
@@ -247,6 +247,10 @@ namespace Mono.CSharp
 %token LITERAL_STRING            "string literal"
 
 %token IDENTIFIER
+%token CLOSE_PARENS_CAST
+%token CLOSE_PARENS_NO_CAST
+%token CLOSE_PARENS_OPEN_PARENS
+%token CLOSE_PARENS_MINUS
 
 /* Add precedence rules to solve dangling else s/r conflict */
 %nonassoc LOWPREC
@@ -429,9 +433,10 @@ type_declaration
 //
 // Enable this when we have handled all errors, because this acts as a generic fallback
 //
-//     | error {
-//             Report.Error (1518, lexer.Location, "Expected class, struct, interface, enum or delegate");
-//       }
+       | error {
+               Console.WriteLine ("Token=" + yyToken);
+               Report.Error (1518, lexer.Location, "Expected class, struct, interface, enum or delegate");
+         }
        ;
 
 //
@@ -2064,11 +2069,31 @@ boolean_literal
        | FALSE                 { $$ = new BoolLiteral (false); }
        ;
 
-parenthesized_expression
+parenthesized_expression_0
        : OPEN_PARENS expression CLOSE_PARENS
-         { $$ = $2; }
+         {
+               $$ = $2;
+               lexer.Deambiguate_CloseParens ();
+               // After this, the next token returned is one of
+               // CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST, CLOSE_PARENS_OPEN_PARENS
+               // or CLOSE_PARENS_MINUS.
+         }
        ;
 
+parenthesized_expression
+       : parenthesized_expression_0 CLOSE_PARENS_NO_CAST
+         {
+               $$ = $1;
+         }
+       | parenthesized_expression_0 CLOSE_PARENS_MINUS
+         {
+               // If a parenthesized expression is followed by a minus, we need to wrap
+               // the expression inside a ParenthesizedExpression for the CS0075 check
+               // in Binary.DoResolve().
+               $$ = new ParenthesizedExpression ((Expression) $1, lexer.Location);
+         }
+       ;;
+
 member_access
        : primary_expression DOT IDENTIFIER
          {
@@ -2093,9 +2118,13 @@ invocation_expression
                }
                $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
          }
-       | OPEN_PARENS expression CLOSE_PARENS unary_expression
+       | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS CLOSE_PARENS
+         {
+               $$ = new Invocation ((Expression) $1, new ArrayList (), lexer.Location);
+         }
+       | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS primary_expression
          {
-                 $$ = new InvocationOrCast ((Expression) $2, (Expression) $4, lexer.Location);
+               $$ = new InvocationOrCast ((Expression) $1, (Expression) $3, lexer.Location);
          }
        ;
 
@@ -2199,6 +2228,10 @@ base_access
          {
                $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
          }
+       | BASE error {
+               Report.Error (175, "Use of keyword `base' is not valid in this context");
+               $$ = null;
+         }
        ;
 
 post_increment_expression
@@ -2444,10 +2477,22 @@ unary_expression
        | cast_expression
        ;
 
+cast_list
+       : parenthesized_expression_0 CLOSE_PARENS_CAST unary_expression
+         {
+               $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS cast_expression
+         {
+               $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
+         }     
+       ;
+
 cast_expression
-       : OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
+       : cast_list
+       | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
          {
-                 $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
+               $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
          }
        ;
 
@@ -4181,7 +4226,7 @@ public Tokenizer Lexer {
        }
 }                 
 
-public CSharpParser (StreamReader reader, SourceFile file, ArrayList defines)
+public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList defines)
 {
        current_namespace = new NamespaceEntry (null, file, null);
        this.name = file.Name;
index b3676fe5c778771ac31e6e33618905967df6ceef..e759a1a17806ded6c62752b1286efec5b9756f29 100755 (executable)
@@ -30,7 +30,7 @@ namespace Mono.CSharp
 \r
        public class Tokenizer : yyParser.yyInput\r
        {\r
-               StreamReader reader;\r
+               SeekableStreamReader reader;\r
                public SourceFile ref_name;\r
                public SourceFile file_name;\r
                public int ref_line = 1;\r
@@ -335,7 +335,7 @@ namespace Mono.CSharp
                        defines [def] = true;\r
                }\r
                \r
-               public Tokenizer (StreamReader input, SourceFile file, ArrayList defs)\r
+               public Tokenizer (SeekableStreamReader input, SourceFile file, ArrayList defs)\r
                {\r
                        this.ref_name = file;\r
                        this.file_name = file;\r
@@ -384,8 +384,28 @@ namespace Mono.CSharp
                                return Token.CLOSE_BRACKET;\r
                        case '(':\r
                                return Token.OPEN_PARENS;\r
-                       case ')':\r
-                               return Token.CLOSE_PARENS;\r
+                       case ')': {\r
+                               if (deambiguate_close_parens == 0)\r
+                                       return Token.CLOSE_PARENS;\r
+\r
+                               --deambiguate_close_parens;\r
+\r
+                               // Save current position and parse next token.\r
+                               int old = reader.Position;\r
+                               int new_token = token ();\r
+                               reader.Position = old;\r
+                               putback_char = -1;\r
+\r
+                               if (new_token == Token.OPEN_PARENS)\r
+                                       return Token.CLOSE_PARENS_OPEN_PARENS;\r
+                               else if (new_token == Token.MINUS)\r
+                                       return Token.CLOSE_PARENS_MINUS;\r
+                               else if (IsCastToken (new_token))\r
+                                       return Token.CLOSE_PARENS_CAST;\r
+                               else\r
+                                       return Token.CLOSE_PARENS_NO_CAST;\r
+                       }\r
+\r
                        case ',':\r
                                return Token.COMMA;\r
                        case ':':\r
@@ -529,6 +549,14 @@ namespace Mono.CSharp
                        return Token.ERROR;\r
                }\r
 \r
+               int deambiguate_close_parens = 0;\r
+\r
+               public void Deambiguate_CloseParens ()\r
+               {\r
+                       putback (')');\r
+                       deambiguate_close_parens++;\r
+               }\r
+\r
                void Error_NumericConstantTooLong ()\r
                {\r
                        Report.Error (1021, Location, "Numeric constant too long");                     \r
@@ -999,13 +1027,45 @@ namespace Mono.CSharp
                {\r
                        return val;\r
                }\r
-               \r
-               public int token ()\r
+\r
+               bool IsCastToken (int token)\r
                {\r
-                       current_token = xtoken ();\r
-                       return current_token;\r
+                       switch (token) {\r
+                       case Token.BANG:\r
+                       case Token.TILDE:\r
+                       case Token.IDENTIFIER:\r
+                       case Token.LITERAL_INTEGER:\r
+                       case Token.LITERAL_FLOAT:\r
+                       case Token.LITERAL_DOUBLE:\r
+                       case Token.LITERAL_DECIMAL:\r
+                       case Token.LITERAL_CHARACTER:\r
+                       case Token.LITERAL_STRING:\r
+                       case Token.BASE:\r
+                       case Token.CHECKED:\r
+                       case Token.FALSE:\r
+                       case Token.FIXED:\r
+                       case Token.NEW:\r
+                       case Token.NULL:\r
+                       case Token.SIZEOF:\r
+                       case Token.THIS:\r
+                       case Token.THROW:\r
+                       case Token.TRUE:\r
+                       case Token.TYPEOF:\r
+                       case Token.UNCHECKED:\r
+                       case Token.UNSAFE:\r
+                               return true;\r
+\r
+                       default:\r
+                               return false;\r
+                       }\r
                }\r
 \r
+               public int token ()\r
+                {\r
+                       current_token = xtoken ();\r
+                        return current_token;\r
+                }\r
+\r
                static StringBuilder static_cmd_arg = new System.Text.StringBuilder ();\r
                \r
                void get_cmd_arg (out string cmd, out string arg)\r
index 1b8f735c690fd0c827d872ae65c6871018f9ab60..01d12ea067c0af634a3ffdcca5d93b23e31cf82d 100755 (executable)
@@ -139,7 +139,7 @@ namespace Mono.CSharp
                        }
 
                        using (input){
-                               StreamReader reader = new StreamReader (input, encoding, using_default_encoder);
+                               SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
                                Tokenizer lexer = new Tokenizer (reader, file, defines);
                                int token, tokens = 0, errors = 0;
 
@@ -168,7 +168,7 @@ namespace Mono.CSharp
                                return;
                        }
 
-                       StreamReader reader = new StreamReader (input, encoding, using_default_encoder);
+                       SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
                                
                        parser = new CSharpParser (reader, file, defines);
                        parser.yacc_verbose_flag = yacc_verbose;
index da16aeda8f08348f62a46a50f1a8e31241ad67e4..3e5af29963714d458a06d959fe561a4aa127e5d1 100755 (executable)
@@ -2560,11 +2560,12 @@ namespace Mono.CSharp {
 
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
-
-                               if ((f.ModFlags & Modifiers.VOLATILE) != 0)
-                                       is_volatile = true;
-                               
-                               f.status |= Field.Status.USED;
+                               if (f != null){
+                                       if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+                                               is_volatile = true;
+                                       
+                                       f.status |= Field.Status.USED;
+                               }
                        } 
                        
                        if (FieldInfo.IsStatic){
@@ -2615,7 +2616,7 @@ namespace Mono.CSharp {
                                Report_AssignToReadonly (!is_static);
                                return;
                        }
-                       
+
                        if (!is_static){
                                Expression instance = instance_expr;
 
@@ -2635,11 +2636,12 @@ namespace Mono.CSharp {
 
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
-                               
-                               if ((f.ModFlags & Modifiers.VOLATILE) != 0)
-                                       ig.Emit (OpCodes.Volatile);
-                               
-                               f.status |= Field.Status.ASSIGNED;
+                               if (f != null){
+                                       if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+                                               ig.Emit (OpCodes.Volatile);
+                                       
+                                       f.status |= Field.Status.ASSIGNED;
+                               }
                        } 
 
                        if (is_static)
@@ -2654,15 +2656,17 @@ namespace Mono.CSharp {
                        
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
-                               if ((f.ModFlags & Modifiers.VOLATILE) != 0){
-                                       Error (676, "volatile variable: can not take its address, or pass as ref/out parameter");
-                                       return;
+                               if (f != null){
+                                       if ((f.ModFlags & Modifiers.VOLATILE) != 0){
+                                               Error (676, "volatile variable: can not take its address, or pass as ref/out parameter");
+                                               return;
+                                       }
+                                       
+                                       if ((mode & AddressOp.Store) != 0)
+                                               f.status |= Field.Status.ASSIGNED;
+                                       if ((mode & AddressOp.Load) != 0)
+                                               f.status |= Field.Status.USED;
                                }
-                               
-                               if ((mode & AddressOp.Store) != 0)
-                                       f.status |= Field.Status.ASSIGNED;
-                               if ((mode & AddressOp.Load) != 0)
-                                       f.status |= Field.Status.USED;
                        } 
 
                        //
@@ -2700,6 +2704,20 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // A FieldExpr whose address can not be taken
+       //
+       public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
+               public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
+               {
+               }
+               
+               public new void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
+               }
+       }
+       
        /// <summary>
        ///   Expression that evaluates to a Property.  The Assign class
        ///   might set the `Value' expression if we are in an assignment.
@@ -3098,14 +3116,15 @@ namespace Mono.CSharp {
 
                public void EmitAddOrRemove (EmitContext ec, Expression source)
                {
-                       Expression handler = ((Binary) source).Right;
+                       BinaryDelegate source_del = (BinaryDelegate) source;
+                       Expression handler = source_del.Right;
                        
                        Argument arg = new Argument (handler, Argument.AType.Expression);
                        ArrayList args = new ArrayList ();
                                
                        args.Add (arg);
                        
-                       if (((Binary) source).Oper == Binary.Operator.Addition)
+                       if (source_del.IsAddition)
                                Invocation.EmitCall (
                                        ec, false, IsStatic, instance_expr, add_accessor, args, loc);
                        else
index f2603a97c1beb40b8f0b7b2c43d731def132968e..a223248ee94c6c51ae25cc15c3bcd6f5d7e8be4e 100755 (executable)
@@ -81,6 +81,28 @@ namespace Mono.CSharp {
                                ec.ig.Emit (OpCodes.Pop);
                }
        }
+
+       public class ParenthesizedExpression : Expression
+       {
+               public Expression Expr;
+
+               public ParenthesizedExpression (Expression expr, Location loc)
+               {
+                       this.Expr = expr;
+                       this.loc = loc;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expr = Expr.Resolve (ec);
+                       return Expr;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should not happen");
+               }
+       }
        
        /// <summary>
        ///   Unary expressions.  
@@ -950,9 +972,7 @@ namespace Mono.CSharp {
                                // For now: only localvariables when not remapped
                                //
 
-                               if (method == null && 
-                                   (expr is LocalVariableReference && ec.RemapToProxy == false) ||
-                                   (expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic)){
+                               if (method == null && (expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic)){
                                        if (empty_expr == null)
                                                empty_expr = new EmptyExpression ();
                                        
@@ -1816,15 +1836,6 @@ namespace Mono.CSharp {
                Operator oper;
                Expression left, right;
 
-               //
-               // After resolution, method might contain the operator overload
-               // method.
-               //
-               protected MethodBase method;
-               ArrayList  Arguments;
-
-               bool DelegateOperation;
-
                // This must be kept in sync with Operator!!!
                public static readonly string [] oper_names;
                
@@ -2239,16 +2250,15 @@ namespace Mono.CSharp {
                                        union = (MethodGroupExpr) left_expr;
                                
                                if (union != null) {
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                       ArrayList args = new ArrayList (2);
+                                       args.Add (new Argument (left, Argument.AType.Expression));
+                                       args.Add (new Argument (right, Argument.AType.Expression));
                                        
-                                       method = Invocation.OverloadResolve (ec, union, Arguments, Location.Null);
+                                       MethodBase method = Invocation.OverloadResolve (ec, union, args, Location.Null);
                                        if (method != null) {
                                                MethodInfo mi = (MethodInfo) method;
                                                
-                                               type = mi.ReturnType;
-                                               return this;
+                                               return new BinaryMethod (mi.ReturnType, method, args);
                                        } else {
                                                overload_failed = true;
                                        }
@@ -2268,6 +2278,7 @@ namespace Mono.CSharp {
                                //
                                
                                if (l == TypeManager.string_type){
+                                       MethodBase method;
                                        
                                        if (r == TypeManager.void_type) {
                                                Error_OperatorCannotBeApplied ();
@@ -2283,33 +2294,29 @@ namespace Mono.CSharp {
                                                                ls.Value + rs.Value);
                                                }
 
-                                               if (left is Binary){
-                                                       Binary b = (Binary) left;
+                                               if (left is BinaryMethod){
+                                                       BinaryMethod b = (BinaryMethod) left;
 
                                                        //
                                                        // Call String.Concat (string, string, string) or
                                                        // String.Concat (string, string, string, string)
                                                        // if possible.
                                                        //
-                                                       if (b.oper == Operator.Addition &&
-                                                           (b.method == TypeManager.string_concat_string_string ||
-                                                            b.method == TypeManager.string_concat_string_string_string)){
+                                                       if (b.method == TypeManager.string_concat_string_string ||
+                                                            b.method == TypeManager.string_concat_string_string_string){
                                                                ArrayList bargs = b.Arguments;
                                                                int count = bargs.Count;
                                                                
                                                                if (count == 2){
-                                                                       Arguments = bargs;
-                                                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-                                                                       type = TypeManager.string_type;
-                                                                       method = TypeManager.string_concat_string_string_string;
-                                                                       
-                                                                       return this;
+                                                                       bargs.Add (new Argument (right, Argument.AType.Expression));
+                                                                       return new BinaryMethod (
+                                                                               TypeManager.string_type,
+                                                                               TypeManager.string_concat_string_string_string, bargs);
                                                                } else if (count == 3){
-                                                                       Arguments = bargs;
-                                                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-                                                                       type = TypeManager.string_type;
-                                                                       method = TypeManager.string_concat_string_string_string_string;                                                                 
-                                                                       return this;
+                                                                       bargs.Add (new Argument (right, Argument.AType.Expression));
+                                                                       return new BinaryMethod (
+                                                                               TypeManager.string_type,
+                                                                               TypeManager.string_concat_string_string_string_string, bargs);
                                                                }
                                                        }
                                                }
@@ -2326,14 +2333,15 @@ namespace Mono.CSharp {
                                                        return null;
                                                }
                                        }
-                                       type = TypeManager.string_type;
 
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                       //
+                                       // Cascading concats will hold up to 4 arguments
+                                       //
+                                       ArrayList args = new ArrayList (4);
+                                       args.Add (new Argument (left, Argument.AType.Expression));
+                                       args.Add (new Argument (right, Argument.AType.Expression));
 
-                                       return this;
-                                       
+                                       return new BinaryMethod (TypeManager.string_type, method, args);
                                } else if (r == TypeManager.string_type){
                                        // object + string
 
@@ -2342,19 +2350,16 @@ namespace Mono.CSharp {
                                                return null;
                                        }
                                        
-                                       method = TypeManager.string_concat_object_object;
                                        left = Convert.ImplicitConversion (ec, left, TypeManager.object_type, loc);
                                        if (left == null){
                                                Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
                                                return null;
                                        }
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                       ArrayList args = new ArrayList (2);
+                                       args.Add (new Argument (left, Argument.AType.Expression));
+                                       args.Add (new Argument (right, Argument.AType.Expression));
 
-                                       type = TypeManager.string_type;
-
-                                       return this;
+                                       return new BinaryMethod (TypeManager.string_type, TypeManager.string_concat_object_object, args);
                                }
 
                                //
@@ -2438,10 +2443,12 @@ namespace Mono.CSharp {
                        if (oper == Operator.Addition || oper == Operator.Subtraction) {
                                if (l.IsSubclassOf (TypeManager.delegate_type) &&
                                    r.IsSubclassOf (TypeManager.delegate_type)) {
+                                       MethodInfo method;
+                                       ArrayList args = new ArrayList (2);
                                        
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                       args = new ArrayList (2);
+                                       args.Add (new Argument (left, Argument.AType.Expression));
+                                       args.Add (new Argument (right, Argument.AType.Expression));
                                        
                                        if (oper == Operator.Addition)
                                                method = TypeManager.delegate_combine_delegate_delegate;
@@ -2453,9 +2460,7 @@ namespace Mono.CSharp {
                                                return null;
                                        }
 
-                                       DelegateOperation = true;
-                                       type = l;
-                                       return this;
+                                       return new BinaryDelegate (l, method, args);
                                }
 
                                //
@@ -2669,7 +2674,18 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       left = left.Resolve (ec);
+                       if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) {
+                               left = ((ParenthesizedExpression) left).Expr;
+                               left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type);
+                               if (left == null)
+                                       return null;
+
+                               if (left.eclass == ExprClass.Type) {
+                                       Error (75, "Casting a negative value needs to have the value in parentheses.");
+                                       return null;
+                               }
+                       } else
+                               left = left.Resolve (ec);
                        right = right.Resolve (ec);
 
                        if (left == null || right == null)
@@ -2700,9 +2716,6 @@ namespace Mono.CSharp {
                /// </remarks>
                public bool EmitBranchable (EmitContext ec, Label target, bool onTrue)
                {
-                       if (method != null)
-                               return false;
-
                        ILGenerator ig = ec.ig;
 
                        //
@@ -2928,24 +2941,6 @@ namespace Mono.CSharp {
                        Type r = right.Type;
                        OpCode opcode;
 
-                       if (method != null) {
-
-                               // Note that operators are static anyway
-                               
-                               if (Arguments != null) 
-                                       Invocation.EmitArguments (ec, method, Arguments);
-                               
-                               if (method is MethodInfo)
-                                       ig.Emit (OpCodes.Call, (MethodInfo) method);
-                               else
-                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
-
-                               if (DelegateOperation)
-                                       ig.Emit (OpCodes.Castclass, type);
-                                       
-                               return;
-                       }
-
                        //
                        // Handle short-circuit operators differently
                        // than the rest
@@ -3139,14 +3134,87 @@ namespace Mono.CSharp {
 
                        ig.Emit (opcode);
                }
+       }
+
+       //
+       // Object created by Binary when the binary operator uses an method instead of being
+       // a binary operation that maps to a CIL binary operation.
+       //
+       public class BinaryMethod : Expression {
+               public MethodBase method;
+               public ArrayList  Arguments;
+               
+               public BinaryMethod (Type t, MethodBase m, ArrayList args)
+               {
+                       method = m;
+                       Arguments = args;
+                       type = t;
+                       eclass = ExprClass.Value;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (Arguments != null) 
+                               Invocation.EmitArguments (ec, method, Arguments);
+                       
+                       if (method is MethodInfo)
+                               ig.Emit (OpCodes.Call, (MethodInfo) method);
+                       else
+                               ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+               }
+       }
+
+       //
+       // Object created with +/= on delegates
+       //
+       public class BinaryDelegate : Expression {
+               MethodInfo method;
+               ArrayList  args;
+
+               public BinaryDelegate (Type t, MethodInfo mi, ArrayList args)
+               {
+                       method = mi;
+                       this.args = args;
+                       type = t;
+                       eclass = ExprClass.Value;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
 
-               public bool IsBuiltinOperator {
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       Invocation.EmitArguments (ec, method, args);
+                       
+                       ig.Emit (OpCodes.Call, (MethodInfo) method);
+                       ig.Emit (OpCodes.Castclass, type);
+               }
+
+               public Expression Right {
                        get {
-                               return method == null;
+                               Argument arg = (Argument) args [1];
+                               return arg.Expr;
                        }
                }
-       }
 
+               public bool IsAddition {
+                       get {
+                               return method == TypeManager.delegate_combine_delegate_delegate;
+                       }
+               }
+       }
+       
        //
        // User-defined conditional logical operator
        public class ConditionalLogicalOperator : Expression {
@@ -3493,6 +3561,9 @@ namespace Mono.CSharp {
                        if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
                                return null;
 
+                       if (local_info.LocalBuilder == null)
+                               return ec.RemapLocal (local_info);
+                       
                        return this;
                }
 
@@ -3512,6 +3583,9 @@ namespace Mono.CSharp {
                                Error (1604, "cannot assign to `" + Name + "' because it is readonly");
                                return null;
                        }
+
+                       if (local_info.LocalBuilder == null)
+                               return ec.RemapLocalLValue (local_info, right_side);
                        
                        return this;
                }
@@ -3525,13 +3599,7 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
 
-                       if (local_info.LocalBuilder == null){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
-                       } else 
-                               ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
-                       
-                       local_info.Used = true;
+                       ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
                }
                
                public void EmitAssign (EmitContext ec, Expression source)
@@ -3540,25 +3608,15 @@ namespace Mono.CSharp {
 
                        local_info.Assigned = true;
 
-                       if (local_info.LocalBuilder == null){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               source.Emit (ec);
-                               ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
-                       } else {
-                               source.Emit (ec);
-                               ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
-                       }
+                       source.Emit (ec);
+                       ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
                }
                
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        ILGenerator ig = ec.ig;
                        
-                       if (local_info.LocalBuilder == null){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               ig.Emit (OpCodes.Ldflda, local_info.FieldBuilder);
-                       } else
-                               ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
+                       ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
                }
 
                public override string ToString ()
@@ -3663,6 +3721,9 @@ namespace Mono.CSharp {
                        if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
                                return null;
 
+                       if (ec.RemapToProxy)
+                               return ec.RemapParameter (idx);
+                       
                        return this;
                }
 
@@ -3672,6 +3733,9 @@ namespace Mono.CSharp {
 
                        SetAssigned (ec);
 
+                       if (ec.RemapToProxy)
+                               return ec.RemapParameterLValue (idx, right_side);
+                       
                        return this;
                }
 
@@ -3710,12 +3774,6 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        
-                       if (ec.RemapToProxy){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               ec.EmitArgument (idx);
-                               return;
-                       }
-                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -3737,13 +3795,6 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        
-                       if (ec.RemapToProxy){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               source.Emit (ec);
-                               ec.EmitStoreArgument (idx);
-                               return;
-                       }
-                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -3766,11 +3817,6 @@ namespace Mono.CSharp {
 
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
-                       if (ec.RemapToProxy){
-                               Report.Error (-1, "Report this: Taking the address of a remapped parameter not supported");
-                               return;
-                       }
-                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -3986,9 +4032,10 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               ///  Determines "better conversion" as specified in 7.4.2.3
-               ///  Returns : 1 if a->p is better
-               ///            0 if a->q or neither is better 
+               ///   Determines "better conversion" as specified in 7.4.2.3
+               ///
+                ///    Returns : 1 if a->p is better
+               ///              0 if a->q or neither is better 
                /// </summary>
                static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
                {
@@ -3996,15 +4043,20 @@ namespace Mono.CSharp {
                        Expression argument_expr = a.Expr;
 
                        if (argument_type == null)
-                               throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
+                               throw new Exception ("Expression of type " + a.Expr +
+                                                     " does not resolve its type");
 
                        //
                        // This is a special case since csc behaves this way. I can't find
                        // it anywhere in the spec but oh well ...
                        //
-                       if (argument_expr is NullLiteral && p == TypeManager.string_type && q == TypeManager.object_type)
+                       if (argument_expr is NullLiteral &&
+                            p == TypeManager.string_type &&
+                            q == TypeManager.object_type)
                                return 1;
-                       else if (argument_expr is NullLiteral && p == TypeManager.object_type && q == TypeManager.string_type)
+                       else if (argument_expr is NullLiteral &&
+                                 p == TypeManager.object_type &&
+                                 q == TypeManager.string_type)
                                return 0;
                        
                        if (p == q)
@@ -4125,16 +4177,18 @@ namespace Mono.CSharp {
                }
                
                /// <summary>
-               ///  Determines "Better function"
+               ///   Determines "Better function" between candidate
+                ///   and the current best match
                /// </summary>
                /// <remarks>
-               ///    and returns an integer indicating :
-               ///    0 if candidate ain't better
-               ///    1 if candidate is better than the current best match
+               ///    Returns an integer indicating :
+               ///     0 if candidate ain't better
+               ///     1 if candidate is better than the current best match
                /// </remarks>
                static int BetterFunction (EmitContext ec, ArrayList args,
-                                          MethodBase candidate, MethodBase best,
-                                          bool expanded_form, Location loc)
+                                          MethodBase candidate, bool candidate_params,
+                                           MethodBase best, bool best_params,
+                                          Location loc)
                {
                        ParameterData candidate_pd = GetParameterData (candidate);
                        ParameterData best_pd;
@@ -4153,7 +4207,7 @@ namespace Mono.CSharp {
                        if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
                                if (cand_count != argument_count)
                                        return 0;
-                       
+
                        if (best == null) {
                                int x = 0;
 
@@ -4161,14 +4215,13 @@ namespace Mono.CSharp {
                                    candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
                                        return 1;
                                
-                               for (int j = argument_count; j > 0;) {
-                                       j--;
+                               for (int j = 0; j < argument_count; ++j) {
 
                                        Argument a = (Argument) args [j];
                                        Type t = candidate_pd.ParameterType (j);
 
                                        if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
-                                               if (expanded_form)
+                                               if (candidate_params)
                                                        t = TypeManager.GetElementType (t);
 
                                        x = BetterConversion (ec, a, t, null, loc);
@@ -4196,13 +4249,13 @@ namespace Mono.CSharp {
                                Type bt = best_pd.ParameterType (j);
 
                                if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
-                                       if (expanded_form)
+                                       if (candidate_params)
                                                ct = TypeManager.GetElementType (ct);
 
                                if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
-                                       if (expanded_form)
+                                       if (best_params)
                                                bt = TypeManager.GetElementType (bt);
-                               
+
                                x = BetterConversion (ec, a, ct, bt, loc);
                                y = BetterConversion (ec, a, bt, ct, loc);
 
@@ -4213,6 +4266,16 @@ namespace Mono.CSharp {
                                rating2 += y;
                        }
 
+                        //
+                        // If a method (in the normal form) with the
+                        // same signature as the expanded form of the
+                        // current best params method already exists,
+                        // the expanded form is not applicable so we
+                        // force it to select the candidate
+                        //
+                        if (!candidate_params && best_params && cand_count == argument_count)
+                                return 1;
+
                        if (rating1 > rating2)
                                return 1;
                        else
@@ -4254,7 +4317,7 @@ namespace Mono.CSharp {
                        MemberInfo [] miset;
                        MethodGroupExpr union;
 
-                       if (mg1 == null){
+                       if (mg1 == null) {
                                if (mg2 == null)
                                        return null;
                                return (MethodGroupExpr) mg2;
@@ -4274,33 +4337,29 @@ namespace Mono.CSharp {
                        
                        ArrayList common = new ArrayList ();
 
-                       foreach (MethodBase l in left_set.Methods){
-                               foreach (MethodBase r in right_set.Methods){
-                                       if (l != r)
-                                               continue;
+                       foreach (MethodBase r in right_set.Methods){
+                               if (TypeManager.ArrayContainsMethod (left_set.Methods, r))
                                        common.Add (r);
-                                       break;
-                               }
                        }
-                       
+
                        miset = new MemberInfo [length1 + length2 - common.Count];
                        left_set.Methods.CopyTo (miset, 0);
                        
                        int k = length1;
 
-                       foreach (MemberInfo mi in right_set.Methods){
-                               if (!common.Contains (mi))
-                                       miset [k++] = mi;
+                       foreach (MethodBase r in right_set.Methods) {
+                               if (!common.Contains (r))
+                                       miset [k++] = r;
                        }
-                       
+
                        union = new MethodGroupExpr (miset, loc);
                        
                        return union;
                }
 
                /// <summary>
-               ///  Determines is the candidate method, if a params method, is applicable
-               ///  in its expanded form to the given set of arguments
+               ///   Determines if the candidate method, if a params method, is applicable
+               ///   in its expanded form to the given set of arguments
                /// </summary>
                static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
                {
@@ -4328,8 +4387,9 @@ namespace Mono.CSharp {
                                return true;
 
                        //
-                       // If we have come this far, the case which remains is when the number of parameters
-                       // is less than or equal to the argument count.
+                       // If we have come this far, the case which
+                       // remains is when the number of parameters is
+                       // less than or equal to the argument count.
                        //
                        for (int i = 0; i < pd_count - 1; ++i) {
 
@@ -4343,7 +4403,9 @@ namespace Mono.CSharp {
                                if (a_mod == p_mod) {
 
                                        if (a_mod == Parameter.Modifier.NONE)
-                                               if (!Convert.ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
+                                               if (!Convert.ImplicitConversionExists (ec,
+                                                                                       a.Expr,
+                                                                                       pd.ParameterType (i)))
                                                        return false;
                                                                                
                                        if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
@@ -4365,7 +4427,7 @@ namespace Mono.CSharp {
                        for (int i = pd_count - 1; i < arg_count; i++) {
                                Argument a = (Argument) arguments [i];
                                
-                               if (!Convert.ImplicitStandardConversionExists (a.Expr, element_type))
+                               if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
                                        return false;
                        }
                        
@@ -4373,8 +4435,8 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               ///  Determines if the candidate method is applicable (section 14.4.2.1)
-               ///  to the given set of arguments
+               ///   Determines if the candidate method is applicable (section 14.4.2.1)
+               ///   to the given set of arguments
                /// </summary>
                static bool IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
                {
@@ -4407,8 +4469,9 @@ namespace Mono.CSharp {
                                if (a_mod == p_mod ||
                                    (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
                                        if (a_mod == Parameter.Modifier.NONE) {
-                                                 if (!Convert.ImplicitConversionExists (ec,
-                                                                                       a.Expr, pd.ParameterType (i)))
+                                                if (!Convert.ImplicitConversionExists (ec,
+                                                                                       a.Expr,
+                                                                                       pd.ParameterType (i)))
                                                        return false;
                                         }
                                        
@@ -4417,7 +4480,7 @@ namespace Mono.CSharp {
 
                                                if (!pt.IsByRef)
                                                        pt = TypeManager.GetReferenceType (pt);
-
+                                                
                                                if (pt != a.Type)
                                                        return false;
                                        }
@@ -4455,9 +4518,15 @@ namespace Mono.CSharp {
                        ArrayList candidates = new ArrayList ();
 
                         //
-                        // First we construct the set of applicable methods
+                        // Used to keep a map between the candidate
+                        // and whether it is being considered in its
+                        // normal or expanded form
                         //
+                        Hashtable candidate_to_form = new PtrHashtable ();
+
 
+                        //
+                        // First we construct the set of applicable methods
                         //
                         // We start at the top of the type hierarchy and
                         // go down to find applicable methods
@@ -4469,7 +4538,6 @@ namespace Mono.CSharp {
                                 return null;
                         }
 
-
                         bool found_applicable = false;
                        foreach (MethodBase candidate in me.Methods) {
                                 Type decl_type = candidate.DeclaringType;
@@ -4486,59 +4554,48 @@ namespace Mono.CSharp {
 
 
                                // Check if candidate is applicable (section 14.4.2.1)
-                               if (!IsApplicable (ec, Arguments, candidate))
-                                       continue;
-
-                                
-                               candidates.Add (candidate);
-                                applicable_type = candidate.DeclaringType;
-                                found_applicable = true;
-
+                               if (!IsApplicable (ec, Arguments, candidate)) {
+                                       // Candidate is applicable in normal form
+                                       candidates.Add (candidate);
+                                       applicable_type = candidate.DeclaringType;
+                                       found_applicable = true;
+                                       candidate_to_form [candidate] = false;
+                               } else {
+                                        if (IsParamsMethodApplicable (ec, Arguments, candidate)) {
+                                                // Candidate is applicable in expanded form
+                                                candidates.Add (candidate);
+                                                applicable_type = candidate.DeclaringType;
+                                                found_applicable = true; 
+                                                candidate_to_form [candidate] = true;
+                                        }
+                               }
                        }
 
-
                         //
                         // Now we actually find the best method
                         //
                         foreach (MethodBase candidate in candidates) {
-                                int x = BetterFunction (ec, Arguments, candidate, method, false, loc);
+                                bool cand_params = (bool) candidate_to_form [candidate];
+                                bool method_params = false;
+                               
+                                if (method != null)
+                                        method_params = (bool) candidate_to_form [method];
                                 
+                                int x = BetterFunction (ec, Arguments,
+                                                        candidate, cand_params,
+                                                       method, method_params,
+                                                        loc);
                                 if (x == 0)
                                         continue;
                                 
                                 method = candidate;
                         }
 
-
                        if (Arguments == null)
                                argument_count = 0;
                        else
                                argument_count = Arguments.Count;
                        
-                       //
-                       // Now we see if we can find params functions,
-                       // applicable in their expanded form since if
-                       // they were applicable in their normal form,
-                       // they would have been selected above anyways
-                       //
-                       bool chose_params_expanded = false;
-                       
-                       if (method == null) {
-                               candidates = new ArrayList ();
-                               foreach (MethodBase candidate in me.Methods){
-                                       if (!IsParamsMethodApplicable (ec, Arguments, candidate))
-                                               continue;
-
-                                       candidates.Add (candidate);
-
-                                       int x = BetterFunction (ec, Arguments, candidate, method, true, loc);
-                                       if (x == 0)
-                                               continue;
-
-                                       method = candidate; 
-                                       chose_params_expanded = true;
-                               }
-                       }
 
                        if (method == null) {
                                //
@@ -4555,6 +4612,7 @@ namespace Mono.CSharp {
 
                                        VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
                                                               null, loc);
+                                        break;
                                }
 
                                 if (!Location.IsNull (loc)) {
@@ -4572,11 +4630,13 @@ namespace Mono.CSharp {
                        // Now check that there are no ambiguities i.e the selected method
                        // should be better than all the others
                        //
+                        bool best_params = (bool) candidate_to_form [method];
 
                        foreach (MethodBase candidate in candidates){
-                               if (candidate == method)
-                                       continue;
 
+                                if (candidate == method)
+                                        continue;
+                                               
                                //
                                // If a normal method is applicable in
                                // the sense that it has the same
@@ -4585,13 +4645,15 @@ namespace Mono.CSharp {
                                // applicable so we debar the params
                                // method.
                                //
-
-                                if (IsParamsMethodApplicable (ec, Arguments, candidate) &&
-                                   IsApplicable (ec, Arguments, method))
-                                       continue;
-                                       
-                               int x = BetterFunction (ec, Arguments, method, candidate,
-                                                       chose_params_expanded, loc);
+                                if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
+                                     IsApplicable (ec, Arguments, method)))
+                                        continue;
+                                
+                                bool cand_params = (bool) candidate_to_form [candidate];
+                               int x = BetterFunction (ec, Arguments,
+                                                        method, best_params,
+                                                        candidate, cand_params,
+                                                       loc);
 
                                if (x != 1) {
                                        Report.Error (
@@ -4607,9 +4669,8 @@ namespace Mono.CSharp {
                        // necessary etc. and return if everything is
                        // all right
                        //
-
-                       if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
-                                                  chose_params_expanded, null, loc))
+                        if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
+                                                    best_params, null, loc))
                                return null;
 
                        return method;
@@ -4723,9 +4784,6 @@ namespace Mono.CSharp {
                                if (a_mod != p_mod &&
                                    pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
                                        if (!Location.IsNull (loc)) {
-                                               Console.WriteLine ("A:P: " + a.GetParameterModifier ());
-                                               Console.WriteLine ("PP:: " + pd.ParameterModifier (j));
-                                               Console.WriteLine ("PT:  " + parameter_type.IsByRef);
                                                Report.Error (1502, loc,
                                                       "The best overloaded match for method '" + FullMethodDesc (method)+
                                                       "' has some invalid arguments");
@@ -6321,6 +6379,29 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // This produces the value that renders an instance, used by the iterators code
+       //
+       public class ProxyInstance : Expression, IMemoryLocation  {
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       eclass = ExprClass.Variable;
+                       type = ec.ContainerType;
+                       return this;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldarg_0);
+
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       ec.ig.Emit (OpCodes.Ldarg_0);
+               }
+       }
+       
        /// <summary>
        ///   Implements the typeof operator
        /// </summary>
index bed88521116a6d5cf44dcedd176a68678621175a..10be47f48a51262517985d0be51b76d900b9d15a 100644 (file)
@@ -96,8 +96,8 @@ namespace Mono.CSharp {
                        if (!Yield.CheckContext (ec, loc))
                                return false;
 
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
-                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowBranching.FlowReturns.Always;
+                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowBranching.FlowReturns.Always;
                        return true;
                }
 
@@ -255,9 +255,13 @@ namespace Mono.CSharp {
                // Invoked when a local variable declaration needs to be mapped to
                // a field in our proxy class
                //
-               public FieldBuilder MapVariable (string name, Type t)
+               // Prefixes registered:
+               //   v_   for EmitContext.MapVariable
+               //   s_   for Storage
+               //
+               public FieldBuilder MapVariable (string pfx, string name, Type t)
                {
-                       return enumerator_proxy_class.DefineField ("v" + name, t, FieldAttributes.Public);
+                       return enumerator_proxy_class.DefineField (pfx + name, t, FieldAttributes.Public);
                }
                
                void Create_Reset ()
index f4ff2280c3209847c84cbd2b2c5902aa7edd58e1..83731a82e561926b86fb2b7298e5d3f4504bc1fe 100755 (executable)
@@ -201,11 +201,11 @@ namespace Mono.CSharp {
 
                public class AliasEntry {
                        public readonly string Name;
-                       public readonly string Alias;
+                       public readonly Expression Alias;
                        public readonly NamespaceEntry NamespaceEntry;
                        public readonly Location Location;
                        
-                       public AliasEntry (NamespaceEntry entry, string name, string alias, Location loc)
+                       public AliasEntry (NamespaceEntry entry, string name, Expression alias, Location loc)
                        {
                                Name = name;
                                Alias = alias;
@@ -221,8 +221,15 @@ namespace Mono.CSharp {
                                        return resolved;
 
                                NamespaceEntry curr_ns = NamespaceEntry;
+
+                               //
+                               // GENERICS: Cope with the expression and not with the string
+                               // this will fail with `using A = Stack<int>'
+                               //
+                               
+                               string alias = Alias.ToString ();
                                while ((curr_ns != null) && (resolved == null)) {
-                                       resolved = curr_ns.Lookup (null, Alias, Location);
+                                       resolved = curr_ns.Lookup (null, alias, Location);
 
                                        if (resolved == null)
                                                curr_ns = curr_ns.Parent;
@@ -313,7 +320,7 @@ namespace Mono.CSharp {
                        using_clauses.Add (ue);
                }
 
-               public void UsingAlias (string alias, string namespace_or_type, Location loc)
+               public void UsingAlias (string alias, Expression namespace_or_type, Location loc)
                {
                        if (aliases == null)
                                aliases = new Hashtable ();
@@ -542,7 +549,7 @@ namespace Mono.CSharp {
                                        if (alias.Resolve () != null)
                                                continue;
 
-                                       error246 (alias.Location, alias.Alias);
+                                       error246 (alias.Location, alias.Alias.ToString ());
                                }
                        }
                }
index 36ab0e9a37a248c09f9fdb708627269478a1dd78..8727b71ac32e2f1dc343a5fb401f00e3c84b46e1 100755 (executable)
@@ -139,14 +139,14 @@ namespace Mono.CSharp {
                                return false;
                        }
                        
-                       ec.StartFlowBranching (FlowBranchingType.BLOCK, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
                        
                        if (!TrueStatement.Resolve (ec)) {
                                ec.KillFlowBranching ();
                                return false;
                        }
 
-                       ec.CurrentBranching.CreateSibling ();
+                       ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
 
                        if ((FalseStatement != null) && !FalseStatement.Resolve (ec)) {
                                ec.KillFlowBranching ();
@@ -229,7 +229,7 @@ namespace Mono.CSharp {
                {
                        bool ok = true;
 
-                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.LoopBlock, loc);
 
                        if (!EmbeddedStatement.Resolve (ec))
                                ok = false;
@@ -245,8 +245,8 @@ namespace Mono.CSharp {
                        }
 
                        ec.CurrentBranching.Infinite = infinite;
-                       FlowReturns returns = ec.EndFlowBranching ();
-                       may_return = returns != FlowReturns.NEVER;
+                       FlowBranching.FlowReturns returns = ec.EndFlowBranching ();
+                       may_return = returns != FlowBranching.FlowReturns.Never;
 
                        return ok;
                }
@@ -314,7 +314,7 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return false;
 
-                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.LoopBlock, loc);
 
                        //
                        // Inform whether we are infinite or not
@@ -331,7 +331,7 @@ namespace Mono.CSharp {
                                //
                                // We are not infinite, so the loop may or may not be executed.
                                //
-                               ec.CurrentBranching.CreateSibling ();
+                               ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
                        }
 
                        if (!Statement.Resolve (ec))
@@ -341,8 +341,8 @@ namespace Mono.CSharp {
                                ec.KillFlowBranching ();
                        else {
                                ec.CurrentBranching.Infinite = infinite;
-                               FlowReturns returns = ec.EndFlowBranching ();
-                               may_return = returns != FlowReturns.NEVER;
+                               FlowBranching.FlowReturns returns = ec.EndFlowBranching ();
+                               may_return = returns != FlowBranching.FlowReturns.Never;
                        }
 
                        return ok;
@@ -451,9 +451,9 @@ namespace Mono.CSharp {
                        } else
                                infinite = true;
 
-                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.LoopBlock, loc);
                        if (!infinite)
-                               ec.CurrentBranching.CreateSibling ();
+                               ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
 
                        if (!Statement.Resolve (ec))
                                ok = false;
@@ -467,8 +467,8 @@ namespace Mono.CSharp {
                                ec.KillFlowBranching ();
                        else {
                                ec.CurrentBranching.Infinite = infinite;
-                               FlowReturns returns = ec.EndFlowBranching ();
-                               may_return = returns != FlowReturns.NEVER;
+                               FlowBranching.FlowReturns returns = ec.EndFlowBranching ();
+                               may_return = returns != FlowBranching.FlowReturns.Never;
                        }
 
                        return ok;
@@ -605,8 +605,8 @@ namespace Mono.CSharp {
                        else
                                vector.CheckOutParameters (ec.CurrentBranching);
 
-                       vector.Returns = FlowReturns.ALWAYS;
-                       vector.Breaks = FlowReturns.ALWAYS;
+                       vector.Returns = FlowBranching.FlowReturns.Always;
+                       vector.Breaks = FlowBranching.FlowReturns.Always;
                        return true;
                }
                
@@ -677,8 +677,8 @@ namespace Mono.CSharp {
                        if (!label.IsDefined)
                                label.AddUsageVector (ec.CurrentBranching.CurrentUsageVector);
 
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
-                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowBranching.FlowReturns.Always;
+                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowBranching.FlowReturns.Always;
 
                        return true;
                }
@@ -755,8 +755,8 @@ namespace Mono.CSharp {
                        if (vectors != null)
                                ec.CurrentBranching.CurrentUsageVector.MergeJumpOrigins (vectors);
                        else {
-                               ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.NEVER;
-                               ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.NEVER;
+                               ec.CurrentBranching.CurrentUsageVector.Breaks = FlowBranching.FlowReturns.Never;
+                               ec.CurrentBranching.CurrentUsageVector.Returns = FlowBranching.FlowReturns.Never;
                        }
 
                        referenced = true;
@@ -786,8 +786,8 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
-                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowBranching.FlowReturns.Always;
+                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowBranching.FlowReturns.Always;
                        return true;
                }
 
@@ -853,8 +853,8 @@ namespace Mono.CSharp {
 
                        label = sl.ILLabelCode;
 
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.UNREACHABLE;
-                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowBranching.FlowReturns.Unreachable;
+                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowBranching.FlowReturns.Always;
                        return true;
                }
 
@@ -901,8 +901,8 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.EXCEPTION;
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.EXCEPTION;
+                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowBranching.FlowReturns.Exception;
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowBranching.FlowReturns.Exception;
                        return true;
                }
                        
@@ -938,7 +938,7 @@ namespace Mono.CSharp {
                public override bool Resolve (EmitContext ec)
                {
                        ec.CurrentBranching.MayLeaveLoop = true;
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowBranching.FlowReturns.Always;
                        return true;
                }
 
@@ -969,7 +969,7 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowBranching.FlowReturns.Always;
                        return true;
                }
 
@@ -1003,1749 +1003,6 @@ namespace Mono.CSharp {
                }
        }
 
-       // <summary>
-       //   This is used in the control flow analysis code to specify whether the
-       //   current code block may return to its enclosing block before reaching
-       //   its end.
-       // </summary>
-       public enum FlowReturns {
-               // It can never return.
-               NEVER,
-
-               // This means that the block contains a conditional return statement
-               // somewhere.
-               SOMETIMES,
-
-               // The code always returns, ie. there's an unconditional return / break
-               // statement in it.
-               ALWAYS,
-
-               // The code always throws an exception.
-               EXCEPTION,
-
-               // The current code block is unreachable.  This happens if it's immediately
-               // following a FlowReturns.ALWAYS block.
-               UNREACHABLE
-       }
-
-       // <summary>
-       //   This is a special bit vector which can inherit from another bit vector doing a
-       //   copy-on-write strategy.  The inherited vector may have a smaller size than the
-       //   current one.
-       // </summary>
-       public class MyBitVector {
-               public readonly int Count;
-               public readonly MyBitVector InheritsFrom;
-
-               bool is_dirty;
-               BitArray vector;
-
-               public MyBitVector (int Count)
-                       : this (null, Count)
-               { }
-
-               public MyBitVector (MyBitVector InheritsFrom, int Count)
-               {
-                       this.InheritsFrom = InheritsFrom;
-                       this.Count = Count;
-               }
-
-               // <summary>
-               //   Checks whether this bit vector has been modified.  After setting this to true,
-               //   we won't use the inherited vector anymore, but our own copy of it.
-               // </summary>
-               public bool IsDirty {
-                       get {
-                               return is_dirty;
-                       }
-
-                       set {
-                               if (!is_dirty)
-                                       initialize_vector ();
-                       }
-               }
-
-               // <summary>
-               //   Get/set bit `index' in the bit vector.
-               // </summary>
-               public bool this [int index]
-               {
-                       get {
-                               if (index > Count)
-                                       throw new ArgumentOutOfRangeException ();
-
-                               // We're doing a "copy-on-write" strategy here; as long
-                               // as nobody writes to the array, we can use our parent's
-                               // copy instead of duplicating the vector.
-
-                               if (vector != null)
-                                       return vector [index];
-                               else if (InheritsFrom != null) {
-                                       BitArray inherited = InheritsFrom.Vector;
-
-                                       if (index < inherited.Count)
-                                               return inherited [index];
-                                       else
-                                               return false;
-                               } else
-                                       return false;
-                       }
-
-                       set {
-                               if (index > Count)
-                                       throw new ArgumentOutOfRangeException ();
-
-                               // Only copy the vector if we're actually modifying it.
-
-                               if (this [index] != value) {
-                                       initialize_vector ();
-
-                                       vector [index] = value;
-                               }
-                       }
-               }
-
-               // <summary>
-               //   If you explicitly convert the MyBitVector to a BitArray, you will get a deep
-               //   copy of the bit vector.
-               // </summary>
-               public static explicit operator BitArray (MyBitVector vector)
-               {
-                       vector.initialize_vector ();
-                       return vector.Vector;
-               }
-
-               // <summary>
-               //   Performs an `or' operation on the bit vector.  The `new_vector' may have a
-               //   different size than the current one.
-               // </summary>
-               public void Or (MyBitVector new_vector)
-               {
-                       BitArray new_array = new_vector.Vector;
-
-                       initialize_vector ();
-
-                       int upper;
-                       if (vector.Count < new_array.Count)
-                               upper = vector.Count;
-                       else
-                               upper = new_array.Count;
-
-                       for (int i = 0; i < upper; i++)
-                               vector [i] = vector [i] | new_array [i];
-               }
-
-               // <summary>
-               //   Perfonrms an `and' operation on the bit vector.  The `new_vector' may have
-               //   a different size than the current one.
-               // </summary>
-               public void And (MyBitVector new_vector)
-               {
-                       BitArray new_array = new_vector.Vector;
-
-                       initialize_vector ();
-
-                       int lower, upper;
-                       if (vector.Count < new_array.Count)
-                               lower = upper = vector.Count;
-                       else {
-                               lower = new_array.Count;
-                               upper = vector.Count;
-                       }
-
-                       for (int i = 0; i < lower; i++)
-                               vector [i] = vector [i] & new_array [i];
-
-                       for (int i = lower; i < upper; i++)
-                               vector [i] = false;
-               }
-
-               // <summary>
-               //   This does a deep copy of the bit vector.
-               // </summary>
-               public MyBitVector Clone ()
-               {
-                       MyBitVector retval = new MyBitVector (Count);
-
-                       retval.Vector = Vector;
-
-                       return retval;
-               }
-
-               BitArray Vector {
-                       get {
-                               if (vector != null)
-                                       return vector;
-                               else if (!is_dirty && (InheritsFrom != null))
-                                       return InheritsFrom.Vector;
-
-                               initialize_vector ();
-
-                               return vector;
-                       }
-
-                       set {
-                               initialize_vector ();
-
-                               for (int i = 0; i < System.Math.Min (vector.Count, value.Count); i++)
-                                       vector [i] = value [i];
-                       }
-               }
-
-               void initialize_vector ()
-               {
-                       if (vector != null)
-                               return;
-
-                       vector = new BitArray (Count, false);
-                       if (InheritsFrom != null)
-                               Vector = InheritsFrom.Vector;
-
-                       is_dirty = true;
-               }
-
-               public override string ToString ()
-               {
-                       StringBuilder sb = new StringBuilder ("MyBitVector (");
-
-                       BitArray vector = Vector;
-                       sb.Append (Count);
-                       sb.Append (",");
-                       if (!IsDirty)
-                               sb.Append ("INHERITED - ");
-                       for (int i = 0; i < vector.Count; i++) {
-                               if (i > 0)
-                                       sb.Append (",");
-                               sb.Append (vector [i]);
-                       }
-                       
-                       sb.Append (")");
-                       return sb.ToString ();
-               }
-       }
-
-       // <summary>
-       //   The type of a FlowBranching.
-       // </summary>
-       public enum FlowBranchingType {
-               // Normal (conditional or toplevel) block.
-               BLOCK,
-
-               // A loop block.
-               LOOP_BLOCK,
-
-               // Try/Catch block.
-               EXCEPTION,
-
-               // Switch block.
-               SWITCH,
-
-               // Switch section.
-               SWITCH_SECTION
-       }
-
-       // <summary>
-       //   A new instance of this class is created every time a new block is resolved
-       //   and if there's branching in the block's control flow.
-       // </summary>
-       public class FlowBranching {
-               // <summary>
-               //   The type of this flow branching.
-               // </summary>
-               public readonly FlowBranchingType Type;
-
-               // <summary>
-               //   The block this branching is contained in.  This may be null if it's not
-               //   a top-level block and it doesn't declare any local variables.
-               // </summary>
-               public readonly Block Block;
-
-               // <summary>
-               //   The parent of this branching or null if this is the top-block.
-               // </summary>
-               public readonly FlowBranching Parent;
-
-               // <summary>
-               //   Start-Location of this flow branching.
-               // </summary>
-               public readonly Location Location;
-
-               // <summary>
-               //   A list of UsageVectors.  A new vector is added each time control flow may
-               //   take a different path.
-               // </summary>
-               public UsageVector[] Siblings;
-
-               // <summary>
-               //   If this is an infinite loop.
-               // </summary>
-               public bool Infinite;
-
-               // <summary>
-               //   If we may leave the current loop.
-               // </summary>
-               public bool MayLeaveLoop;
-
-               //
-               // Private
-               //
-               VariableMap param_map, local_map;
-               ArrayList finally_vectors;
-
-               static int next_id = 0;
-               int id;
-
-               // <summary>
-               //   Performs an `And' operation on the FlowReturns status
-               //   (for instance, a block only returns ALWAYS if all its siblings
-               //   always return).
-               // </summary>
-               public static FlowReturns AndFlowReturns (FlowReturns a, FlowReturns b)
-               {
-                       if (b == FlowReturns.UNREACHABLE)
-                               return a;
-
-                       switch (a) {
-                       case FlowReturns.NEVER:
-                               if (b == FlowReturns.NEVER)
-                                       return FlowReturns.NEVER;
-                               else
-                                       return FlowReturns.SOMETIMES;
-
-                       case FlowReturns.SOMETIMES:
-                               return FlowReturns.SOMETIMES;
-
-                       case FlowReturns.ALWAYS:
-                               if ((b == FlowReturns.ALWAYS) || (b == FlowReturns.EXCEPTION))
-                                       return FlowReturns.ALWAYS;
-                               else
-                                       return FlowReturns.SOMETIMES;
-
-                       case FlowReturns.EXCEPTION:
-                               if (b == FlowReturns.EXCEPTION)
-                                       return FlowReturns.EXCEPTION;
-                               else if (b == FlowReturns.ALWAYS)
-                                       return FlowReturns.ALWAYS;
-                               else
-                                       return FlowReturns.SOMETIMES;
-                       }
-
-                       return b;
-               }
-
-               // <summary>
-               //   The vector contains a BitArray with information about which local variables
-               //   and parameters are already initialized at the current code position.
-               // </summary>
-               public class UsageVector {
-                       // <summary>
-                       //   If this is true, then the usage vector has been modified and must be
-                       //   merged when we're done with this branching.
-                       // </summary>
-                       public bool IsDirty;
-
-                       // <summary>
-                       //   The number of parameters in this block.
-                       // </summary>
-                       public readonly int CountParameters;
-
-                       // <summary>
-                       //   The number of locals in this block.
-                       // </summary>
-                       public readonly int CountLocals;
-
-                       // <summary>
-                       //   If not null, then we inherit our state from this vector and do a
-                       //   copy-on-write.  If null, then we're the first sibling in a top-level
-                       //   block and inherit from the empty vector.
-                       // </summary>
-                       public readonly UsageVector InheritsFrom;
-
-                       //
-                       // Private.
-                       //
-                       MyBitVector locals, parameters;
-                       FlowReturns real_returns, real_breaks;
-                       bool is_finally;
-
-                       static int next_id = 0;
-                       int id;
-
-                       //
-                       // Normally, you should not use any of these constructors.
-                       //
-                       public UsageVector (UsageVector parent, int num_params, int num_locals)
-                       {
-                               this.InheritsFrom = parent;
-                               this.CountParameters = num_params;
-                               this.CountLocals = num_locals;
-                               this.real_returns = FlowReturns.NEVER;
-                               this.real_breaks = FlowReturns.NEVER;
-
-                               if (parent != null) {
-                                       locals = new MyBitVector (parent.locals, CountLocals);
-                                       if (num_params > 0)
-                                               parameters = new MyBitVector (parent.parameters, num_params);
-                                       real_returns = parent.Returns;
-                                       real_breaks = parent.Breaks;
-                               } else {
-                                       locals = new MyBitVector (null, CountLocals);
-                                       if (num_params > 0)
-                                               parameters = new MyBitVector (null, num_params);
-                               }
-
-                               id = ++next_id;
-                       }
-
-                       public UsageVector (UsageVector parent)
-                               : this (parent, parent.CountParameters, parent.CountLocals)
-                       { }
-
-                       // <summary>
-                       //   This does a deep copy of the usage vector.
-                       // </summary>
-                       public UsageVector Clone ()
-                       {
-                               UsageVector retval = new UsageVector (null, CountParameters, CountLocals);
-
-                               retval.locals = locals.Clone ();
-                               if (parameters != null)
-                                       retval.parameters = parameters.Clone ();
-                               retval.real_returns = real_returns;
-                               retval.real_breaks = real_breaks;
-
-                               return retval;
-                       }
-
-                       public bool IsAssigned (VariableInfo var)
-                       {
-                               if (!var.IsParameter && AlwaysBreaks)
-                                       return true;
-
-                               return var.IsAssigned (var.IsParameter ? parameters : locals);
-                       }
-
-                       public void SetAssigned (VariableInfo var)
-                       {
-                               if (!var.IsParameter && AlwaysBreaks)
-                                       return;
-
-                               var.SetAssigned (var.IsParameter ? parameters : locals);
-                       }
-
-                       public bool IsFieldAssigned (VariableInfo var, string name)
-                       {
-                               if (!var.IsParameter && AlwaysBreaks)
-                                       return true;
-
-                               return var.IsFieldAssigned (var.IsParameter ? parameters : locals, name);
-                       }
-
-                       public void SetFieldAssigned (VariableInfo var, string name)
-                       {
-                               if (!var.IsParameter && AlwaysBreaks)
-                                       return;
-
-                               var.SetFieldAssigned (var.IsParameter ? parameters : locals, name);
-                       }
-
-                       // <summary>
-                       //   Specifies when the current block returns.
-                       //   If this is FlowReturns.UNREACHABLE, then control can never reach the
-                       //   end of the method (so that we don't need to emit a return statement).
-                       //   The same applies for FlowReturns.EXCEPTION, but in this case the return
-                       //   value will never be used.
-                       // </summary>
-                       public FlowReturns Returns {
-                               get {
-                                       return real_returns;
-                               }
-
-                               set {
-                                       real_returns = value;
-                               }
-                       }
-
-                       // <summary>
-                       //   Specifies whether control may return to our containing block
-                       //   before reaching the end of this block.  This happens if there
-                       //   is a break/continue/goto/return in it.
-                       //   This can also be used to find out whether the statement immediately
-                       //   following the current block may be reached or not.
-                       // </summary>
-                       public FlowReturns Breaks {
-                               get {
-                                       return real_breaks;
-                               }
-
-                               set {
-                                       real_breaks = value;
-                               }
-                       }
-
-                       public bool AlwaysBreaks {
-                               get {
-                                       return (Breaks == FlowReturns.ALWAYS) ||
-                                               (Breaks == FlowReturns.EXCEPTION) ||
-                                               (Breaks == FlowReturns.UNREACHABLE);
-                               }
-                       }
-
-                       public bool MayBreak {
-                               get {
-                                       return Breaks != FlowReturns.NEVER;
-                               }
-                       }
-
-                       public bool AlwaysReturns {
-                               get {
-                                       return (Returns == FlowReturns.ALWAYS) ||
-                                               (Returns == FlowReturns.EXCEPTION);
-                               }
-                       }
-
-                       public bool MayReturn {
-                               get {
-                                       return (Returns == FlowReturns.SOMETIMES) ||
-                                               (Returns == FlowReturns.ALWAYS);
-                               }
-                       }
-
-                       // <summary>
-                       //   Merge a child branching.
-                       // </summary>
-                       public FlowReturns MergeChildren (FlowBranching branching, UsageVector[] children)
-                       {
-                               MyBitVector new_locals = null;
-                               MyBitVector new_params = null;
-
-                               FlowReturns new_returns = FlowReturns.NEVER;
-                               FlowReturns new_breaks = FlowReturns.NEVER;
-                               bool new_returns_set = false, new_breaks_set = false;
-
-                               Report.Debug (2, "MERGING CHILDREN", branching, branching.Type,
-                                             this, children.Length);
-
-                               foreach (UsageVector child in children) {
-                                       Report.Debug (2, "  MERGING CHILD", child, child.is_finally);
-                                       
-                                       if (!child.is_finally) {
-                                               if (child.Breaks != FlowReturns.UNREACHABLE) {
-                                                       // If Returns is already set, perform an
-                                                       // `And' operation on it, otherwise just set just.
-                                                       if (!new_returns_set) {
-                                                               new_returns = child.Returns;
-                                                               new_returns_set = true;
-                                                       } else
-                                                               new_returns = AndFlowReturns (
-                                                                       new_returns, child.Returns);
-                                               }
-
-                                               // If Breaks is already set, perform an
-                                               // `And' operation on it, otherwise just set just.
-                                               if (!new_breaks_set) {
-                                                       new_breaks = child.Breaks;
-                                                       new_breaks_set = true;
-                                               } else
-                                                       new_breaks = AndFlowReturns (
-                                                               new_breaks, child.Breaks);
-                                       }
-
-                                       // Ignore unreachable children.
-                                       if (child.Returns == FlowReturns.UNREACHABLE)
-                                               continue;
-
-                                       // A local variable is initialized after a flow branching if it
-                                       // has been initialized in all its branches which do neither
-                                       // always return or always throw an exception.
-                                       //
-                                       // If a branch may return, but does not always return, then we
-                                       // can treat it like a never-returning branch here: control will
-                                       // only reach the code position after the branching if we did not
-                                       // return here.
-                                       //
-                                       // It's important to distinguish between always and sometimes
-                                       // returning branches here:
-                                       //
-                                       //    1   int a;
-                                       //    2   if (something) {
-                                       //    3      return;
-                                       //    4      a = 5;
-                                       //    5   }
-                                       //    6   Console.WriteLine (a);
-                                       //
-                                       // The if block in lines 3-4 always returns, so we must not look
-                                       // at the initialization of `a' in line 4 - thus it'll still be
-                                       // uninitialized in line 6.
-                                       //
-                                       // On the other hand, the following is allowed:
-                                       //
-                                       //    1   int a;
-                                       //    2   if (something)
-                                       //    3      a = 5;
-                                       //    4   else
-                                       //    5      return;
-                                       //    6   Console.WriteLine (a);
-                                       //
-                                       // Here, `a' is initialized in line 3 and we must not look at
-                                       // line 5 since it always returns.
-                                       // 
-                                       if (child.is_finally) {
-                                               if (new_locals == null)
-                                                       new_locals = locals.Clone ();
-                                               new_locals.Or (child.locals);
-
-                                               if (parameters != null) {
-                                                       if (new_params == null)
-                                                               new_params = parameters.Clone ();
-                                                       new_params.Or (child.parameters);
-                                               }
-                                       } else {
-                                               if (!child.AlwaysReturns && !child.AlwaysBreaks) {
-                                                       if (new_locals != null)
-                                                               new_locals.And (child.locals);
-                                                       else {
-                                                               new_locals = locals.Clone ();
-                                                               new_locals.Or (child.locals);
-                                                       }
-                                               } else if (children.Length == 1) {
-                                                       new_locals = locals.Clone ();
-                                                       new_locals.Or (child.locals);
-                                               }
-
-                                               // An `out' parameter must be assigned in all branches which do
-                                               // not always throw an exception.
-                                               if (parameters != null) {
-                                                       bool and_params = child.Breaks != FlowReturns.EXCEPTION;
-                                                       if (branching.Type == FlowBranchingType.EXCEPTION)
-                                                               and_params &= child.Returns != FlowReturns.NEVER;
-                                                       if (and_params) {
-                                                               if (new_params != null)
-                                                                       new_params.And (child.parameters);
-                                                               else {
-                                                                       new_params = parameters.Clone ();
-                                                                       new_params.Or (child.parameters);
-                                                               }
-                                                       } else if ((children.Length == 1) || (new_params == null)) {
-                                                               new_params = parameters.Clone ();
-                                                               new_params.Or (child.parameters);
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               Returns = new_returns;
-                               if ((branching.Type == FlowBranchingType.BLOCK) ||
-                                   (branching.Type == FlowBranchingType.EXCEPTION) ||
-                                   (new_breaks == FlowReturns.UNREACHABLE) ||
-                                   (new_breaks == FlowReturns.EXCEPTION))
-                                       Breaks = new_breaks;
-                               else if (branching.Type == FlowBranchingType.SWITCH_SECTION)
-                                       Breaks = new_returns;
-                               else if (branching.Type == FlowBranchingType.SWITCH){
-                                       if (new_breaks == FlowReturns.ALWAYS)
-                                               Breaks = FlowReturns.ALWAYS;
-                               }
-
-                               //
-                               // We've now either reached the point after the branching or we will
-                               // never get there since we always return or always throw an exception.
-                               //
-                               // If we can reach the point after the branching, mark all locals and
-                               // parameters as initialized which have been initialized in all branches
-                               // we need to look at (see above).
-                               //
-
-                               if (((new_breaks != FlowReturns.ALWAYS) &&
-                                    (new_breaks != FlowReturns.EXCEPTION) &&
-                                    (new_breaks != FlowReturns.UNREACHABLE)) ||
-                                   (children.Length == 1)) {
-                                       if (new_locals != null)
-                                               locals.Or (new_locals);
-
-                                       if (new_params != null)
-                                               parameters.Or (new_params);
-                               }
-
-                               Report.Debug (2, "MERGING CHILDREN DONE", branching.Type,
-                                             new_params, new_locals, new_returns, new_breaks,
-                                             branching.Infinite, branching.MayLeaveLoop, this);
-
-                               if (branching.Type == FlowBranchingType.SWITCH_SECTION) {
-                                       if ((new_breaks != FlowReturns.ALWAYS) &&
-                                           (new_breaks != FlowReturns.EXCEPTION) &&
-                                           (new_breaks != FlowReturns.UNREACHABLE))
-                                               Report.Error (163, branching.Location,
-                                                             "Control cannot fall through from one " +
-                                                             "case label to another");
-                               }
-
-                               if (branching.Infinite && !branching.MayLeaveLoop) {
-                                       Report.Debug (1, "INFINITE", new_returns, new_breaks,
-                                                     Returns, Breaks, this);
-
-                                       // We're actually infinite.
-                                       if (new_returns == FlowReturns.NEVER) {
-                                               Breaks = FlowReturns.UNREACHABLE;
-                                               return FlowReturns.UNREACHABLE;
-                                       }
-
-                                       // If we're an infinite loop and do not break, the code after
-                                       // the loop can never be reached.  However, if we may return
-                                       // from the loop, then we do always return (or stay in the loop
-                                       // forever).
-                                       if ((new_returns == FlowReturns.SOMETIMES) ||
-                                           (new_returns == FlowReturns.ALWAYS)) {
-                                               Returns = FlowReturns.ALWAYS;
-                                               return FlowReturns.ALWAYS;
-                                       }
-                               }
-
-                               if (branching.Type == FlowBranchingType.LOOP_BLOCK) {
-                                       Report.Debug (2, "MERGING LOOP BLOCK DONE", branching,
-                                                     branching.Infinite, branching.MayLeaveLoop,
-                                                     new_breaks, new_returns);
-
-                                       // If we may leave the loop, then we do not always return.
-                                       if (branching.MayLeaveLoop && (new_returns == FlowReturns.ALWAYS)) {
-                                               Returns = FlowReturns.SOMETIMES;
-                                               return FlowReturns.SOMETIMES;
-                                       }
-
-                                       // A `break' in a loop does not "break" in the outer block.
-                                       Breaks = FlowReturns.NEVER;
-                               }
-
-                               return new_returns;
-                       }
-
-                       // <summary>
-                       //   Tells control flow analysis that the current code position may be reached with
-                       //   a forward jump from any of the origins listed in `origin_vectors' which is a
-                       //   list of UsageVectors.
-                       //
-                       //   This is used when resolving forward gotos - in the following example, the
-                       //   variable `a' is uninitialized in line 8 becase this line may be reached via
-                       //   the goto in line 4:
-                       //
-                       //      1     int a;
-                       //
-                       //      3     if (something)
-                       //      4        goto World;
-                       //
-                       //      6     a = 5;
-                       //
-                       //      7  World:
-                       //      8     Console.WriteLine (a);
-                       //
-                       // </summary>
-                       public void MergeJumpOrigins (ICollection origin_vectors)
-                       {
-                               Report.Debug (1, "MERGING JUMP ORIGIN", this);
-
-                               real_breaks = FlowReturns.NEVER;
-                               real_returns = FlowReturns.NEVER;
-
-                               foreach (UsageVector vector in origin_vectors) {
-                                       Report.Debug (1, "  MERGING JUMP ORIGIN", vector);
-
-                                       locals.And (vector.locals);
-                                       if (parameters != null)
-                                               parameters.And (vector.parameters);
-                                       Breaks = AndFlowReturns (Breaks, vector.Breaks);
-                                       Returns = AndFlowReturns (Returns, vector.Returns);
-                               }
-
-                               Report.Debug (1, "MERGING JUMP ORIGIN DONE", this);
-                       }
-
-                       // <summary>
-                       //   This is used at the beginning of a finally block if there were
-                       //   any return statements in the try block or one of the catch blocks.
-                       // </summary>
-                       public void MergeFinallyOrigins (ICollection finally_vectors)
-                       {
-                               Report.Debug (1, "MERGING FINALLY ORIGIN", this);
-
-                               real_breaks = FlowReturns.NEVER;
-
-                               foreach (UsageVector vector in finally_vectors) {
-                                       Report.Debug (1, "  MERGING FINALLY ORIGIN", vector);
-
-                                       if (parameters != null)
-                                               parameters.And (vector.parameters);
-                                       Breaks = AndFlowReturns (Breaks, vector.Breaks);
-                               }
-
-                               is_finally = true;
-
-                               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>
-                       public void Or (UsageVector new_vector)
-                       {
-                               locals.Or (new_vector.locals);
-                               if (parameters != null)
-                                       parameters.Or (new_vector.parameters);
-                       }
-
-                       // <summary>
-                       //   Performs an `and' operation on the locals.
-                       // </summary>
-                       public void AndLocals (UsageVector new_vector)
-                       {
-                               locals.And (new_vector.locals);
-                       }
-
-                       // <summary>
-                       //   Returns a deep copy of the parameters.
-                       // </summary>
-                       public MyBitVector Parameters {
-                               get {
-                                       if (parameters != null)
-                                               return parameters.Clone ();
-                                       else
-                                               return null;
-                               }
-                       }
-
-                       // <summary>
-                       //   Returns a deep copy of the locals.
-                       // </summary>
-                       public MyBitVector Locals {
-                               get {
-                                       return locals.Clone ();
-                               }
-                       }
-
-                       //
-                       // Debugging stuff.
-                       //
-
-                       public override string ToString ()
-                       {
-                               StringBuilder sb = new StringBuilder ();
-
-                               sb.Append ("Vector (");
-                               sb.Append (id);
-                               sb.Append (",");
-                               sb.Append (Returns);
-                               sb.Append (",");
-                               sb.Append (Breaks);
-                               if (parameters != null) {
-                                       sb.Append (" - ");
-                                       sb.Append (parameters);
-                               }
-                               sb.Append (" - ");
-                               sb.Append (locals);
-                               sb.Append (")");
-
-                               return sb.ToString ();
-                       }
-               }
-
-               FlowBranching (FlowBranchingType type, Location loc)
-               {
-                       this.Block = null;
-                       this.Location = loc;
-                       this.Type = type;
-                       id = ++next_id;
-               }
-
-               // <summary>
-               //   Creates a new flow branching for `block'.
-               //   This is used from Block.Resolve to create the top-level branching of
-               //   the block.
-               // </summary>
-               public FlowBranching (Block block, Location loc)
-                       : this (FlowBranchingType.BLOCK, loc)
-               {
-                       Block = block;
-                       Parent = null;
-
-                       param_map = block.ParameterMap;
-                       local_map = block.LocalMap;
-
-                       UsageVector vector = new UsageVector (null, param_map.Length, local_map.Length);
-
-                       AddSibling (vector);
-               }
-
-               // <summary>
-               //   Creates a new flow branching which is contained in `parent'.
-               //   You should only pass non-null for the `block' argument if this block
-               //   introduces any new variables - in this case, we need to create a new
-               //   usage vector with a different size than our parent's one.
-               // </summary>
-               public FlowBranching (FlowBranching parent, FlowBranchingType type,
-                                     Block block, Location loc)
-                       : this (type, loc)
-               {
-                       Parent = parent;
-                       Block = block;
-
-                       UsageVector vector;
-                       if (Block != null) {
-                               param_map = Block.ParameterMap;
-                               local_map = Block.LocalMap;
-
-                               vector = new UsageVector (parent.CurrentUsageVector, param_map.Length,
-                                                         local_map.Length);
-                       } else {
-                               param_map = Parent.param_map;
-                               local_map = Parent.local_map;
-                               vector = new UsageVector (Parent.CurrentUsageVector);
-                       }
-
-                       AddSibling (vector);
-
-                       switch (Type) {
-                       case FlowBranchingType.EXCEPTION:
-                               finally_vectors = new ArrayList ();
-                               break;
-
-                       default:
-                               break;
-                       }
-               }
-
-               void AddSibling (UsageVector uv)
-               {
-                       if (Siblings != null) {
-                               UsageVector[] ns = new UsageVector [Siblings.Length + 1];
-                               for (int i = 0; i < Siblings.Length; ++i)
-                                       ns [i] = Siblings [i];
-                               Siblings = ns;
-                       } else {
-                               Siblings = new UsageVector [1];
-                       }
-                       Siblings [Siblings.Length - 1] = uv;
-               }
-
-               // <summary>
-               //   Returns the branching's current usage vector.
-               // </summary>
-               public UsageVector CurrentUsageVector
-               {
-                       get {
-                               return Siblings [Siblings.Length - 1];
-                       }
-               }
-
-               // <summary>
-               //   Creates a sibling of the current usage vector.
-               // </summary>
-               public void CreateSibling ()
-               {
-                       AddSibling (new UsageVector (Parent.CurrentUsageVector));
-
-                       Report.Debug (1, "CREATED SIBLING", CurrentUsageVector);
-               }
-
-               // <summary>
-               //   Creates a sibling for a `finally' block.
-               // </summary>
-               public void CreateSiblingForFinally ()
-               {
-                       if (Type != FlowBranchingType.EXCEPTION)
-                               throw new NotSupportedException ();
-
-                       CreateSibling ();
-
-                       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.Count; i++) {
-                               VariableInfo var = param_map [i];
-
-                               if (var == null)
-                                       continue;
-
-                               if (var.IsAssigned (parameters))
-                                       continue;
-
-                               Report.Error (177, loc, "The out parameter `" +
-                                             param_map.VariableNames [i] + "' must be " +
-                                             "assigned before control leave the current method.");
-                       }
-               }
-
-               // <summary>
-               //   Merge a child branching.
-               // </summary>
-               public FlowReturns MergeChild (FlowBranching child)
-               {
-                       FlowReturns returns = CurrentUsageVector.MergeChildren (child, child.Siblings);
-
-                       if ((child.Type != FlowBranchingType.LOOP_BLOCK) &&
-                           (child.Type != FlowBranchingType.SWITCH_SECTION))
-                               MayLeaveLoop |= child.MayLeaveLoop;
-
-                       return returns;
-               }
-               // <summary>
-               //   Does the toplevel merging.
-               // </summary>
-               public FlowReturns MergeTopBlock ()
-               {
-                       if ((Type != FlowBranchingType.BLOCK) || (Block == null))
-                               throw new NotSupportedException ();
-
-                       UsageVector vector = new UsageVector (null, param_map.Length, local_map.Length);
-
-                       Report.Debug (1, "MERGING TOP BLOCK", Location, vector);
-
-                       vector.MergeChildren (this, Siblings);
-
-                       if (Siblings.Length == 1)
-                               Siblings [0] = vector;
-                       else {
-                               Siblings = null;
-                               AddSibling (vector);
-                       }
-
-                       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;
-               }
-
-               public bool InTryBlock ()
-               {
-                       if (finally_vectors != null)
-                               return true;
-                       else if (Parent != null)
-                               return Parent.InTryBlock ();
-                       else
-                               return false;
-               }
-
-               public void AddFinallyVector (UsageVector vector)
-               {
-                       if (finally_vectors != null) {
-                               finally_vectors.Add (vector.Clone ());
-                               return;
-                       }
-
-                       if (Parent != null)
-                               Parent.AddFinallyVector (vector);
-                       else
-                               throw new NotSupportedException ();
-               }
-
-               public bool IsAssigned (VariableInfo vi)
-               {
-                       return CurrentUsageVector.IsAssigned (vi);
-               }
-
-               public bool IsFieldAssigned (VariableInfo vi, string field_name)
-               {
-                       if (CurrentUsageVector.IsAssigned (vi))
-                               return true;
-
-                       return CurrentUsageVector.IsFieldAssigned (vi, field_name);
-               }
-
-               public void SetAssigned (VariableInfo vi)
-               {
-                       CurrentUsageVector.SetAssigned (vi);
-               }
-
-               public void SetFieldAssigned (VariableInfo vi, string name)
-               {
-                       CurrentUsageVector.SetFieldAssigned (vi, name);
-               }
-
-               public bool IsReachable ()
-               {
-                       bool reachable;
-
-                       switch (Type) {
-                       case FlowBranchingType.SWITCH_SECTION:
-                               // The code following a switch block is reachable unless the switch
-                               // block always returns.
-                               reachable = !CurrentUsageVector.AlwaysReturns;
-                               break;
-
-                       case FlowBranchingType.LOOP_BLOCK:
-                               // The code following a loop is reachable unless the loop always
-                               // returns or it's an infinite loop without any `break's in it.
-                               reachable = !CurrentUsageVector.AlwaysReturns &&
-                                       (CurrentUsageVector.Breaks != FlowReturns.UNREACHABLE);
-                               break;
-
-                       default:
-                               // The code following a block or exception is reachable unless the
-                               // block either always returns or always breaks.
-                               if (MayLeaveLoop)
-                                       reachable = true;
-                               else
-                                       reachable = !CurrentUsageVector.AlwaysBreaks &&
-                                               !CurrentUsageVector.AlwaysReturns;
-                               break;
-                       }
-
-                       Report.Debug (1, "REACHABLE", this, Type, CurrentUsageVector.Returns,
-                                     CurrentUsageVector.Breaks, CurrentUsageVector, MayLeaveLoop,
-                                     reachable);
-
-                       return reachable;
-               }
-
-               public override string ToString ()
-               {
-                       StringBuilder sb = new StringBuilder ("FlowBranching (");
-
-                       sb.Append (id);
-                       sb.Append (",");
-                       sb.Append (Type);
-                       if (Block != null) {
-                               sb.Append (" - ");
-                               sb.Append (Block.ID);
-                               sb.Append (" - ");
-                               sb.Append (Block.StartLocation);
-                       }
-                       sb.Append (" - ");
-                       sb.Append (Siblings.Length);
-                       sb.Append (" - ");
-                       sb.Append (CurrentUsageVector);
-                       sb.Append (")");
-                       return sb.ToString ();
-               }
-       }
-
-       // <summary>
-       //   This is used by the flow analysis code to keep track of the type of local variables
-       //   and variables.
-       //
-       //   The flow code uses a BitVector to keep track of whether a variable has been assigned
-       //   or not.  This is easy for fundamental types (int, char etc.) or reference types since
-       //   you can only assign the whole variable as such.
-       //
-       //   For structs, we also need to keep track of all its fields.  To do this, we allocate one
-       //   bit for the struct itself (it's used if you assign/access the whole struct) followed by
-       //   one bit for each of its fields.
-       //
-       //   This class computes this `layout' for each type.
-       // </summary>
-       public class TypeInfo
-       {
-               public readonly Type Type;
-
-               // <summary>
-               //   Total number of bits a variable of this type consumes in the flow vector.
-               // </summary>
-               public readonly int TotalLength;
-
-               // <summary>
-               //   Number of bits the simple fields of a variable of this type consume
-               //   in the flow vector.
-               // </summary>
-               public readonly int Length;
-
-               // <summary>
-               //   This is only used by sub-structs.
-               // </summary>
-               public readonly int Offset;
-
-               // <summary>
-               //   If this is a struct.
-               // </summary>
-               public readonly bool IsStruct;       
-
-               // <summary>
-               //   If this is a struct, all fields which are structs theirselves.
-               // </summary>
-               public TypeInfo[] SubStructInfo;
-
-               protected readonly StructInfo struct_info;
-               private static Hashtable type_hash = new Hashtable ();
-
-               public static TypeInfo GetTypeInfo (Type type)
-               {
-                       TypeInfo info = (TypeInfo) type_hash [type];
-                       if (info != null)
-                               return info;
-
-                       info = new TypeInfo (type);
-                       type_hash.Add (type, info);
-                       return info;
-               }
-
-               public static TypeInfo GetTypeInfo (TypeContainer tc)
-               {
-                       TypeInfo info = (TypeInfo) type_hash [tc.TypeBuilder];
-                       if (info != null)
-                               return info;
-
-                       info = new TypeInfo (tc);
-                       type_hash.Add (tc.TypeBuilder, info);
-                       return info;
-               }
-
-               private TypeInfo (Type type)
-               {
-                       this.Type = type;
-
-                       struct_info = StructInfo.GetStructInfo (type);
-                       if (struct_info != null) {
-                               Length = struct_info.Length;
-                               TotalLength = struct_info.TotalLength;
-                               SubStructInfo = struct_info.StructFields;
-                               IsStruct = true;
-                       } else {
-                               Length = 0;
-                               TotalLength = 1;
-                               IsStruct = false;
-                       }
-               }
-
-               private TypeInfo (TypeContainer tc)
-               {
-                       this.Type = tc.TypeBuilder;
-
-                       struct_info = StructInfo.GetStructInfo (tc);
-                       if (struct_info != null) {
-                               Length = struct_info.Length;
-                               TotalLength = struct_info.TotalLength;
-                               SubStructInfo = struct_info.StructFields;
-                               IsStruct = true;
-                       } else {
-                               Length = 0;
-                               TotalLength = 1;
-                               IsStruct = false;
-                       }
-               }
-
-               protected TypeInfo (StructInfo struct_info, int offset)
-               {
-                       this.struct_info = struct_info;
-                       this.Offset = offset;
-                       this.Length = struct_info.Length;
-                       this.TotalLength = struct_info.TotalLength;
-                       this.SubStructInfo = struct_info.StructFields;
-                       this.Type = struct_info.Type;
-                       this.IsStruct = true;
-               }
-
-               public int GetFieldIndex (string name)
-               {
-                       if (struct_info == null)
-                               return 0;
-
-                       return struct_info [name];
-               }
-
-               public TypeInfo GetSubStruct (string name)
-               {
-                       if (struct_info == null)
-                               return null;
-
-                       return struct_info.GetStructField (name);
-               }
-
-               // <summary>
-               //   A struct's constructor must always assign all fields.
-               //   This method checks whether it actually does so.
-               // </summary>
-               public bool IsFullyInitialized (FlowBranching branching, VariableInfo vi, Location loc)
-               {
-                       if (struct_info == null)
-                               return true;
-
-                       bool ok = true;
-                       for (int i = 0; i < struct_info.Count; i++) {
-                               FieldInfo field = struct_info.Fields [i];
-
-                               if (!branching.IsFieldAssigned (vi, field.Name)) {
-                                       Report.Error (171, loc,
-                                                     "Field `" + TypeManager.CSharpName (Type) +
-                                                     "." + field.Name + "' must be fully initialized " +
-                                                     "before control leaves the constructor");
-                                       ok = false;
-                               }
-                       }
-
-                       return ok;
-               }
-
-               public override string ToString ()
-               {
-                       return String.Format ("TypeInfo ({0}:{1}:{2}:{3})",
-                                             Type, Offset, Length, TotalLength);
-               }
-
-               protected class StructInfo {
-                       public readonly Type Type;
-                       public readonly FieldInfo[] Fields;
-                       public readonly TypeInfo[] StructFields;
-                       public readonly int Count;
-                       public readonly int CountPublic;
-                       public readonly int CountNonPublic;
-                       public readonly int Length;
-                       public readonly int TotalLength;
-                       public readonly bool HasStructFields;
-
-                       private static Hashtable field_type_hash = new Hashtable ();
-                       private Hashtable struct_field_hash;
-                       private Hashtable field_hash;
-
-                       protected bool InTransit = false;
-
-                       // Private constructor.  To save memory usage, we only need to create one instance
-                       // of this class per struct type.
-                       private StructInfo (Type type)
-                       {
-                               this.Type = type;
-
-                               field_type_hash.Add (type, this);
-
-                               if (type is TypeBuilder) {
-                                       TypeContainer tc = TypeManager.LookupTypeContainer (type);
-
-                                       ArrayList fields = tc.Fields;
-
-                                       ArrayList public_fields = new ArrayList ();
-                                       ArrayList non_public_fields = new ArrayList ();
-
-                                       if (fields != null) {
-                                               foreach (Field field in fields) {
-                                                       if ((field.ModFlags & Modifiers.STATIC) != 0)
-                                                               continue;
-                                                       if ((field.ModFlags & Modifiers.PUBLIC) != 0)
-                                                               public_fields.Add (field.FieldBuilder);
-                                                       else
-                                                               non_public_fields.Add (field.FieldBuilder);
-                                               }
-                                       }
-
-                                       CountPublic = public_fields.Count;
-                                       CountNonPublic = non_public_fields.Count;
-                                       Count = CountPublic + CountNonPublic;
-
-                                       Fields = new FieldInfo [Count];
-                                       public_fields.CopyTo (Fields, 0);
-                                       non_public_fields.CopyTo (Fields, CountPublic);
-                               } else {
-                                       FieldInfo[] public_fields = type.GetFields (
-                                               BindingFlags.Instance|BindingFlags.Public);
-                                       FieldInfo[] non_public_fields = type.GetFields (
-                                               BindingFlags.Instance|BindingFlags.NonPublic);
-
-                                       CountPublic = public_fields.Length;
-                                       CountNonPublic = non_public_fields.Length;
-                                       Count = CountPublic + CountNonPublic;
-
-                                       Fields = new FieldInfo [Count];
-                                       public_fields.CopyTo (Fields, 0);
-                                       non_public_fields.CopyTo (Fields, CountPublic);
-                               }
-
-                               struct_field_hash = new Hashtable ();
-                               field_hash = new Hashtable ();
-
-                               Length = 0;
-                               StructFields = new TypeInfo [Count];
-                               StructInfo[] sinfo = new StructInfo [Count];
-
-                               InTransit = true;
-
-                               for (int i = 0; i < Count; i++) {
-                                       FieldInfo field = (FieldInfo) Fields [i];
-
-                                       sinfo [i] = GetStructInfo (field.FieldType);
-                                       if (sinfo [i] == null)
-                                               field_hash.Add (field.Name, ++Length);
-                                       else if (sinfo [i].InTransit) {
-                                               Report.Error (523, String.Format (
-                                                                     "Struct member '{0}.{1}' of type '{2}' causes " +
-                                                                     "a cycle in the structure layout",
-                                                                     type, field.Name, sinfo [i].Type));
-                                               sinfo [i] = null;
-                                               return;
-                                       }
-                               }
-
-                               InTransit = false;
-
-                               TotalLength = Length + 1;
-                               for (int i = 0; i < Count; i++) {
-                                       FieldInfo field = (FieldInfo) Fields [i];
-
-                                       if (sinfo [i] == null)
-                                               continue;
-
-                                       field_hash.Add (field.Name, TotalLength);
-
-                                       HasStructFields = true;
-                                       StructFields [i] = new TypeInfo (sinfo [i], TotalLength);
-                                       struct_field_hash.Add (field.Name, StructFields [i]);
-                                       TotalLength += sinfo [i].TotalLength;
-                               }
-                       }
-
-                       public int this [string name] {
-                               get {
-                                       if (field_hash.Contains (name))
-                                               return (int) field_hash [name];
-                                       else
-                                               return 0;
-                               }
-                       }
-
-                       public TypeInfo GetStructField (string name)
-                       {
-                               return (TypeInfo) struct_field_hash [name];
-                       }
-
-                       public static StructInfo GetStructInfo (Type type)
-                       {
-                               if (!TypeManager.IsValueType (type) || TypeManager.IsEnumType (type) ||
-                                   TypeManager.IsBuiltinType (type))
-                                       return null;
-
-                               StructInfo info = (StructInfo) field_type_hash [type];
-                               if (info != null)
-                                       return info;
-
-                               return new StructInfo (type);
-                       }
-
-                       public static StructInfo GetStructInfo (TypeContainer tc)
-                       {
-                               StructInfo info = (StructInfo) field_type_hash [tc.TypeBuilder];
-                               if (info != null)
-                                       return info;
-
-                               return new StructInfo (tc.TypeBuilder);
-                       }
-               }
-       }
-
-       // <summary>
-       //   This is used by the flow analysis code to store information about a single local variable
-       //   or parameter.  Depending on the variable's type, we need to allocate one or more elements
-       //   in the BitVector - if it's a fundamental or reference type, we just need to know whether
-       //   it has been assigned or not, but for structs, we need this information for each of its fields.
-       // </summary>
-       public class VariableInfo {
-               public readonly string Name;
-               public readonly TypeInfo TypeInfo;
-
-               // <summary>
-               //   The bit offset of this variable in the flow vector.
-               // </summary>
-               public readonly int Offset;
-
-               // <summary>
-               //   The number of bits this variable needs in the flow vector.
-               //   The first bit always specifies whether the variable as such has been assigned while
-               //   the remaining bits contain this information for each of a struct's fields.
-               // </summary>
-               public readonly int Length;
-
-               // <summary>
-               //   If this is a parameter of local variable.
-               // </summary>
-               public readonly bool IsParameter;
-
-               public readonly LocalInfo LocalInfo;
-               public readonly int ParameterIndex;
-
-               readonly VariableInfo Parent;
-               VariableInfo[] sub_info;
-
-               protected VariableInfo (string name, Type type, int offset)
-               {
-                       this.Name = name;
-                       this.Offset = offset;
-                       this.TypeInfo = TypeInfo.GetTypeInfo (type);
-
-                       Length = TypeInfo.TotalLength;
-
-                       Initialize ();
-               }
-
-               protected VariableInfo (VariableInfo parent, TypeInfo type)
-               {
-                       this.Name = parent.Name;
-                       this.TypeInfo = type;
-                       this.Offset = parent.Offset + type.Offset;
-                       this.Parent = parent;
-                       this.Length = type.TotalLength;
-
-                       this.IsParameter = parent.IsParameter;
-                       this.LocalInfo = parent.LocalInfo;
-                       this.ParameterIndex = parent.ParameterIndex;
-
-                       Initialize ();
-               }
-
-               protected void Initialize ()
-               {
-                       TypeInfo[] sub_fields = TypeInfo.SubStructInfo;
-                       if (sub_fields != null) {
-                               sub_info = new VariableInfo [sub_fields.Length];
-                               for (int i = 0; i < sub_fields.Length; i++) {
-                                       if (sub_fields [i] != null)
-                                               sub_info [i] = new VariableInfo (this, sub_fields [i]);
-                               }
-                       } else
-                               sub_info = new VariableInfo [0];
-               }
-
-               public VariableInfo (LocalInfo local_info, int offset)
-                       : this (local_info.Name, local_info.VariableType, offset)
-               {
-                       this.LocalInfo = local_info;
-                       this.IsParameter = false;
-               }
-
-               public VariableInfo (string name, Type type, int param_idx, int offset)
-                       : this (name, type, offset)
-               {
-                       this.ParameterIndex = param_idx;
-                       this.IsParameter = true;
-               }
-
-               public bool IsAssigned (EmitContext ec)
-               {
-                       return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (this);
-               }
-
-               public bool IsAssigned (EmitContext ec, Location loc)
-               {
-                       if (IsAssigned (ec))
-                               return true;
-
-                       Report.Error (165, loc,
-                                     "Use of unassigned local variable `" + Name + "'");
-                       ec.CurrentBranching.SetAssigned (this);
-                       return false;
-               }
-
-               public bool IsAssigned (MyBitVector vector)
-               {
-                       if (vector [Offset])
-                               return true;
-
-                       for (VariableInfo parent = Parent; parent != null; parent = parent.Parent)
-                               if (vector [parent.Offset])
-                                       return true;
-
-                       // Return unless this is a struct.
-                       if (!TypeInfo.IsStruct)
-                               return false;
-
-                       // Ok, so each field must be assigned.
-                       for (int i = 0; i < TypeInfo.Length; i++) {
-                               if (!vector [Offset + i + 1])
-                                       return false;
-                       }
-
-                       // Ok, now check all fields which are structs.
-                       for (int i = 0; i < sub_info.Length; i++) {
-                               VariableInfo sinfo = sub_info [i];
-                               if (sinfo == null)
-                                       continue;
-
-                               if (!sinfo.IsAssigned (vector))
-                                       return false;
-                       }
-
-                       vector [Offset] = true;
-                       return true;
-               }
-
-               public void SetAssigned (EmitContext ec)
-               {
-                       if (ec.DoFlowAnalysis)
-                               ec.CurrentBranching.SetAssigned (this);
-               }
-
-               public void SetAssigned (MyBitVector vector)
-               {
-                       vector [Offset] = true;
-               }
-
-               public bool IsFieldAssigned (EmitContext ec, string name, Location loc)
-               {
-                       if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsFieldAssigned (this, name))
-                               return true;
-
-                       Report.Error (170, loc,
-                                     "Use of possibly unassigned field `" + name + "'");
-                       ec.CurrentBranching.SetFieldAssigned (this, name);
-                       return false;
-               }
-
-               public bool IsFieldAssigned (MyBitVector vector, string field_name)
-               {
-                       int field_idx = TypeInfo.GetFieldIndex (field_name);
-
-                       if (field_idx == 0)
-                               return true;
-
-                       return vector [Offset + field_idx];
-               }
-
-               public void SetFieldAssigned (EmitContext ec, string name)
-               {
-                       if (ec.DoFlowAnalysis)
-                               ec.CurrentBranching.SetFieldAssigned (this, name);
-               }
-
-               public void SetFieldAssigned (MyBitVector vector, string field_name)
-               {
-                       int field_idx = TypeInfo.GetFieldIndex (field_name);
-
-                       if (field_idx == 0)
-                               return;
-
-                       vector [Offset + field_idx] = true;
-               }
-
-               public VariableInfo GetSubStruct (string name)
-               {
-                       TypeInfo type = TypeInfo.GetSubStruct (name);
-
-                       if (type == null)
-                               return null;
-
-                       return new VariableInfo (this, type);
-               }
-
-               public override string ToString ()
-               {
-                       return String.Format ("VariableInfo ({0}:{1}:{2}:{3}:{4})",
-                                             Name, TypeInfo, Offset, Length, IsParameter);
-               }
-       }
-
-       // <summary>
-       //   This is used by the flow code to hold the `layout' of the flow vector for
-       //   all locals and all parameters (ie. we create one instance of this class for the
-       //   locals and another one for the params).
-       // </summary>
-       public class VariableMap {
-               // <summary>
-               //   The number of variables in the map.
-               // </summary>
-               public readonly int Count;
-
-               // <summary>
-               //   Total length of the flow vector for this map.
-               // <summary>
-               public readonly int Length;
-
-               // <summary>
-               //   Type and name of all the variables.
-               //   Note that this is null for variables for which we do not need to compute
-               //   assignment info.
-               // </summary>
-               public readonly Type[] VariableTypes;
-               public readonly string[] VariableNames;
-
-               VariableInfo[] map;
-
-               public VariableMap (InternalParameters ip)
-               {
-                       Count = ip != null ? ip.Count : 0;
-                       map = new VariableInfo [Count];
-                       VariableNames = new string [Count];
-                       VariableTypes = new Type [Count];
-                       Length = 0;
-
-                       for (int i = 0; i < Count; i++) {
-                               Parameter.Modifier mod = ip.ParameterModifier (i);
-
-                               if ((mod & Parameter.Modifier.OUT) == 0)
-                                       continue;
-
-                               VariableNames [i] = ip.ParameterName (i);
-                               VariableTypes [i] = TypeManager.GetElementType (ip.ParameterType (i));
-
-                               map [i] = new VariableInfo (VariableNames [i], VariableTypes [i], i, Length);
-                               Length += map [i].Length;
-                       }
-               }
-
-               public VariableMap (LocalInfo[] locals)
-                       : this (null, locals)
-               { }
-
-               public VariableMap (VariableMap parent, LocalInfo[] locals)
-               {
-                       int offset = 0, start = 0;
-                       if (parent != null) {
-                               offset = parent.Length;
-                               start = parent.Count;
-                       }
-
-                       Count = locals.Length + start;
-                       map = new VariableInfo [Count];
-                       VariableNames = new string [Count];
-                       VariableTypes = new Type [Count];
-                       Length = offset;
-
-                       if (parent != null) {
-                               parent.map.CopyTo (map, 0);
-                               parent.VariableNames.CopyTo (VariableNames, 0);
-                               parent.VariableTypes.CopyTo (VariableTypes, 0);
-                       }
-
-                       for (int i = start; i < Count; i++) {
-                               LocalInfo li = locals [i-start];
-
-                               if (li.VariableType == null)
-                                       continue;
-
-                               VariableNames [i] = li.Name;
-                               VariableTypes [i] = li.VariableType;
-
-                               map [i] = li.VariableInfo = new VariableInfo (li, Length);
-                               Length += map [i].Length;
-                       }
-               }
-
-               // <summary>
-               //   Returns the VariableInfo for variable @index or null if we don't need to
-               //   compute assignment info for this variable.
-               // </summary>
-               public VariableInfo this [int index] {
-                       get {
-                               return map [index];
-                       }
-               }
-
-               public override string ToString ()
-               {
-                       return String.Format ("VariableMap ({0}:{1})", Count, Length);
-               }
-       }
-
        public class LocalInfo {
                public Expression Type;
 
@@ -2852,7 +1109,10 @@ namespace Mono.CSharp {
                [Flags]
                public enum Flags : byte {
                        Implicit  = 1,
-                       Unchecked = 2
+                       Unchecked = 2,
+                       BlockUsed = 4,
+                       VariablesInitialized = 8,
+                       HasRet = 16
                }
                Flags flags;
 
@@ -2904,8 +1164,6 @@ namespace Mono.CSharp {
                //
                Block switch_block;
 
-               bool used = false;
-
                static int id;
 
                int this_id;
@@ -3148,7 +1406,7 @@ namespace Mono.CSharp {
 
                        variables.Add (name, vi);
 
-                       if (variables_initialized)
+                       if ((flags & Flags.VariablesInitialized) != 0)
                                throw new Exception ();
 
                        // Console.WriteLine ("Adding {0} to {1}", name, ID);
@@ -3264,26 +1522,25 @@ namespace Mono.CSharp {
                public void AddStatement (Statement s)
                {
                        statements.Add (s);
-                       used = true;
+                       flags |= Flags.BlockUsed;
                }
 
                public bool Used {
                        get {
-                               return used;
+                               return (flags & Flags.BlockUsed) != 0;
                        }
                }
 
                public void Use ()
                {
-                       used = true;
+                       flags |= Flags.BlockUsed;
                }
 
                VariableMap param_map, local_map;
-               bool variables_initialized = false;
 
                public VariableMap ParameterMap {
                        get {
-                               if (!variables_initialized)
+                               if ((flags & Flags.VariablesInitialized) == 0)
                                        throw new Exception ();
 
                                return param_map;
@@ -3292,7 +1549,7 @@ namespace Mono.CSharp {
 
                public VariableMap LocalMap {
                        get {
-                               if (!variables_initialized)
+                               if ((flags & Flags.VariablesInitialized) == 0)
                                        throw new Exception ();
 
                                return local_map;
@@ -3305,10 +1562,8 @@ namespace Mono.CSharp {
                /// <remarks>
                ///   tc: is our typecontainer (to resolve type references)
                ///   ig: is the code generator:
-               ///   toplevel: the toplevel block.  This is used for checking 
-               ///             that no two labels with the same name are used.
                /// </remarks>
-               public void EmitMeta (EmitContext ec, InternalParameters ip, Block toplevel)
+               public void EmitMeta (EmitContext ec, InternalParameters ip)
                {
                        DeclSpace ds = ec.DeclSpace;
                        ILGenerator ig = ec.ig;
@@ -3336,7 +1591,7 @@ namespace Mono.CSharp {
                                local_map = new VariableMap (locals);
 
                        param_map = new VariableMap (ip);
-                       variables_initialized = true;
+                       flags |= Flags.VariablesInitialized;
 
                        bool old_check_state = ec.ConstantCheckState;
                        ec.ConstantCheckState = (flags & Flags.Unchecked) == 0;
@@ -3401,7 +1656,7 @@ namespace Mono.CSharp {
                        //
                        if (children != null){
                                foreach (Block b in children)
-                                       b.EmitMeta (ec, ip, toplevel);
+                                       b.EmitMeta (ec, ip);
                        }
                }
 
@@ -3436,8 +1691,6 @@ namespace Mono.CSharp {
                                        b.UsageWarning ();
                }
 
-               bool has_ret = false;
-
                public override bool Resolve (EmitContext ec)
                {
                        Block prev_block = ec.CurrentBlock;
@@ -3478,12 +1731,12 @@ namespace Mono.CSharp {
 
                        Report.Debug (1, "RESOLVE BLOCK DONE", StartLocation, ec.CurrentBranching);
 
-                       FlowReturns returns = ec.EndFlowBranching ();
+                       FlowBranching.FlowReturns returns = ec.EndFlowBranching ();
                        ec.CurrentBlock = prev_block;
 
                        // If we're a non-static `struct' constructor which doesn't have an
                        // initializer, then we must initialize all of the struct's fields.
-                       if ((this_variable != null) && (returns != FlowReturns.EXCEPTION) &&
+                       if ((this_variable != null) && (returns != FlowBranching.FlowReturns.Exception) &&
                            !this_variable.IsThisAssigned (ec, loc))
                                ok = false;
 
@@ -3494,10 +1747,10 @@ namespace Mono.CSharp {
                                                                "This label has not been referenced");
                        }
 
-                       if ((returns == FlowReturns.ALWAYS) ||
-                           (returns == FlowReturns.EXCEPTION) ||
-                           (returns == FlowReturns.UNREACHABLE))
-                               has_ret = true;
+                       if ((returns == FlowBranching.FlowReturns.Always) ||
+                           (returns == FlowBranching.FlowReturns.Exception) ||
+                           (returns == FlowBranching.FlowReturns.Unreachable))
+                               flags |= Flags.HasRet;
 
                        return ok;
                }
@@ -3507,7 +1760,7 @@ namespace Mono.CSharp {
                        foreach (Statement s in statements)
                                s.Emit (ec);
 
-                       return has_ret;
+                       return (flags & Flags.HasRet) != 0;
                }
 
                public override bool Emit (EmitContext ec)
@@ -4288,12 +2541,12 @@ namespace Mono.CSharp {
                        ec.Switch = this;
                        ec.Switch.SwitchType = SwitchType;
 
-                       ec.StartFlowBranching (FlowBranchingType.SWITCH, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Switch, loc);
 
                        bool first = true;
                        foreach (SwitchSection ss in Sections){
                                if (!first)
-                                       ec.CurrentBranching.CreateSibling ();
+                                       ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.SwitchSection);
                                else
                                        first = false;
 
@@ -4303,7 +2556,7 @@ namespace Mono.CSharp {
 
 
                        if (!got_default)
-                               ec.CurrentBranching.CreateSibling ();
+                               ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.SwitchSection);
 
                        ec.EndFlowBranching ();
                        ec.Switch = old_switch;
@@ -4836,7 +3089,7 @@ namespace Mono.CSharp {
                {
                        bool ok = true;
                        
-                       ec.StartFlowBranching (FlowBranchingType.EXCEPTION, Block.StartLocation);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Exception, Block.StartLocation);
 
                        Report.Debug (1, "START OF TRY BLOCK", Block.StartLocation);
 
@@ -4853,7 +3106,7 @@ namespace Mono.CSharp {
                        Report.Debug (1, "START OF CATCH BLOCKS", vector);
 
                        foreach (Catch c in Specific){
-                               ec.CurrentBranching.CreateSibling ();
+                               ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Catch);
                                Report.Debug (1, "STARTED SIBLING FOR CATCH", ec.CurrentBranching);
 
                                if (c.Name != null) {
@@ -4883,7 +3136,7 @@ namespace Mono.CSharp {
                        Report.Debug (1, "END OF CATCH BLOCKS", ec.CurrentBranching);
 
                        if (General != null){
-                               ec.CurrentBranching.CreateSibling ();
+                               ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Catch);
                                Report.Debug (1, "STARTED SIBLING FOR GENERAL", ec.CurrentBranching);
 
                                bool old_in_catch = ec.InCatch;
@@ -4906,7 +3159,7 @@ namespace Mono.CSharp {
 
                        if (Fini != null) {
                                if (ok)
-                                       ec.CurrentBranching.CreateSiblingForFinally ();
+                                       ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Finally);
                                Report.Debug (1, "STARTED SIBLING FOR FINALLY", ec.CurrentBranching, vector);
 
                                bool old_in_finally = ec.InFinally;
@@ -4918,13 +3171,13 @@ namespace Mono.CSharp {
                                ec.InFinally = old_in_finally;
                        }
 
-                       FlowReturns returns = ec.EndFlowBranching ();
+                       FlowBranching.FlowReturns returns = ec.EndFlowBranching ();
 
                        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)) {
+                       if ((returns == FlowBranching.FlowReturns.Sometimes) || (returns == FlowBranching.FlowReturns.Always)) {
                                ec.CurrentBranching.CheckOutParameters (f_vector.Parameters, loc);
                        }
 
@@ -4932,7 +3185,7 @@ namespace Mono.CSharp {
 
                        Report.Debug (1, "END OF TRY", ec.CurrentBranching);
 
-                       if (returns != FlowReturns.ALWAYS) {
+                       if (returns != FlowBranching.FlowReturns.Always) {
                                // Unfortunately, System.Reflection.Emit automatically emits a leave
                                // to the end of the finally block.  This is a problem if `returns'
                                // is true since we may jump to a point after the end of the method.
@@ -5207,7 +3460,7 @@ namespace Mono.CSharp {
        /// </summary>
        public class Foreach : Statement {
                Expression type;
-               LocalVariableReference variable;
+               Expression variable;
                Expression expr;
                Statement statement;
                ForeachHelperMethods hm;
@@ -5266,8 +3519,8 @@ namespace Mono.CSharp {
                                empty = new EmptyExpression (hm.element_type);
                        }
 
-                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
-                       ec.CurrentBranching.CreateSibling ();
+                       ec.StartFlowBranching (FlowBranching.BranchingType.LoopBlock, loc);
+                       ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
 
                        //
                        //
@@ -5281,13 +3534,14 @@ namespace Mono.CSharp {
                        if (conv == null)
                                return false;
 
-                       if (variable.ResolveLValue (ec, empty) == null)
+                       variable = variable.ResolveLValue (ec, empty);
+                       if (variable == null)
                                return false;
 
                        if (!statement.Resolve (ec))
                                return false;
 
-                       FlowReturns returns = ec.EndFlowBranching ();
+                       FlowBranching.FlowReturns returns = ec.EndFlowBranching ();
 
                        return true;
                }
@@ -5541,14 +3795,15 @@ namespace Mono.CSharp {
                bool EmitCollectionForeach (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       LocalBuilder enumerator, disposable;
+                       VariableStorage enumerator, disposable;
 
-                       enumerator = ig.DeclareLocal (hm.enumerator_type);
+                       enumerator = new VariableStorage (ec, hm.enumerator_type);
                        if (hm.is_disposable)
-                               disposable = ig.DeclareLocal (TypeManager.idisposable_type);
+                               disposable = new VariableStorage (ec, TypeManager.idisposable_type);
                        else
                                disposable = null;
-                       
+
+                       enumerator.EmitThis ();
                        //
                        // Instantiate the enumerator
                        //
@@ -5565,7 +3820,7 @@ namespace Mono.CSharp {
                                expr.Emit (ec);
                                ig.Emit (OpCodes.Callvirt, hm.get_enumerator);
                        }
-                       ig.Emit (OpCodes.Stloc, enumerator);
+                       enumerator.EmitStore ();
 
                        //
                        // Protect the code in a try/finalize block, so that
@@ -5582,13 +3837,21 @@ namespace Mono.CSharp {
                        Label end_try = ig.DefineLabel ();
                        
                        ig.MarkLabel (ec.LoopBegin);
-                       ig.Emit (OpCodes.Ldloc, enumerator);
+                       enumerator.EmitLoad ();
                        ig.Emit (OpCodes.Callvirt, hm.move_next);
                        ig.Emit (OpCodes.Brfalse, end_try);
-                       ig.Emit (OpCodes.Ldloc, enumerator);
+                       if (ec.InIterator)
+                               ec.EmitThis ();
+                       
+                       enumerator.EmitLoad ();
                        ig.Emit (OpCodes.Callvirt, hm.get_current);
 
-                       variable.EmitAssign (ec, conv);
+                       if (ec.InIterator){
+                               conv.Emit (ec);
+                               ig.Emit (OpCodes.Stfld, ((FieldExpr) variable).FieldInfo);
+                       } else 
+                               ((IAssignMethod)variable).EmitAssign (ec, conv);
+                               
                        statement.Emit (ec);
                        ig.Emit (OpCodes.Br, ec.LoopBegin);
                        ig.MarkLabel (end_try);
@@ -5605,13 +3868,16 @@ namespace Mono.CSharp {
                                bool old_in_finally = ec.InFinally;
                                ec.InFinally = true;
                                ig.BeginFinallyBlock ();
-                       
-                               ig.Emit (OpCodes.Ldloc, enumerator);
+
+                               disposable.EmitThis ();
+                               enumerator.EmitThis ();
+                               enumerator.EmitLoad ();
                                ig.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
-                               ig.Emit (OpCodes.Stloc, disposable);
-                               ig.Emit (OpCodes.Ldloc, disposable);
+                               disposable.EmitStore ();
+                               disposable.EmitLoad ();
                                ig.Emit (OpCodes.Brfalse, end_finally);
-                               ig.Emit (OpCodes.Ldloc, disposable);
+                               disposable.EmitThis ();
+                               disposable.EmitLoad ();
                                ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
                                ig.MarkLabel (end_finally);
                                ec.InFinally = old_in_finally;
@@ -5635,82 +3901,106 @@ namespace Mono.CSharp {
                        int rank = array_type.GetArrayRank ();
                        ILGenerator ig = ec.ig;
 
-                       LocalBuilder copy = ig.DeclareLocal (array_type);
+                       VariableStorage copy = new VariableStorage (ec, array_type);
                        
                        //
                        // Make our copy of the array
                        //
+                       copy.EmitThis ();
                        expr.Emit (ec);
-                       ig.Emit (OpCodes.Stloc, copy);
+                       copy.EmitStore ();
                        
                        if (rank == 1){
-                               LocalBuilder counter = ig.DeclareLocal (TypeManager.int32_type);
+                               VariableStorage counter = new VariableStorage (ec,TypeManager.int32_type);
 
                                Label loop, test;
-                               
+
+                               counter.EmitThis ();
                                ig.Emit (OpCodes.Ldc_I4_0);
-                               ig.Emit (OpCodes.Stloc, counter);
+                               counter.EmitStore ();
                                test = ig.DefineLabel ();
                                ig.Emit (OpCodes.Br, test);
 
                                loop = ig.DefineLabel ();
                                ig.MarkLabel (loop);
 
-                               ig.Emit (OpCodes.Ldloc, copy);
-                               ig.Emit (OpCodes.Ldloc, counter);
+                               if (ec.InIterator)
+                                       ec.EmitThis ();
+                               
+                               copy.EmitThis ();
+                               copy.EmitLoad ();
+                               counter.EmitThis ();
+                               counter.EmitLoad ();
 
                                //
                                // Load the value, we load the value using the underlying type,
                                // then we use the variable.EmitAssign to load using the proper cast.
                                //
                                ArrayAccess.EmitLoadOpcode (ig, element_type);
-                               variable.EmitAssign (ec, conv);
+                               if (ec.InIterator){
+                                       conv.Emit (ec);
+                                       ig.Emit (OpCodes.Stfld, ((FieldExpr) variable).FieldInfo);
+                               } else 
+                                       ((IAssignMethod)variable).EmitAssign (ec, conv);
 
                                statement.Emit (ec);
 
                                ig.MarkLabel (ec.LoopBegin);
-                               ig.Emit (OpCodes.Ldloc, counter);
+                               counter.EmitThis ();
+                               counter.EmitThis ();
+                               counter.EmitLoad ();
                                ig.Emit (OpCodes.Ldc_I4_1);
                                ig.Emit (OpCodes.Add);
-                               ig.Emit (OpCodes.Stloc, counter);
+                               counter.EmitStore ();
 
                                ig.MarkLabel (test);
-                               ig.Emit (OpCodes.Ldloc, counter);
-                               ig.Emit (OpCodes.Ldloc, copy);
+                               counter.EmitThis ();
+                               counter.EmitLoad ();
+                               copy.EmitThis ();
+                               copy.EmitLoad ();
                                ig.Emit (OpCodes.Ldlen);
                                ig.Emit (OpCodes.Conv_I4);
                                ig.Emit (OpCodes.Blt, loop);
                        } else {
-                               LocalBuilder [] dim_len   = new LocalBuilder [rank];
-                               LocalBuilder [] dim_count = new LocalBuilder [rank];
+                               VariableStorage [] dim_len   = new VariableStorage [rank];
+                               VariableStorage [] dim_count = new VariableStorage [rank];
                                Label [] loop = new Label [rank];
                                Label [] test = new Label [rank];
                                int dim;
                                
                                for (dim = 0; dim < rank; dim++){
-                                       dim_len [dim] = ig.DeclareLocal (TypeManager.int32_type);
-                                       dim_count [dim] = ig.DeclareLocal (TypeManager.int32_type);
+                                       dim_len [dim] = new VariableStorage (ec, TypeManager.int32_type);
+                                       dim_count [dim] = new VariableStorage (ec, TypeManager.int32_type);
                                        test [dim] = ig.DefineLabel ();
                                        loop [dim] = ig.DefineLabel ();
                                }
                                        
                                for (dim = 0; dim < rank; dim++){
-                                       ig.Emit (OpCodes.Ldloc, copy);
+                                       dim_len [dim].EmitThis ();
+                                       copy.EmitThis ();
+                                       copy.EmitLoad ();
                                        IntLiteral.EmitInt (ig, dim);
                                        ig.Emit (OpCodes.Callvirt, TypeManager.int_getlength_int);
-                                       ig.Emit (OpCodes.Stloc, dim_len [dim]);
+                                       dim_len [dim].EmitStore ();
+                                       
                                }
 
                                for (dim = 0; dim < rank; dim++){
+                                       dim_count [dim].EmitThis ();
                                        ig.Emit (OpCodes.Ldc_I4_0);
-                                       ig.Emit (OpCodes.Stloc, dim_count [dim]);
+                                       dim_count [dim].EmitStore ();
                                        ig.Emit (OpCodes.Br, test [dim]);
                                        ig.MarkLabel (loop [dim]);
                                }
 
-                               ig.Emit (OpCodes.Ldloc, copy);
-                               for (dim = 0; dim < rank; dim++)
-                                       ig.Emit (OpCodes.Ldloc, dim_count [dim]);
+                               if (ec.InIterator)
+                                       ec.EmitThis ();
+                               copy.EmitThis ();
+                               copy.EmitLoad ();
+                               for (dim = 0; dim < rank; dim++){
+                                       dim_count [dim].EmitThis ();
+                                       dim_count [dim].EmitLoad ();
+                               }
 
                                //
                                // FIXME: Maybe we can cache the computation of `get'?
@@ -5727,18 +4017,26 @@ namespace Mono.CSharp {
                                        CallingConventions.HasThis| CallingConventions.Standard,
                                        var_type, args);
                                ig.Emit (OpCodes.Call, get);
-                               variable.EmitAssign (ec, conv);
+                               if (ec.InIterator){
+                                       conv.Emit (ec);
+                                       ig.Emit (OpCodes.Stfld, ((FieldExpr) variable).FieldInfo);
+                               } else 
+                                       ((IAssignMethod)variable).EmitAssign (ec, conv);
                                statement.Emit (ec);
                                ig.MarkLabel (ec.LoopBegin);
                                for (dim = rank - 1; dim >= 0; dim--){
-                                       ig.Emit (OpCodes.Ldloc, dim_count [dim]);
+                                       dim_count [dim].EmitThis ();
+                                       dim_count [dim].EmitThis ();
+                                       dim_count [dim].EmitLoad ();
                                        ig.Emit (OpCodes.Ldc_I4_1);
                                        ig.Emit (OpCodes.Add);
-                                       ig.Emit (OpCodes.Stloc, dim_count [dim]);
+                                       dim_count [dim].EmitStore ();
 
                                        ig.MarkLabel (test [dim]);
-                                       ig.Emit (OpCodes.Ldloc, dim_count [dim]);
-                                       ig.Emit (OpCodes.Ldloc, dim_len [dim]);
+                                       dim_count [dim].EmitThis ();
+                                       dim_count [dim].EmitLoad ();
+                                       dim_len [dim].EmitThis ();
+                                       dim_len [dim].EmitLoad ();
                                        ig.Emit (OpCodes.Blt, loop [dim]);
                                }
                        }
index c93be326bf6fa2bd413bc4004354cc692f06a02d..64f87b5194592e3d5ca4e97fc59bb6176ee34006 100755 (executable)
@@ -9,6 +9,7 @@
 //
 
 using System;
+using System.IO;
 using System.Text;
 using System.Reflection;
 using System.Collections;
@@ -255,4 +256,76 @@ namespace Mono.CSharp {
                }
        }
 
+       /// <summary>
+       ///   This is a wrapper around StreamReader which is seekable.
+       /// </summary>
+       public class SeekableStreamReader
+       {
+               public SeekableStreamReader (StreamReader reader)
+               {
+                       this.reader = reader;
+                       this.buffer = new char [DefaultCacheSize];
+               }
+
+               public SeekableStreamReader (Stream stream, Encoding encoding, bool detect_encoding_from_bytemarks)
+                       : this (new StreamReader (stream, encoding, detect_encoding_from_bytemarks))
+               { }
+
+               StreamReader reader;
+
+               private const int DefaultCacheSize = 1024;
+
+               char[] buffer;
+               int buffer_start;
+               int buffer_size;
+               int pos;
+
+               /// <remarks>
+               ///   The difference to the StreamReader's BaseStream.Position is that this one is reliable; ie. it
+               //    always reports the correct position and if it's modified, it also takes care of the buffered data.
+               /// </remarks>
+               public int Position {
+                       get {
+                               return buffer_start + pos;
+                       }
+
+                       set {
+                               // This one is easy: we're modifying the position within our current
+                               // buffer.
+                               if ((value >= buffer_start) && (value < buffer_start + buffer_size)) {
+                                       pos = value - buffer_start;
+                                       return;
+                               }
+
+                               // Ok, now we need to seek.
+                               reader.DiscardBufferedData ();
+                               reader.BaseStream.Position = buffer_start = value;
+                               buffer_size = pos = 0;
+                       }
+               }
+
+               private bool ReadBuffer ()
+               {
+                       pos = 0;
+                       buffer_start += buffer_size;
+                       buffer_size = reader.Read (buffer, 0, buffer.Length);
+                       return buffer_size > 0;
+               }
+
+               public int Peek ()
+               {
+                       if ((pos >= buffer_size) && !ReadBuffer ())
+                               return -1;
+
+                       return buffer [pos];
+               }
+
+               public int Read ()
+               {
+                       if ((pos >= buffer_size) && !ReadBuffer ())
+                               return -1;
+
+                       return buffer [pos++];
+               }
+       }
 }
index 801ceba84ae8efae4d5820115cd01dab86302168..e3544a31f16181189c7d1145b43c1d886da33905 100755 (executable)
@@ -1622,6 +1622,11 @@ public class TypeManager {
                return true;
        }
 
+       //
+       // The return value can be null;  This will be the case for
+       // auxiliary FieldBuilders created by the compiler that have no
+       // real field being declared on the source code
+       //
        static public FieldBase GetField (FieldInfo fb)
        {
                return (FieldBase) fieldbuilders_to_fields [fb];
@@ -2051,14 +2056,19 @@ public class TypeManager {
        //
        // Returns whether the array of memberinfos contains the given method
        //
-       static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
+       public static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
        {
                Type [] new_args = TypeManager.GetArgumentTypes (new_method);
                
-               foreach (MethodBase method in array){
+               foreach (MethodBase method in array) {
                        if (method.Name != new_method.Name)
                                continue;
-                       
+
+                        if (method is MethodInfo && new_method is MethodInfo)
+                                if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
+                                        continue;
+
+                        
                        Type [] old_args = TypeManager.GetArgumentTypes (method);
                        int old_count = old_args.Length;
                        int i;
@@ -2075,6 +2085,7 @@ public class TypeManager {
 
                        return true;
                }
+                
                return false;
        }