2010-05-27 Marek Safar <marek.safar@gmail.com>
authorMarek Safar <marek.safar@gmail.com>
Thu, 27 May 2010 18:56:10 +0000 (18:56 -0000)
committerMarek Safar <marek.safar@gmail.com>
Thu, 27 May 2010 18:56:10 +0000 (18:56 -0000)
A fix for bugs #608007, #572540, #566130, #476358

* generic.cs, linq.cs, expression.cs, statement.cs, cs-parser.jay:
More tricky refactoring of implicit linq blocks.

svn path=/trunk/mcs/; revision=158058

mcs/mcs/ChangeLog
mcs/mcs/cs-parser.jay
mcs/mcs/expression.cs
mcs/mcs/generic.cs
mcs/mcs/linq.cs
mcs/mcs/statement.cs

index 0024151c0bd321d0e8e0523221473df744678ab1..41ad1ae1b640d86fdd309bf33e703ca51dcb4adf 100644 (file)
@@ -1,3 +1,10 @@
+2010-05-27  Marek Safar  <marek.safar@gmail.com>
+
+       A fix for bugs #608007, #572540, #566130, #476358
+
+       * generic.cs, linq.cs, expression.cs, statement.cs, cs-parser.jay:
+       More tricky refactoring of implicit linq blocks.
+       
 2010-05-25  Marek Safar  <marek.safar@gmail.com>
 
        * linq.cs, cs-parser.jay: Keep location for all linq clauses.
index f89b24b8beca08a60fb06c472fea683daca775a2..adccfdf4da46cdb75f6113233ba148aefd1cf8d9 100644 (file)
@@ -54,7 +54,6 @@ namespace Mono.CSharp
 
                Delegate   current_delegate;
                
-               GenericMethod current_generic_method;
                AnonymousMethodExpression current_anonymous_method;
 
                /// <summary>
@@ -1273,7 +1272,6 @@ method_declaration
                        Report.Error (531, method.Location, "`{0}': interface members cannot have a definition", method.GetSignatureForError ());
                }
 
-               current_generic_method = null;
                current_local_parameters = null;
 
                if (RootContext.Documentation != null)
@@ -1320,8 +1318,6 @@ method_header
                                method.GetSignatureForError ());
                }
 
-               current_generic_method = generic;
-
                if (RootContext.Documentation != null)
                        method.DocComment = Lexer.consume_doc_comment ();
 
@@ -1382,8 +1378,6 @@ method_header
                method = new Method (current_class, generic, TypeManager.system_void_expr,
                                     modifiers, name, current_local_parameters, (Attributes) $1);
 
-               current_generic_method = generic;
-
                if (RootContext.Documentation != null)
                        method.DocComment = Lexer.consume_doc_comment ();
 
@@ -5444,30 +5438,42 @@ query_expression
 first_from_clause
        : FROM_FIRST IDENTIFIER IN expression
          {
-               $$ = new Linq.QueryExpression (current_block, new Linq.QueryStartClause ((Expression)$4));
-               var lt = (Tokenizer.LocatedToken) $2;
-               current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1));
+               current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
+         
+               var lt = (Tokenizer.LocatedToken) $2;     
+               $$ = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1)));
          }
        | FROM_FIRST type IDENTIFIER IN expression
          {
+               current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
+         
                var lt = (Tokenizer.LocatedToken) $3;
-               $$ = new Linq.QueryExpression (current_block, new Linq.Cast ((FullNamedExpression)$2, (Expression)$5));
-               current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1));
+               $$ = new Linq.QueryExpression (
+                       new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1)) {
+                               IdentifierType = (FullNamedExpression)$2
+                       }
+               );
          }
        ;
 
 nested_from_clause
        : FROM IDENTIFIER IN expression
          {
-               $$ = new Linq.QueryExpression (current_block, new Linq.QueryStartClause ((Expression)$4));
-               var lt = (Tokenizer.LocatedToken) $2;
-               current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1));
+               current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
+         
+               var lt = (Tokenizer.LocatedToken) $2;     
+               $$ = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1)));
          }
        | FROM type IDENTIFIER IN expression
          {
-               $$ = new Linq.QueryExpression (current_block, new Linq.Cast ((FullNamedExpression)$2, (Expression)$5));
+               current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
+         
                var lt = (Tokenizer.LocatedToken) $3;
-               current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1));
+               $$ = new Linq.QueryExpression (
+                       new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1)) {
+                               IdentifierType = (FullNamedExpression)$2
+                       }
+               );
          }
        ;
        
@@ -5485,7 +5491,7 @@ from_clause
                current_block.SetEndLocation (lexer.Location);
                current_block = current_block.Parent;
                
-               ((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn);
+               ((Linq.QueryBlock)current_block).AddRangeVariable (sn);
          }       
        | FROM type IDENTIFIER IN
          {
@@ -5496,14 +5502,14 @@ from_clause
                var lt = (Tokenizer.LocatedToken) $3;
                var sn = new SimpleMemberName (lt.Value, lt.Location);
 
-               FullNamedExpression type = (FullNamedExpression)$2;
-               
-               $$ = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, new Linq.Cast (type, (Expression)$6), GetLocation ($1));
+               $$ = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)$6, GetLocation ($1)) {
+                       IdentifierType = (FullNamedExpression)$2
+               };
                
                current_block.SetEndLocation (lexer.Location);
                current_block = current_block.Parent;
                
-               ((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn);
+               ((Linq.QueryBlock)current_block).AddRangeVariable (sn);
          }
        ;       
 
@@ -5593,12 +5599,12 @@ let_clause
          {
                var lt = (Tokenizer.LocatedToken) $2;
                var sn = new SimpleMemberName (lt.Value, lt.Location);
-               $$ = new Linq.Let ((Linq.QueryBlock) current_block, current_container, sn, (Expression)$5, GetLocation ($1));
+               $$ = new Linq.Let ((Linq.QueryBlock) current_block, sn, (Expression)$5, GetLocation ($1));
                
                current_block.SetEndLocation (lexer.Location);
                current_block = current_block.Parent;
                
-               ((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn);
+               ((Linq.QueryBlock)current_block).AddRangeVariable (sn);
          }
        ;
 
@@ -5639,8 +5645,7 @@ join_clause
                current_block.SetEndLocation (lexer.Location);
                current_block = current_block.Parent;
 
-               var lt = (Tokenizer.LocatedToken) $2;
-               current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), lexer.Location);
+               current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
          }
          expression opt_join_into
          {
@@ -5648,15 +5653,15 @@ join_clause
                var sn = new SimpleMemberName (lt.Value, lt.Location);
                SimpleMemberName sn2 = null;
                
-               ToplevelBlock outer_selector = linq_clause_blocks.Pop ();
-               ToplevelBlock block = linq_clause_blocks.Pop ();
+               var outer_selector = linq_clause_blocks.Pop ();
+               var block = linq_clause_blocks.Pop ();
 
                if ($12 == null) {
-                       $$ = new Linq.Join (block, sn, (Expression)$5, outer_selector, current_block.Toplevel, GetLocation ($1));
+                       $$ = new Linq.Join (block, sn, (Expression)$5, outer_selector, (Linq.QueryBlock) current_block, GetLocation ($1));
                } else {
                        var lt2 = (Tokenizer.LocatedToken) $12;
                        sn2 = new SimpleMemberName (lt2.Value, lt2.Location);
-                       $$ = new Linq.GroupJoin (block, sn, (Expression)$5, outer_selector, current_block.Toplevel,
+                       $$ = new Linq.GroupJoin (block, sn, (Expression)$5, outer_selector, (Linq.QueryBlock) current_block,
                                sn2, GetLocation ($1));
                }
 
@@ -5664,10 +5669,7 @@ join_clause
                current_block.SetEndLocation (lexer.Location);
                current_block = current_block.Parent;
                        
-               if (sn2 == null)
-                       ((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn);
-               else
-                       ((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn2);
+               ((Linq.QueryBlock)current_block).AddRangeVariable (sn2 ?? sn);
          }
        | JOIN type IDENTIFIER IN
          {
@@ -5691,35 +5693,33 @@ join_clause
                current_block.SetEndLocation (lexer.Location);
                current_block = current_block.Parent;
 
-               var lt = (Tokenizer.LocatedToken) $3;
-               current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), lexer.Location);
+               current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
          }
          expression opt_join_into
          {
                var lt = (Tokenizer.LocatedToken) $3;
                var sn = new SimpleMemberName (lt.Value, lt.Location);
                SimpleMemberName sn2 = null;
-               ToplevelBlock outer_selector = linq_clause_blocks.Pop ();
-               ToplevelBlock block = linq_clause_blocks.Pop ();
+               var outer_selector = linq_clause_blocks.Pop ();
+               var block = linq_clause_blocks.Pop ();
                
-               Linq.Cast cast = new Linq.Cast ((FullNamedExpression)$2, (Expression)$6);
                if ($13 == null) {
-                       $$ = new Linq.Join (block, sn, cast, outer_selector, current_block.Toplevel, GetLocation ($1));
+                       $$ = new Linq.Join (block, sn, (Expression)$6, outer_selector, (Linq.QueryBlock) current_block, GetLocation ($1)) {
+                               IdentifierType = (FullNamedExpression)$2
+                       };
                } else {
                        var lt2 = (Tokenizer.LocatedToken) $13;
                        sn2 = new SimpleMemberName (lt2.Value, lt2.Location);
-                       $$ = new Linq.GroupJoin (block, sn, cast, outer_selector, current_block.Toplevel,
-                               sn2, GetLocation ($1));
+                       $$ = new Linq.GroupJoin (block, sn, (Expression)$6, outer_selector, (Linq.QueryBlock) current_block, sn2, GetLocation ($1)) {
+                               IdentifierType = (FullNamedExpression)$2
+                       };                      
                }
                
                current_block.AddStatement (new ContextualReturn ((Expression) $12));
                current_block.SetEndLocation (lexer.Location);
                current_block = current_block.Parent;
                        
-               if (sn2 == null)
-                       ((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn);
-               else
-                       ((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn2);
+               ((Linq.QueryBlock)current_block).AddRangeVariable (sn2 ?? sn);
          }
        ;
        
@@ -5768,11 +5768,11 @@ orderings_then_by
                current_block.SetEndLocation (lexer.Location);
                current_block = current_block.Parent;
          
-               current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);   
+               current_block = new Linq.QueryBlock (compiler, (Linq.QueryBlock) current_block, lexer.Location);         
         }
         then_by
         {
-               ((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$3;
+               ((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$4;
                $$ = $1;
         }
        ;       
@@ -5780,30 +5780,30 @@ orderings_then_by
 order_by
        : expression
          {
-               $$ = new Linq.OrderByAscending (current_block.Toplevel, (Expression)$1);        
+               $$ = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)$1);       
          }
        | expression ASCENDING
          {
-               $$ = new Linq.OrderByAscending (current_block.Toplevel, (Expression)$1);        
+               $$ = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)$1);       
          }
        | expression DESCENDING
          {
-               $$ = new Linq.OrderByDescending (current_block.Toplevel, (Expression)$1);       
+               $$ = new Linq.OrderByDescending ((Linq.QueryBlock) current_block, (Expression)$1);      
          }
        ;
 
 then_by
        : expression
          {
-               $$ = new Linq.ThenByAscending (current_block.Toplevel, (Expression)$1); 
+               $$ = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)$1);        
          }
        | expression ASCENDING
          {
-               $$ = new Linq.ThenByAscending (current_block.Toplevel, (Expression)$1); 
+               $$ = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)$1);        
          }
        | expression DESCENDING
          {
-               $$ = new Linq.ThenByDescending (current_block.Toplevel, (Expression)$1);        
+               $$ = new Linq.ThenByDescending ((Linq.QueryBlock) current_block, (Expression)$1);       
          }     
        ;
 
@@ -5818,14 +5818,21 @@ opt_query_continuation
 
                current_block.SetEndLocation (GetLocation ($1));
                current_block = current_block.Parent;
-
-               var lt = (Tokenizer.LocatedToken) $2;
+       
+               current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
                
-               current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1));
+               if (linq_clause_blocks == null)
+                       linq_clause_blocks = new Stack<Linq.QueryBlock> ();
+                       
+               linq_clause_blocks.Push ((Linq.QueryBlock) current_block);              
          }
          query_body
          {
-               $$ = new Linq.QueryExpression (current_block, (Linq.AQueryClause)$4);
+               var current_block = linq_clause_blocks.Pop ();    
+               var lt = (Tokenizer.LocatedToken) $2;
+               $$ = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, null, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1)) {
+                       next = (Linq.AQueryClause)$4
+               };
          }
        ;
        
@@ -6300,7 +6307,7 @@ Report Report {
 void start_block (Location loc)
 {
        if (current_block == null || parsing_anonymous_method) {
-               current_block = new ToplevelBlock (compiler, current_block, current_local_parameters, current_generic_method, loc);
+               current_block = new ToplevelBlock (compiler, current_block, current_local_parameters, loc);
                parsing_anonymous_method = false;
        } else {
                current_block = new ExplicitBlock (current_block, loc, Location.Null);
index f0b7ef03816b2f525bf8ab73e4abbcdd6fd4981d..46df76938fd86b9220aa924b26045adc7ba291a1 100644 (file)
@@ -4813,10 +4813,7 @@ namespace Mono.CSharp {
                        if (!DoResolveBase (ec))
                                return null;
 
-                       // HACK: parameters are not captured when probing is on
-                       if (!ec.IsInProbingMode)
-                               SetAssigned (ec);
-
+                       SetAssigned (ec);
                        return this;
                }
 
index 00c6930d17f08497acee0d132163a4328227f2d6..630acb88d2d0b7f6ebe646bc683ba757b85e6ae3 100644 (file)
@@ -1981,14 +1981,21 @@ namespace Mono.CSharp {
                        for (int i = 0; i < names.Length; i++) {
                                string type_argument_name = names[i].Name;
                                int idx = parameters.GetParameterIndexByName (type_argument_name);
+
                                if (idx >= 0) {
-                                       Block b = m.Block;
+                                       var b = m.Block;
                                        if (b == null)
-                                               b = new Block (null);
+                                               b = new ToplevelBlock (Compiler, Location);
 
-                                       b.Error_AlreadyDeclaredTypeParameter (Report, parameters [i].Location,
+                                       b.Error_AlreadyDeclaredTypeParameter (parameters [i].Location,
                                                type_argument_name, "method parameter");
                                }
+
+                               if (m.Block != null) {
+                                       var ikv = m.Block.GetKnownVariable (type_argument_name);
+                                       if (ikv != null)
+                                               ikv.Block.Error_AlreadyDeclaredTypeParameter (ikv.Location, type_argument_name, "local variable");
+                               }
                                
                                snames[i] = type_argument_name;
                        }
index 659baa38803a7b1f59a549acca5d712743219e72..658f2ee9d0bf3d4ce05f1829746f0d820eb355e5 100644 (file)
@@ -14,30 +14,24 @@ using System.Collections.Generic;
 
 namespace Mono.CSharp.Linq
 {
-       // NOTES:
-       // Expression should be IExpression to save some memory and make a few things
-       // easier to read
-       //
-       //
-
        public class QueryExpression : AQueryClause
        {
-               public QueryExpression (Block block, AQueryClause query)
-                       : base (null, null, query.Location)
+               public QueryExpression (AQueryClause start)
+                       : base (null, null, Location.Null)
                {
-                       this.next = query;
+                       this.next = start;
                }
 
-               public override Expression BuildQueryClause (ResolveContext ec, Expression lSide)
+               public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parentParameter)
                {
-                       return next.BuildQueryClause (ec, lSide);
+                       return next.BuildQueryClause (ec, lSide, parentParameter);
                }
 
                protected override Expression DoResolve (ResolveContext ec)
                {
                        int counter = QueryBlock.TransparentParameter.Counter;
 
-                       Expression e = BuildQueryClause (ec, null);
+                       Expression e = BuildQueryClause (ec, null, null);
                        if (e != null)
                                e = e.Resolve (ec);
 
@@ -58,7 +52,7 @@ namespace Mono.CSharp.Linq
 
        public abstract class AQueryClause : ShimExpression
        {
-               class QueryExpressionAccess : MemberAccess
+               protected class QueryExpressionAccess : MemberAccess
                {
                        public QueryExpressionAccess (Expression expr, string methodName, Location loc)
                                : base (expr, methodName, loc)
@@ -80,7 +74,7 @@ namespace Mono.CSharp.Linq
                        }
                }
 
-               class QueryExpressionInvocation : Invocation, MethodGroupExpr.IErrorHandler
+               protected class QueryExpressionInvocation : Invocation, MethodGroupExpr.IErrorHandler
                {
                        public QueryExpressionInvocation (QueryExpressionAccess expr, Arguments arguments)
                                : base (expr, arguments)
@@ -142,11 +136,10 @@ namespace Mono.CSharp.Linq
                        }
                }
 
-               // TODO: protected
                public AQueryClause next;
-               protected ToplevelBlock block;
+               public QueryBlock block;
 
-               protected AQueryClause (ToplevelBlock block, Expression expr, Location loc)
+               protected AQueryClause (QueryBlock block, Expression expr, Location loc)
                         : base (expr)
                {
                        this.block = block;
@@ -160,7 +153,7 @@ namespace Mono.CSharp.Linq
                        AQueryClause t = (AQueryClause) target;
 
                        if (block != null)
-                               t.block = (ToplevelBlock) block.Clone (clonectx);
+                               t.block = (QueryBlock) clonectx.LookupBlock (block);
 
                        if (next != null)
                                t.next = (AQueryClause) next.Clone (clonectx);
@@ -171,29 +164,38 @@ namespace Mono.CSharp.Linq
                        return expr.Resolve (ec);
                }
 
-               public virtual Expression BuildQueryClause (ResolveContext ec, Expression lSide)
+               public virtual Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter)
                {
-                       Arguments args;
-                       CreateArguments (ec, out args);
+                       Arguments args = null;
+                       CreateArguments (ec, parameter, ref args);
                        lSide = CreateQueryExpression (lSide, args);
                        if (next != null) {
+                               parameter = CreateChildrenParameters (parameter);
+
                                Select s = next as Select;
-                               if (s == null || s.IsRequired)
-                                       return next.BuildQueryClause (ec, lSide);
+                               if (s == null || s.IsRequired (parameter))
+                                       return next.BuildQueryClause (ec, lSide, parameter);
                                        
                                // Skip transparent select clause if any clause follows
                                if (next.next != null)
-                                       return next.next.BuildQueryClause (ec, lSide);
+                                       return next.next.BuildQueryClause (ec, lSide, parameter);
                        }
 
                        return lSide;
                }
 
-               protected virtual void CreateArguments (ResolveContext ec, out Arguments args)
+               protected virtual Parameter CreateChildrenParameters (Parameter parameter)
+               {
+                       return parameter;
+               }
+
+               protected virtual void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
                {
                        args = new Arguments (2);
 
                        LambdaExpression selector = new LambdaExpression (loc);
+
+                       block.SetParameter (parameter.Clone ());
                        selector.Block = block;
                        selector.Block.AddStatement (new ContextualReturn (expr));
 
@@ -206,15 +208,9 @@ namespace Mono.CSharp.Linq
                                new QueryExpressionAccess (lSide, MethodName, loc), arguments);
                }
 
-               protected Invocation CreateQueryExpression (Expression lSide, TypeArguments typeArguments, Arguments arguments)
-               {
-                       return new QueryExpressionInvocation (
-                               new QueryExpressionAccess (lSide, MethodName, typeArguments, loc), arguments);
-               }
-
                protected abstract string MethodName { get; }
 
-               public virtual AQueryClause Next {
+               public AQueryClause Next {
                        set {
                                next = value;
                        }
@@ -246,29 +242,52 @@ namespace Mono.CSharp.Linq
                        }
                }
 
-               protected ARangeVariableQueryClause (ToplevelBlock block, Expression expr, Location loc)
+               protected SimpleMemberName range_variable;
+
+               protected ARangeVariableQueryClause (QueryBlock block, SimpleMemberName identifier, Expression expr, Location loc)
                        : base (block, expr, loc)
                {
+                       range_variable = identifier;
                }
 
-               protected static Expression CreateRangeVariableType (ToplevelBlock block, TypeContainer container, SimpleMemberName name, Expression init)
+               public FullNamedExpression IdentifierType { get; set; }
+
+               protected Invocation CreateCastExpression (Expression lSide)
+               {
+                       return new QueryExpressionInvocation (
+                               new QueryExpressionAccess (lSide, "Cast", new TypeArguments (IdentifierType), loc), null);
+               }
+
+               protected override Parameter CreateChildrenParameters (Parameter parameter)
+               {
+                       return new QueryBlock.TransparentParameter (parameter, GetIntoVariable ());
+               }
+
+               protected static Expression CreateRangeVariableType (ResolveContext rc, Parameter parameter, SimpleMemberName name, Expression init)
                {
                        var args = new List<AnonymousTypeParameter> (2);
-                       args.Add (new AnonymousTypeParameter (block.Parameters [0]));
+                       args.Add (new AnonymousTypeParameter (parameter));
                        args.Add (new RangeAnonymousTypeParameter (init, name));
-                       return new NewAnonymousType (args, container, name.Location);
+                       return new NewAnonymousType (args, rc.MemberContext.CurrentMemberDefinition.Parent, name.Location);
+               }
+
+               protected virtual SimpleMemberName GetIntoVariable ()
+               {
+                       return range_variable;
                }
        }
 
-       class QueryStartClause : AQueryClause
+       class QueryStartClause : ARangeVariableQueryClause
        {
-               public QueryStartClause (Expression expr)
-                       : base (null, expr, expr.Location)
+               public QueryStartClause (QueryBlock block, Expression expr, SimpleMemberName identifier, Location loc)
+                       : base (block, identifier, expr, loc)
                {
+                       block.AddRangeVariable (identifier);
                }
 
-               public override Expression BuildQueryClause (ResolveContext ec, Expression lSide)
+               public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter)
                {
+/*
                        expr = expr.Resolve (ec);
                        if (expr == null)
                                return null;
@@ -279,13 +298,20 @@ namespace Mono.CSharp.Linq
                                        TypeManager.CSharpName (expr.Type));
                                return null;
                        }
+*/
 
-                       return next.BuildQueryClause (ec, expr);
+                       if (IdentifierType != null)
+                               expr = CreateCastExpression (expr);
+
+                       if (parameter == null)
+                               lSide = expr;
+
+                       return next.BuildQueryClause (ec, lSide, new ImplicitLambdaParameter (range_variable.Value, range_variable.Location));
                }
 
                protected override Expression DoResolve (ResolveContext ec)
                {
-                       Expression e = BuildQueryClause (ec, null);
+                       Expression e = BuildQueryClause (ec, null, null);
                        return e.Resolve (ec);
                }
 
@@ -294,37 +320,12 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       class Cast : QueryStartClause
-       {
-               // We don't have to clone cast type
-               readonly FullNamedExpression type_expr;
-
-               public Cast (FullNamedExpression type, Expression expr)
-                       : base (expr)
-               {
-                       this.type_expr = type;
-               }
-               
-               public override Expression BuildQueryClause (ResolveContext ec, Expression lSide)
-               {
-                       lSide = CreateQueryExpression (expr, new TypeArguments (type_expr), null);
-                       if (next != null)
-                               return next.BuildQueryClause (ec, lSide);
-
-                       return lSide;
-               }
-
-               protected override string MethodName {
-                       get { return "Cast"; }
-               }
-       }
-
        public class GroupBy : AQueryClause
        {
                Expression element_selector;
-               ToplevelBlock element_block;
-               
-               public GroupBy (ToplevelBlock block, Expression elementSelector, ToplevelBlock elementBlock, Expression keySelector, Location loc)
+               QueryBlock element_block;
+
+               public GroupBy (QueryBlock block, Expression elementSelector, QueryBlock elementBlock, Expression keySelector, Location loc)
                        : base (block, keySelector, loc)
                {
                        //
@@ -336,12 +337,14 @@ namespace Mono.CSharp.Linq
                        }
                }
 
-               protected override void CreateArguments (ResolveContext ec, out Arguments args)
+               protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
                {
-                       base.CreateArguments (ec, out args);
+                       base.CreateArguments (ec, parameter, ref args);
 
                        if (element_selector != null) {
                                LambdaExpression lambda = new LambdaExpression (element_selector.Location);
+
+                               element_block.SetParameter (parameter.Clone ());
                                lambda.Block = element_block;
                                lambda.Block.AddStatement (new ContextualReturn (element_selector));
                                args.Add (new Argument (lambda));
@@ -353,7 +356,7 @@ namespace Mono.CSharp.Linq
                        GroupBy t = (GroupBy) target;
                        if (element_selector != null) {
                                t.element_selector = element_selector.Clone (clonectx);
-                               t.element_block = (ToplevelBlock) element_block.Clone (clonectx);
+                               t.element_block = (QueryBlock) element_block.Clone (clonectx);
                        }
 
                        base.CloneTo (clonectx, t);
@@ -364,63 +367,44 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public class Join : ARangeVariableQueryClause
+       public class Join : SelectMany
        {
-               readonly SimpleMemberName lt;
-               ToplevelBlock inner_selector, outer_selector;
+               QueryBlock inner_selector, outer_selector;
 
-               public Join (ToplevelBlock block, SimpleMemberName lt, Expression inner, ToplevelBlock outerSelector, ToplevelBlock innerSelector, Location loc)
-                       : base (block, inner, loc)
+               public Join (QueryBlock block, SimpleMemberName lt, Expression inner, QueryBlock outerSelector, QueryBlock innerSelector, Location loc)
+                       : base (block, lt, inner, loc)
                {
-                       this.lt = lt;
                        this.outer_selector = outerSelector;
                        this.inner_selector = innerSelector;
                }
 
-               protected override void CreateArguments (ResolveContext ec, out Arguments args)
+               protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
                {
                        args = new Arguments (4);
 
+                       if (IdentifierType != null)
+                               expr = CreateCastExpression (expr);
+
                        args.Add (new Argument (expr));
 
-                       LambdaExpression lambda = new LambdaExpression (outer_selector.StartLocation);
+                       outer_selector.SetParameter (parameter.Clone ());
+                       var lambda = new LambdaExpression (outer_selector.StartLocation);
                        lambda.Block = outer_selector;
                        args.Add (new Argument (lambda));
 
+                       inner_selector.SetParameter (new ImplicitLambdaParameter (range_variable.Value, range_variable.Location));
                        lambda = new LambdaExpression (inner_selector.StartLocation);
                        lambda.Block = inner_selector;
                        args.Add (new Argument (lambda));
 
-                       Expression result_selector_expr;
-                       SimpleMemberName into_variable = GetIntoVariable ();
-                       //
-                       // When select follows use is as result selector
-                       //
-                       if (next is Select) {
-                               result_selector_expr = next.Expr;
-                               next = next.next;
-                       } else {
-                               result_selector_expr = CreateRangeVariableType (block, ec.MemberContext.CurrentMemberDefinition.Parent, into_variable,
-                                       new SimpleName (into_variable.Value, into_variable.Location));
-                       }
-
-                       LambdaExpression result_selector = new LambdaExpression (lt.Location);
-                       result_selector.Block = new QueryBlock (ec.Compiler, block.Parent, block.Parameters, into_variable, block.StartLocation);
-                       result_selector.Block.AddStatement (new ContextualReturn (result_selector_expr));
-
-                       args.Add (new Argument (result_selector));
-               }
-
-               protected virtual SimpleMemberName GetIntoVariable ()
-               {
-                       return lt;
+                       base.CreateArguments (ec, parameter, ref args);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression target)
                {
                        Join t = (Join) target;
-                       t.inner_selector = (ToplevelBlock) inner_selector.Clone (clonectx);
-                       t.outer_selector = (ToplevelBlock) outer_selector.Clone (clonectx);
+                       t.inner_selector = (QueryBlock) inner_selector.Clone (clonectx);
+                       t.outer_selector = (QueryBlock) outer_selector.Clone (clonectx);
                        base.CloneTo (clonectx, t);
                }       
 
@@ -433,8 +417,8 @@ namespace Mono.CSharp.Linq
        {
                readonly SimpleMemberName into;
 
-               public GroupJoin (ToplevelBlock block, SimpleMemberName lt, Expression inner,
-                       ToplevelBlock outerSelector, ToplevelBlock innerSelector, SimpleMemberName into, Location loc)
+               public GroupJoin (QueryBlock block, SimpleMemberName lt, Expression inner,
+                       QueryBlock outerSelector, QueryBlock innerSelector, SimpleMemberName into, Location loc)
                        : base (block, lt, inner, outerSelector, innerSelector, loc)
                {
                        this.into = into;
@@ -452,11 +436,17 @@ namespace Mono.CSharp.Linq
 
        public class Let : ARangeVariableQueryClause
        {
-               public Let (ToplevelBlock block, TypeContainer container, SimpleMemberName identifier, Expression expr, Location loc)
-                       : base (block, CreateRangeVariableType (block, container, identifier, expr), loc)
+               public Let (QueryBlock block, SimpleMemberName identifier, Expression expr, Location loc)
+                       : base (block, identifier, expr, loc)
                {
                }
 
+               protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
+               {
+                       expr = CreateRangeVariableType (ec, parameter, range_variable, expr);
+                       base.CreateArguments (ec, parameter, ref args);
+               }
+
                protected override string MethodName {
                        get { return "Select"; }
                }
@@ -464,7 +454,7 @@ namespace Mono.CSharp.Linq
 
        public class Select : AQueryClause
        {
-               public Select (ToplevelBlock block, Expression expr, Location loc)
+               public Select (QueryBlock block, Expression expr, Location loc)
                        : base (block, expr, loc)
                {
                }
@@ -473,14 +463,13 @@ namespace Mono.CSharp.Linq
                // For queries like `from a orderby a select a'
                // the projection is transparent and select clause can be safely removed 
                //
-               public bool IsRequired {
-                       get {
-                               SimpleName sn = expr as SimpleName;
-                               if (sn == null)
-                                       return true;
+               public bool IsRequired (Parameter parameter)
+               {
+                       SimpleName sn = expr as SimpleName;
+                       if (sn == null)
+                               return true;
 
-                               return sn.Name != block.Parameters.FixedParameters [0].Name;
-                       }
+                       return sn.Name != parameter.Name;
                }
 
                protected override string MethodName {
@@ -490,31 +479,45 @@ namespace Mono.CSharp.Linq
 
        public class SelectMany : ARangeVariableQueryClause
        {
-               SimpleMemberName lt;
-
-               public SelectMany (ToplevelBlock block, SimpleMemberName lt, Expression expr, Location loc)
-                       : base (block, expr, loc)
+               public SelectMany (QueryBlock block, SimpleMemberName identifier, Expression expr, Location loc)
+                       : base (block, identifier, expr, loc)
                {
-                       this.lt = lt;
                }
 
-               protected override void CreateArguments (ResolveContext ec, out Arguments args)
+               protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
                {
-                       base.CreateArguments (ec, out args);
+                       if (args == null) {
+                               if (IdentifierType != null)
+                                       expr = CreateCastExpression (expr);
+
+                               base.CreateArguments (ec, parameter, ref args);
+                       }
 
                        Expression result_selector_expr;
+                       QueryBlock result_block;
+
+                       var target = GetIntoVariable ();
+                       var target_param = new ImplicitLambdaParameter (target.Value, target.Location);
+
                        //
-                       // When select follow use is as result selector
+                       // When select follows use it as a result selector
                        //
                        if (next is Select) {
                                result_selector_expr = next.Expr;
+
+                               result_block = next.block;
+                               result_block.SetParameters (parameter, target_param);
+
                                next = next.next;
                        } else {
-                               result_selector_expr = CreateRangeVariableType (block, ec.MemberContext.CurrentMemberDefinition.Parent, lt, new SimpleName (lt.Value, lt.Location));
+                               result_selector_expr = CreateRangeVariableType (ec, parameter, target, new SimpleName (target.Value, target.Location));
+
+                               result_block = new QueryBlock (ec.Compiler, block.Parent, block.StartLocation);
+                               result_block.SetParameters (parameter, target_param);
                        }
 
-                       LambdaExpression result_selector = new LambdaExpression (lt.Location);
-                       result_selector.Block = new QueryBlock (ec.Compiler, block.Parent, block.Parameters, lt, block.StartLocation);
+                       LambdaExpression result_selector = new LambdaExpression (Location);
+                       result_selector.Block = result_block;
                        result_selector.Block.AddStatement (new ContextualReturn (result_selector_expr));
 
                        args.Add (new Argument (result_selector));
@@ -527,7 +530,7 @@ namespace Mono.CSharp.Linq
 
        public class Where : AQueryClause
        {
-               public Where (ToplevelBlock block, BooleanExpression expr, Location loc)
+               public Where (QueryBlock block, BooleanExpression expr, Location loc)
                        : base (block, expr, loc)
                {
                }
@@ -535,11 +538,16 @@ namespace Mono.CSharp.Linq
                protected override string MethodName {
                        get { return "Where"; }
                }
+
+               protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
+               {
+                       base.CreateArguments (ec, parameter, ref args);
+               }
        }
 
        public class OrderByAscending : AQueryClause
        {
-               public OrderByAscending (ToplevelBlock block,Expression expr)
+               public OrderByAscending (QueryBlock block, Expression expr)
                        : base (block, expr, expr.Location)
                {
                }
@@ -551,7 +559,7 @@ namespace Mono.CSharp.Linq
 
        public class OrderByDescending : AQueryClause
        {
-               public OrderByDescending (ToplevelBlock block, Expression expr)
+               public OrderByDescending (QueryBlock block, Expression expr)
                        : base (block, expr, expr.Location)
                {
                }
@@ -563,7 +571,7 @@ namespace Mono.CSharp.Linq
 
        public class ThenByAscending : OrderByAscending
        {
-               public ThenByAscending (ToplevelBlock block, Expression expr)
+               public ThenByAscending (QueryBlock block, Expression expr)
                        : base (block, expr)
                {
                }
@@ -575,7 +583,7 @@ namespace Mono.CSharp.Linq
 
        public class ThenByDescending : OrderByDescending
        {
-               public ThenByDescending (ToplevelBlock block, Expression expr)
+               public ThenByDescending (QueryBlock block, Expression expr)
                        : base (block, expr)
                {
                }
@@ -588,7 +596,7 @@ namespace Mono.CSharp.Linq
        //
        // Implicit query block
        //
-       class QueryBlock : ToplevelBlock
+       public class QueryBlock : ToplevelBlock
        {
                //
                // Transparent parameters are used to package up the intermediate results
@@ -599,10 +607,10 @@ namespace Mono.CSharp.Linq
                        public static int Counter;
                        const string ParameterNamePrefix = "<>__TranspIdent";
 
-                       public readonly ParametersCompiled Parent;
+                       public readonly Parameter Parent;
                        public readonly string Identifier;
 
-                       public TransparentParameter (ParametersCompiled parent, SimpleMemberName identifier)
+                       public TransparentParameter (Parameter parent, SimpleMemberName identifier)
                                : base (ParameterNamePrefix + Counter++, identifier.Location)
                        {
                                Parent = parent;
@@ -615,41 +623,36 @@ namespace Mono.CSharp.Linq
                        }
                }
 
-               public sealed class ImplicitQueryParameter : ImplicitLambdaParameter
+               sealed class RangeVariable : IKnownVariable
                {
-                       public ImplicitQueryParameter (string name, Location loc)
-                               : base (name, loc)
+                       public RangeVariable (QueryBlock block, Location loc)
                        {
+                               Block = block;
+                               Location = loc;
                        }
-               }
 
-               public QueryBlock (CompilerContext ctx, Block parent, SimpleMemberName lt, Location start)
-                       : base (ctx, parent, new ParametersCompiled (ctx, new ImplicitQueryParameter (lt.Value, lt.Location)), start)
-               {
-                       if (parent != null)
-                               base.CheckParentConflictName (parent.Toplevel, lt.Value, lt.Location);
-               }
+                       public Block Block { get; private set; }
 
-               public QueryBlock (CompilerContext ctx, Block parent, ParametersCompiled parameters, SimpleMemberName lt, Location start)
-                       : base (ctx, parent, new ParametersCompiled (ctx, parameters [0].Clone (), new ImplicitQueryParameter (lt.Value, lt.Location)), start)
-               {
+                       public Location Location { get; private set; }
                }
 
+               List<SimpleMemberName> range_variables;
+
                public QueryBlock (CompilerContext ctx, Block parent, Location start)
-                       : base (ctx, parent, parent.Toplevel.Parameters.Clone (), start)
+                       : base (ctx, parent, ParametersCompiled.EmptyReadOnlyParameters, start)
                {
                }
 
-               public void AddTransparentParameter (CompilerContext ctx, SimpleMemberName name)
+               public void AddRangeVariable (SimpleMemberName name)
                {
-                       base.CheckParentConflictName (this, name.Value, name.Location);
+                       if (!CheckParentConflictName (this, name.Value, name.Location))
+                               return;
 
-                       parameters = new ParametersCompiled (ctx, new TransparentParameter (parameters, name));
-               }
+                       if (range_variables == null)
+                               range_variables = new List<SimpleMemberName> ();
 
-               protected override bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
-               {
-                       return true;
+                       range_variables.Add (name);
+                       AddKnownVariable (name.Value, new RangeVariable (this, name.Location));
                }
 
                // 
@@ -666,11 +669,9 @@ namespace Mono.CSharp.Linq
                                if (tp.Identifier == name)
                                        break;
 
-                               TransparentParameter tp_next = tp.Parent [0] as TransparentParameter;
-                               if (tp_next == null) {
-                                       if (tp.Parent.GetParameterIndexByName (name) >= 0)
-                                               break;
-                               }
+                               TransparentParameter tp_next = tp.Parent as TransparentParameter;
+                               if (tp_next == null && tp.Parent.Name == name)
+                                       break;
 
                                tp = tp_next;
                        }
@@ -679,7 +680,7 @@ namespace Mono.CSharp.Linq
                                expr = new SimpleName (parameters[0].Name, loc);
                                TransparentParameter tp_cursor = (TransparentParameter) parameters[0];
                                while (tp_cursor != tp) {
-                                       tp_cursor = (TransparentParameter) tp_cursor.Parent[0];
+                                       tp_cursor = (TransparentParameter) tp_cursor.Parent;
                                        expr = new MemberAccess (expr, tp_cursor.Name);
                                }
 
@@ -689,6 +690,11 @@ namespace Mono.CSharp.Linq
                        return null;
                }
 
+               protected override bool HasParameterWithName (string name)
+               {
+                       return range_variables != null && range_variables.Exists (l => l.Value == name);
+               }
+
                protected override void Error_AlreadyDeclared (Location loc, string var, string reason)
                {
                        Report.Error (1931, loc, "A range variable `{0}' conflicts with a previous declaration of `{0}'",
@@ -701,10 +707,27 @@ namespace Mono.CSharp.Linq
                                var);           
                }
                
-               public override void Error_AlreadyDeclaredTypeParameter (Report r, Location loc, string name, string conflict)
+               public override void Error_AlreadyDeclaredTypeParameter (Location loc, string name, string conflict)
                {
-                       r.Error (1948, loc, "A range variable `{0}' conflicts with a method type parameter",
+                       Report.Error (1948, loc, "A range variable `{0}' conflicts with a method type parameter",
                                name);
                }
+
+               public void SetParameter (Parameter parameter)
+               {
+                       base.parameters = new ParametersCompiled (null, parameter);
+                       base.parameter_info = new ToplevelParameterInfo [] {
+                               new ToplevelParameterInfo (this, 0)
+                       };
+               }
+
+               public void SetParameters (Parameter first, Parameter second)
+               {
+                       base.parameters = new ParametersCompiled (null, first, second);
+                       base.parameter_info = new ToplevelParameterInfo[] {
+                               new ToplevelParameterInfo (this, 0),
+                               new ToplevelParameterInfo (this, 1)
+                       };
+               }
        }
 }
index 3c0159937e436b094e1ba59c6e68dafa65d2d71d..e7f223b60f1af7a8567b4e565d7bf8325f1363b7 100644 (file)
@@ -1640,7 +1640,7 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               protected virtual bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
+               protected bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
                {
                        LocalInfo vi = GetLocalInfo (name);
                        if (vi != null) {
@@ -1655,13 +1655,13 @@ namespace Mono.CSharp {
                        }
 
                        if (block != null) {
-                               Expression e = block.GetParameterReference (name, Location.Null);
-                               if (e != null) {
-                                       ParameterReference pr = e as ParameterReference;
-                                       if (this is Linq.QueryBlock && (pr != null && pr.Parameter is Linq.QueryBlock.ImplicitQueryParameter || e is MemberAccess))
+                               var tblock = block.CheckParameterNameConflict (name);
+                               if (tblock != null) {
+                                       if (block == tblock && block is Linq.QueryBlock)
                                                Error_AlreadyDeclared (loc, name);
                                        else
                                                Error_AlreadyDeclared (loc, name, "parent or current");
+
                                        return false;
                                }
                        }
@@ -1674,16 +1674,6 @@ namespace Mono.CSharp {
                        if (!CheckParentConflictName (Toplevel, name, l))
                                return null;
 
-                       if (Toplevel.GenericMethod != null) {
-                               foreach (TypeParameter tp in Toplevel.GenericMethod.CurrentTypeParameters) {
-                                       if (tp.Name == name) {
-                                               Toplevel.Report.SymbolRelatedToPreviousError (tp);
-                                               Error_AlreadyDeclaredTypeParameter (Toplevel.Report, loc, name, "local variable");
-                                               return null;
-                                       }
-                               }
-                       }                       
-
                        IKnownVariable kvi = Explicit.GetKnownVariable (name);
                        if (kvi != null) {
                                Toplevel.Report.SymbolRelatedToPreviousError (kvi.Location, name);
@@ -1725,9 +1715,9 @@ namespace Mono.CSharp {
                                "A local variable named `{0}' is already defined in this scope", name);
                }
                                        
-               public virtual void Error_AlreadyDeclaredTypeParameter (Report r, Location loc, string name, string conflict)
+               public virtual void Error_AlreadyDeclaredTypeParameter (Location loc, string name, string conflict)
                {
-                       r.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
+                       Toplevel.Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
                                name, conflict);
                }
 
@@ -1768,9 +1758,8 @@ namespace Mono.CSharp {
                {
                        LocalInfo ret;
                        for (Block b = this; b != null; b = b.Parent) {
-                               if (b.variables != null) {
-                                       if (b.variables.TryGetValue (name, out ret))
-                                               return ret;
+                               if (b.variables != null && b.variables.TryGetValue (name, out ret)) {
+                                       return ret;
                                }
                        }
 
@@ -2188,7 +2177,7 @@ namespace Mono.CSharp {
 
                public override string ToString ()
                {
-                       return String.Format ("{0} ({1}:{2})", GetType (),ID, StartLocation);
+                       return String.Format ("{0} ({1}:{2})", GetType (), this_id, StartLocation);
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -2197,7 +2186,7 @@ namespace Mono.CSharp {
 
                        clonectx.AddBlockMap (this, target);
 
-                       //target.Toplevel = (ToplevelBlock) clonectx.LookupBlock (Toplevel);
+                       target.Toplevel = (ToplevelBlock) clonectx.LookupBlock (Toplevel);
                        target.Explicit = (ExplicitBlock) clonectx.LookupBlock (Explicit);
                        if (Parent != null)
                                target.Parent = clonectx.RemapBlockCopy (Parent);
@@ -2370,15 +2359,13 @@ namespace Mono.CSharp {
                        base.EmitMeta (ec);
                }
 
-               internal IKnownVariable GetKnownVariable (string name)
+               public IKnownVariable GetKnownVariable (string name)
                {
                        if (known_variables == null)
                                return null;
 
                        IKnownVariable kw;
-                       if (!known_variables.TryGetValue (name, out kw))
-                               return null;
-
+                       known_variables.TryGetValue (name, out kw);
                        return kw;
                }
 
@@ -2480,9 +2467,8 @@ namespace Mono.CSharp {
                        }
                }
 
-               GenericMethod generic;
                protected ParametersCompiled parameters;
-               ToplevelParameterInfo[] parameter_info;
+               protected ToplevelParameterInfo[] parameter_info;
                LocalInfo this_variable;
                bool resolved;
                bool unreachable;
@@ -2507,10 +2493,6 @@ namespace Mono.CSharp {
                        get { return compiler.Report; }
                }
 
-               public GenericMethod GenericMethod {
-                       get { return generic; }
-               }
-
                public ToplevelBlock Container {
                        get { return Parent == null ? null : Parent.Toplevel; }
                }
@@ -2520,12 +2502,6 @@ namespace Mono.CSharp {
                {
                }
 
-               public ToplevelBlock (CompilerContext ctx, Block parent, ParametersCompiled parameters, GenericMethod generic, Location start) :
-                       this (ctx, parent, parameters, start)
-               {
-                       this.generic = generic;
-               }
-
                public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start) :
                        this (ctx, null, (Flags) 0, parameters, start)
                {
@@ -2563,10 +2539,11 @@ namespace Mono.CSharp {
                        ToplevelBlock target = (ToplevelBlock) t;
                        base.CloneTo (clonectx, t);
 
-                       if (parameters.Count != 0)
-                               target.parameter_info = new ToplevelParameterInfo [parameters.Count];
-                       for (int i = 0; i < parameters.Count; ++i)
-                               target.parameter_info [i] = new ToplevelParameterInfo (target, i);
+                       if (parameters.Count != 0) {
+                               target.parameter_info = new ToplevelParameterInfo[parameters.Count];
+                               for (int i = 0; i < parameters.Count; ++i)
+                                       target.parameter_info[i] = new ToplevelParameterInfo (target, i);
+                       }
                }
 
                public bool CheckError158 (string name, Location loc)
@@ -2659,6 +2636,9 @@ namespace Mono.CSharp {
                public Expression GetParameterReference (string name, Location loc)
                {
                        for (ToplevelBlock t = this; t != null; t = t.Container) {
+                               if (t.parameters.IsEmpty)
+                                       continue;
+
                                Expression expr = t.GetParameterReferenceExpression (name, loc);
                                if (expr != null)
                                        return expr;
@@ -2674,6 +2654,21 @@ namespace Mono.CSharp {
                                null : new ParameterReference (parameter_info [idx], loc);
                }
 
+               public ToplevelBlock CheckParameterNameConflict (string name)
+               {
+                       for (ToplevelBlock t = this; t != null; t = t.Container) {
+                               if (t.HasParameterWithName (name))
+                                       return t;
+                       }
+
+                       return null;
+               }
+
+               protected virtual bool HasParameterWithName (string name)
+               {
+                       return parameters.GetParameterIndexByName (name) >= 0;
+               }
+
                // <summary>
                //   Returns the "this" instance variable of this block.
                //   See AddThisVariable() for more information.