2008-12-28 Marek Safar <marek.safar@gmail.com>
authorMarek Safar <marek.safar@gmail.com>
Sun, 28 Dec 2008 14:43:49 +0000 (14:43 -0000)
committerMarek Safar <marek.safar@gmail.com>
Sun, 28 Dec 2008 14:43:49 +0000 (14:43 -0000)
A fix for bugs #460847, #460772, #458049, #457339, #447807
* generic.cs, parameter.cs, lambda.cs, linq.cs, anonymous.cs
statement.cs, ecore.cs, class.cs, delegate.cs, flowanalysis.cs
cs-parser.jay, driver.cs: LINQ implementation upgrade to deal with
user lambdas used inside query clauses.

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

13 files changed:
mcs/mcs/ChangeLog
mcs/mcs/anonymous.cs
mcs/mcs/class.cs
mcs/mcs/cs-parser.jay
mcs/mcs/delegate.cs
mcs/mcs/driver.cs
mcs/mcs/ecore.cs
mcs/mcs/flowanalysis.cs
mcs/mcs/generic.cs
mcs/mcs/lambda.cs
mcs/mcs/linq.cs
mcs/mcs/parameter.cs
mcs/mcs/statement.cs

index 2ad6cbaa2931e303d2247c99a341db9c44d89bed..81b6546f455b49c82c47a81a683ede8328f59ea6 100644 (file)
@@ -1,3 +1,11 @@
+2008-12-28  Marek Safar  <marek.safar@gmail.com>
+
+       A fix for bugs #460847, #460772, #458049, #457339, #447807
+       * generic.cs, parameter.cs, lambda.cs, linq.cs, anonymous.cs
+       statement.cs, ecore.cs, class.cs, delegate.cs, flowanalysis.cs
+       cs-parser.jay, driver.cs: LINQ implementation upgrade to deal with
+       user lambdas used inside query clauses.
+
 2008-12-18  Marek Safar  <marek.safar@gmail.com>
 
        A fix for bug #460229
index d4ca17df1558d03588ff2ed7067a5bcff0e7b74f..72fc1c4c9154c71f479857aaabbaeddeb33e0315 100644 (file)
@@ -1089,7 +1089,7 @@ namespace Mono.CSharp {
                                        am = CreateExpressionTree (ec, delegate_type);
 
                                if (!ec.IsInProbingMode)
-                                       compatibles.Add (type, am);
+                                       compatibles.Add (type, am == null ? EmptyExpression.Null : am);
 
                                return am;
                        } catch (Exception e) {
@@ -1667,6 +1667,20 @@ namespace Mono.CSharp {
        //
        public class AnonymousTypeClass : CompilerGeneratedClass
        {
+               sealed class AnonymousParameters : Parameters
+               {
+                       public AnonymousParameters (params Parameter[] parameters)
+                               : base (parameters)
+                       {
+                       }
+
+                       protected override void ErrorDuplicateName (Parameter p)
+                       {
+                               Report.Error (833, p.Location, "`{0}': An anonymous type cannot have multiple properties with the same name",
+                                       p.Name);
+                       }
+               }
+
                static int types_counter;
                public const string ClassNamePrefix = "<>__AnonType";
                public const string SignatureForError = "anonymous type";
@@ -1708,7 +1722,7 @@ namespace Mono.CSharp {
                                a_type.SetParameterInfo (null);
 
                        Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN,
-                               null, new Parameters (ctor_params), null, loc);
+                               null, new AnonymousParameters (ctor_params), null, loc);
                        c.Block = new ToplevelBlock (c.Parameters, loc);
 
                        // 
@@ -1723,8 +1737,6 @@ namespace Mono.CSharp {
 
                                if (!a_type.AddField (f)) {
                                        error = true;
-                                       Report.Error (833, p.Location, "`{0}': An anonymous type cannot have multiple properties with the same name",
-                                               p.Name);
                                        continue;
                                }
 
index 670f956068e099c1f96fbc789966009c15fbc02e..29f30db2151226d20ec9a91eb0faf30c2489d18a 100644 (file)
@@ -1921,7 +1921,7 @@ namespace Mono.CSharp {
                                                if (cb != null && filter (cb, criteria) == true) {
                                                        if (members == null)
                                                                members = new ArrayList ();
-                                                       
+
                                                        members.Add (cb);
                                                }
                                        }
@@ -3384,6 +3384,7 @@ namespace Mono.CSharp {
 
                        if ((ModFlags & Modifiers.OVERRIDE) != 0){
                                if (!(base_method.IsAbstract || base_method.IsVirtual)){
+                                       Report.SymbolRelatedToPreviousError (base_method);
                                        Report.Error (506, Location,
                                                "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
                                                 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
@@ -3742,7 +3743,7 @@ namespace Mono.CSharp {
 #if GMCS_SOURCE
                        if (GenericMethod != null) {
                                MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
-                               if (!GenericMethod.Define (MethodBuilder))
+                               if (!GenericMethod.Define (this))
                                        return false;
                        }
 #endif
index c67858d2e88ba1d1d87c9ce9e07f5722eaf6028a..9b1ff66ed8c92b372f8066f98082a24ec185dfb0 100644 (file)
@@ -131,6 +131,9 @@ namespace Mono.CSharp
                // Keeps track of global data changes to undo on parser error
                //
                public Undo undo;
+               
+               // Stack<ToplevelBlock>
+               Stack linq_clause_blocks;
 
                // A counter to create new class names in interactive mode
                static int class_count;
@@ -897,6 +900,7 @@ class_member_declaration
                Report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration",
                        GetSymbolName (yyToken));
                $$ = null;
+               lexer.parsing_generic_declaration = false;
          }
        ;
 
@@ -5202,40 +5206,46 @@ query_expression
 first_from_clause
        : FROM IDENTIFIER IN expression
          {
-               current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
-               LocatedToken lt = (LocatedToken) $2;
-               
-               current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance, lt.Value, lt.Location);
-               $$ = new Linq.QueryExpression (lt, new Linq.QueryStartClause ((Expression)$4));
+               $$ = new Linq.QueryExpression (current_block, new Linq.QueryStartClause ((Expression)$4));
+               current_block = new Linq.QueryBlock (current_block, (LocatedToken) $2, GetLocation ($1));
          }
        | FROM type IDENTIFIER IN expression
          {
-               current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
-               LocatedToken lt = (LocatedToken) $3;
-
-               FullNamedExpression type = (FullNamedExpression)$2;
-               current_block.AddVariable (type, lt.Value, lt.Location);
-               $$ = new Linq.QueryExpression (lt, new Linq.Cast (type, (Expression)$5));
+               $$ = new Linq.QueryExpression (current_block, new Linq.Cast ((FullNamedExpression)$2, (Expression)$5));
+               current_block = new Linq.QueryBlock (current_block, (LocatedToken) $3, GetLocation ($1));
          }
        ;
        
 from_clause
-       : FROM IDENTIFIER IN expression
+       : FROM IDENTIFIER IN
+         {
+               current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
+         }
+         expression
          {
                LocatedToken lt = (LocatedToken) $2;
+               $$ = new Linq.SelectMany (current_block.Toplevel, lt, (Expression)$5);
                
-               current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
-                       lt.Value, lt.Location);
-                       
-               $$ = new Linq.SelectMany (lt, (Expression)$4);                  
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+               
+               ((Linq.QueryBlock)current_block).AddTransparentParameter (lt);
+         }       
+       | FROM type IDENTIFIER IN
+         {
+               current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
          }
-       | FROM type IDENTIFIER IN expression
+         expression
          {
                LocatedToken lt = (LocatedToken) $3;
-
                FullNamedExpression type = (FullNamedExpression)$2;
-               current_block.AddVariable (type, lt.Value, lt.Location);
-               $$ = new Linq.SelectMany (lt, new Linq.Cast (type, (FullNamedExpression)$5));
+               
+               $$ = new Linq.SelectMany (current_block.Toplevel, lt, new Linq.Cast (type, (FullNamedExpression)$6));
+               
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+               
+               ((Linq.QueryBlock)current_block).AddTransparentParameter (lt);
          }
        ;       
 
@@ -5258,13 +5268,38 @@ query_body
        ;
        
 select_or_group_clause
-       : SELECT expression
+       : SELECT
          {
-               $$ = new Linq.Select ((Expression)$2, GetLocation ($1));
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);
          }
-       | GROUP expression BY expression
+         expression
          {
-           $$ = new Linq.GroupBy ((Expression)$2, (Expression)$4, GetLocation ($1));
+               $$ = new Linq.Select (current_block.Toplevel, (Expression)$3, GetLocation ($1));
+
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+         }
+       | GROUP
+         {
+               if (linq_clause_blocks == null)
+                       linq_clause_blocks = new Stack ();
+                       
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);
+               linq_clause_blocks.Push (current_block);
+         }
+         expression
+         {
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+         
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);
+         }
+         BY expression
+         {
+               $$ = new Linq.GroupBy (current_block.Toplevel, (Expression)$3, (ToplevelBlock) linq_clause_blocks.Pop (), (Expression)$6, GetLocation ($1));
+               
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
          }
        ;
        
@@ -5291,54 +5326,130 @@ query_body_clause
        ;
        
 let_clause
-       : LET IDENTIFIER ASSIGN expression
+       : LET IDENTIFIER ASSIGN 
+         {
+               current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
+         }
+         expression
          {
                LocatedToken lt = (LocatedToken) $2;
-               current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
-                       lt.Value, lt.Location);   
-               $$ = new Linq.Let (lt, (Expression)$4, GetLocation ($1));
+               $$ = new Linq.Let (current_block.Toplevel, current_container, lt, (Expression)$5);
+               
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+               
+               ((Linq.QueryBlock)current_block).AddTransparentParameter (lt);
          }
        ;
 
 where_clause
-       : WHERE boolean_expression
+       : WHERE
          {
-               $$ = new Linq.Where ((Expression)$2, GetLocation ($1));
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);
+         }
+         boolean_expression
+         {
+               $$ = new Linq.Where (current_block.Toplevel, (Expression)$3, GetLocation ($1));
+
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
          }
        ;
        
 join_clause
-       : JOIN IDENTIFIER IN expression ON expression EQUALS expression opt_join_into
+       : JOIN IDENTIFIER IN
+         {
+               if (linq_clause_blocks == null)
+                       linq_clause_blocks = new Stack ();
+                       
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);
+               linq_clause_blocks.Push (current_block);
+         }
+         expression ON
+         {
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);
+               linq_clause_blocks.Push (current_block);
+         }
+         expression EQUALS
+         {
+               current_block.AddStatement (new ContextualReturn ((Expression) $8));
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+
+               current_block = new Linq.QueryBlock (current_block, (LocatedToken) $2, lexer.Location);
+         }
+         expression opt_join_into
          {
-               Location loc = GetLocation ($1);
                LocatedToken lt = (LocatedToken) $2;
-               current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
-                       lt.Value, lt.Location);
                
-               if ($9 == null) {
-                       $$ = new Linq.Join (lt, (Expression)$4, (Expression)$6,
-                               (Expression)$8, loc);
+               ToplevelBlock outer_selector = (ToplevelBlock) linq_clause_blocks.Pop ();
+               ToplevelBlock block = (ToplevelBlock) linq_clause_blocks.Pop ();
+
+               if ($12 == null) {
+                       $$ = new Linq.Join (block, lt, (Expression)$5, outer_selector, current_block.Toplevel, GetLocation ($1));
                } else {
-                       LocatedToken lt_into = (LocatedToken) $9;
-                       $$ = new Linq.GroupJoin (lt, (Expression)$4, (Expression)$6,
-                               (Expression)$8, lt_into, loc);
+                       $$ = new Linq.GroupJoin (block, lt, (Expression)$5, outer_selector, current_block.Toplevel,
+                               (LocatedToken) $12, GetLocation ($1));
                }
+
+               current_block.AddStatement (new ContextualReturn ((Expression) $11));
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+                       
+               if ($12 == null)
+                       ((Linq.QueryBlock)current_block).AddTransparentParameter (lt);
+               else
+                       ((Linq.QueryBlock)current_block).AddTransparentParameter ((LocatedToken) $12);
          }
-       | JOIN type IDENTIFIER IN expression ON expression EQUALS expression opt_join_into
+       | JOIN type IDENTIFIER IN
+         {
+               if (linq_clause_blocks == null)
+                       linq_clause_blocks = new Stack ();
+                       
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);
+               linq_clause_blocks.Push (current_block);
+         }
+         expression ON
+         {
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);
+               linq_clause_blocks.Push (current_block);
+         }
+         expression EQUALS
+         {
+               current_block.AddStatement (new ContextualReturn ((Expression) $9));
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+
+               current_block = new Linq.QueryBlock (current_block, (LocatedToken) $3, lexer.Location);
+         }
+         expression opt_join_into
          {
-               Location loc = GetLocation ($1);
                LocatedToken lt = (LocatedToken) $3;
-               current_block.AddVariable ((FullNamedExpression)$2, lt.Value, lt.Location);
+               ToplevelBlock outer_selector = (ToplevelBlock) linq_clause_blocks.Pop ();
+               ToplevelBlock block = (ToplevelBlock) linq_clause_blocks.Pop ();
                
-               Linq.Cast cast = new Linq.Cast ((FullNamedExpression)$2, (Expression)$5);
-               if ($10 == null) {
-                       $$ = new Linq.Join (lt, cast, (Expression)$7,
-                               (Expression)$9, loc);
+               Linq.Cast cast = new Linq.Cast ((FullNamedExpression)$2, (Expression)$6);
+               if ($13 == null) {
+                       $$ = new Linq.Join (block, lt, cast, outer_selector, current_block.Toplevel, GetLocation ($1));
                } else {
-                       LocatedToken lt_into = (LocatedToken) $10;
-                       $$ = new Linq.GroupJoin (lt, cast, (Expression)$7,
-                               (Expression)$9, lt_into, loc);
+                       $$ = new Linq.GroupJoin (block, lt, cast, outer_selector, current_block.Toplevel,
+                               (LocatedToken) $13, GetLocation ($1));
                }
+               
+               current_block.AddStatement (new ContextualReturn ((Expression) $12));
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+                       
+               if ($13 == null)
+                       ((Linq.QueryBlock)current_block).AddTransparentParameter (lt);
+               else
+                       ((Linq.QueryBlock)current_block).AddTransparentParameter ((LocatedToken) $13);
          }
        ;
        
@@ -5346,65 +5457,83 @@ opt_join_into
        : /* empty */
        | INTO IDENTIFIER
          {
-               $$ = $2;
+               $$ = $2;
          }
        ;
        
 orderby_clause
-       : ORDERBY orderings
+       : ORDERBY
          {
-               $$ = $2;
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);
+         }
+         orderings
+         {
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+         
+               $$ = $3;
          }
        ;
        
 orderings
        : order_by
-       | order_by COMMA orderings_then_by
+       | order_by COMMA
+         {
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+         
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);
+         }
+         orderings_then_by
          {
-               ((Linq.AQueryClause)$1).Next = (Linq.AQueryClause)$3;
+               ((Linq.AQueryClause)$1).Next = (Linq.AQueryClause)$4;
                $$ = $1;
          }
        ;
        
 orderings_then_by
        : then_by
-         {
-               $$ = $1;
-         }
-       | orderings_then_by COMMA then_by
-         {
+       | orderings_then_by COMMA
+        {
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+         
+               current_block = new Linq.QueryBlock (current_block, lexer.Location);     
+        }
+        then_by
+        {
                ((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$3;
                $$ = $1;
-         }
+        }
        ;       
        
 order_by
        : expression
          {
-               $$ = new Linq.OrderByAscending ((Expression)$1);        
+               $$ = new Linq.OrderByAscending (current_block.Toplevel, (Expression)$1);        
          }
        | expression ASCENDING
          {
-               $$ = new Linq.OrderByAscending ((Expression)$1);        
+               $$ = new Linq.OrderByAscending (current_block.Toplevel, (Expression)$1);        
          }
        | expression DESCENDING
          {
-               $$ = new Linq.OrderByDescending ((Expression)$1);       
+               $$ = new Linq.OrderByDescending (current_block.Toplevel, (Expression)$1);       
          }
        ;
 
 then_by
        : expression
          {
-               $$ = new Linq.ThenByAscending ((Expression)$1); 
+               $$ = new Linq.ThenByAscending (current_block.Toplevel, (Expression)$1); 
          }
        | expression ASCENDING
          {
-               $$ = new Linq.ThenByAscending ((Expression)$1); 
+               $$ = new Linq.ThenByAscending (current_block.Toplevel, (Expression)$1); 
          }
        | expression DESCENDING
          {
-               $$ = new Linq.ThenByDescending ((Expression)$1);        
+               $$ = new Linq.ThenByDescending (current_block.Toplevel, (Expression)$1);        
          }     
        ;
 
@@ -5419,16 +5548,12 @@ opt_query_continuation
 
                current_block.SetEndLocation (GetLocation ($1));
                current_block = current_block.Parent;
-               current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
                
-               LocatedToken lt = (LocatedToken) $2;
-               current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
-                       lt.Value, lt.Location);
+               current_block = new Linq.QueryBlock (current_block, (LocatedToken) $2, GetLocation ($1));
          }
          query_body
          {
-               $$ = new Linq.QueryExpression ((LocatedToken) $2,
-                       (Linq.AQueryClause)$4);
+               $$ = new Linq.QueryExpression (current_block, (Linq.AQueryClause)$4);
          }
        ;
        
index 77cd1355dde02f8d3432242dc1dbeef246ff6dea..2baa0b24e398aef53d29f15f519e58b19670ea43 100644 (file)
@@ -423,10 +423,11 @@ namespace Mono.CSharp {
                        }
 #endif
                        Delegate d = TypeManager.LookupDelegate (delegate_type);
+                       MethodInfo invoke;
                        if (d != null) {
 #if GMCS_SOURCE
                                if (g_args != null) {
-                                       MethodInfo invoke = TypeBuilder.GetMethod (dt, d.InvokeBuilder);
+                                       invoke = TypeBuilder.GetMethod (dt, d.InvokeBuilder);
 #if MS_COMPATIBLE
                                        Parameters p = (Parameters) d.Parameters.InflateTypes (g_args, g_args);
                                        TypeManager.RegisterMethod (invoke, p);
@@ -447,7 +448,17 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       return (MethodInfo) mg.Methods[0];
+                       invoke = (MethodInfo) mg.Methods[0];
+#if MS_COMPATIBLE
+                       if (g_args != null) {
+                               AParametersCollection p = TypeManager.GetParameterData (invoke);
+                               p = p.InflateTypes (g_args, g_args);
+                               TypeManager.RegisterMethod (invoke, p);
+                               return invoke;
+                       }
+#endif
+
+                       return invoke;
                }
 
                //
@@ -868,6 +879,11 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               public bool AmbiguousCall (MethodBase ambiguous)
+               {
+                       return false;
+               }
+
                #endregion
        }
 
index 7c5e99d01fea9b4df7e5e707ef687f7574ddedf2..27a5b003b1281b786ed76e6930f69727ffa6246b 100644 (file)
@@ -2004,6 +2004,7 @@ namespace Mono.CSharp
                        AnonymousMethodStorey.Reset ();
                        SymbolWriter.Reset ();
                        Switch.Reset ();
+                       Linq.QueryBlock.TransparentParameter.Reset ();
                }
 
        }
index eb67a4d965e0bb3d3697cbbd15369bd063e645f0..e7f92208ef984aaf3290f309689cf491871aea18 100644 (file)
@@ -2328,6 +2328,18 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override bool Equals (object obj)
+               {
+                       ATypeNameExpression atne = obj as ATypeNameExpression;
+                       return atne != null && atne.Name == Name &&
+                               (targs == null || targs.Equals (atne.targs));
+               }
+
+               public override int GetHashCode ()
+               {
+                       return Name.GetHashCode ();
+               }
+
                public override string GetSignatureForError ()
                {
                        if (targs != null) {
@@ -2622,9 +2634,6 @@ namespace Mono.CSharp {
                                }
 
                                Expression expr = current_block.Toplevel.GetParameterReference (Name, loc);
-                               if (expr == null)
-                                       expr = current_block.Toplevel.GetTransparentIdentifier (Name);
-
                                if (expr != null) {
                                        if (right_side != null)
                                                return expr.ResolveLValue (ec, right_side, loc);
@@ -3287,6 +3296,7 @@ namespace Mono.CSharp {
        {
                public interface IErrorHandler
                {
+                       bool AmbiguousCall (MethodBase ambiguous);
                        bool NoExactMatch (EmitContext ec, MethodBase method);
                }
 
@@ -3708,6 +3718,16 @@ namespace Mono.CSharp {
                        Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc);                   
                }
 
+               void Error_AmbiguousCall (MethodBase ambiguous)
+               {
+                       if (CustomErrorHandler != null && CustomErrorHandler.AmbiguousCall (ambiguous))
+                               return;
+
+                       Report.SymbolRelatedToPreviousError (best_candidate);
+                       Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
+                               TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate));
+               }
+
                protected virtual void Error_InvalidArguments (EmitContext ec, Location loc, int idx, MethodBase method,
                                                                                                        Argument a, AParametersCollection expected_par, Type paramType)
                {
@@ -4185,10 +4205,8 @@ namespace Mono.CSharp {
                                // return error info about the closest match
                                //
                                if (best_candidate != null) {
-                                       if (CustomErrorHandler != null) {
-                                               if (CustomErrorHandler.NoExactMatch (ec, best_candidate))
-                                                       return null;
-                                       }
+                                       if (CustomErrorHandler != null && CustomErrorHandler.NoExactMatch (ec, best_candidate))
+                                               return null;
 
                                        AParametersCollection pd = TypeManager.GetParameterData (best_candidate);
                                        bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
@@ -4351,9 +4369,7 @@ namespace Mono.CSharp {
                        }
 
                        if (ambiguous != null) {
-                               Report.SymbolRelatedToPreviousError (best_candidate);
-                               Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
-                                       TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate));
+                               Error_AmbiguousCall (ambiguous);
                                return this;
                        }
 
@@ -5457,7 +5473,7 @@ namespace Mono.CSharp {
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
                        if (right_side == EmptyExpression.OutAccess) {
-                               if (ec.CurrentBlock.Toplevel.GetTransparentIdentifier (PropertyInfo.Name) != null) {
+                               if (ec.CurrentBlock.Toplevel.GetParameterReference (PropertyInfo.Name, loc) is MemberAccess) {
                                        Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
                                            PropertyInfo.Name);
                                } else {
@@ -5481,7 +5497,7 @@ namespace Mono.CSharp {
                                if (getter == null)
                                        return null;
 
-                               if (ec.CurrentBlock.Toplevel.GetTransparentIdentifier (PropertyInfo.Name) != null) {
+                               if (ec.CurrentBlock.Toplevel.GetParameterReference (PropertyInfo.Name, loc) is MemberAccess) {
                                        Report.Error (1947, loc, "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value",
                                                PropertyInfo.Name);
                                } else {
index f07ea4baa674bbc86a47e72d1fa0faafb40e8579..bedc9d74e5018bd446dc65dd6c36b38df9262d88 100644 (file)
@@ -1610,7 +1610,9 @@ namespace Mono.CSharp
                public bool this [int index] {
                        get {
                                if (index >= Count)
-                                       throw new ArgumentOutOfRangeException ();
+                                       // FIXME: Disabled due to missing anonymous method flow analysis
+                                       // throw new ArgumentOutOfRangeException ();
+                                       return true; 
 
                                if (vector != null)
                                        return vector [index];
index 10632b6b9d103b3cb680d694a72aedd351f490a1..bd4a3b6d7b453235700c7959922014a3c003f47f 100644 (file)
@@ -1646,7 +1646,7 @@ namespace Mono.CSharp {
                ///   Define and resolve the type parameters.
                ///   We're called from Method.Define().
                /// </summary>
-               public bool Define (MethodBuilder mb)
+               public bool Define (MethodOrOperator m)
                {
                        TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations ();
                        string[] snames = new string [names.Length];
@@ -1654,14 +1654,18 @@ namespace Mono.CSharp {
                                string type_argument_name = names[i].Name;
                                int idx = parameters.GetParameterIndexByName (type_argument_name);
                                if (idx >= 0) {
-                                       Error_ParameterNameCollision (parameters [i].Location, type_argument_name, "method parameter");
-                                       return false;
+                                       Block b = m.Block;
+                                       if (b == null)
+                                               b = new Block (null);
+
+                                       b.Error_AlreadyDeclaredTypeParameter (parameters [i].Location,
+                                               type_argument_name, "method parameter");
                                }
                                
                                snames[i] = type_argument_name;
                        }
 
-                       GenericTypeParameterBuilder[] gen_params = mb.DefineGenericParameters (snames);
+                       GenericTypeParameterBuilder[] gen_params = m.MethodBuilder.DefineGenericParameters (snames);
                        for (int i = 0; i < TypeParameters.Length; i++)
                                TypeParameters [i].Define (gen_params [i]);
 
@@ -1676,12 +1680,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               internal static void Error_ParameterNameCollision (Location loc, string name, string collisionWith)
-               {
-                       Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
-                               name, collisionWith);
-               }
-
                /// <summary>
                ///   We're called from MethodData.Define() after creating the MethodBuilder.
                /// </summary>
index b8e009343a27b71adaca7b9b30829d05e4c969bb..46a86df477b12cdb82b18b574a3d817fba213a44 100644 (file)
@@ -135,6 +135,11 @@ namespace Mono.CSharp {
                {
                }
 
+               protected override void CloneTo (CloneContext clonectx, Expression target)
+               {
+                       // TODO: nothing ??
+               }
+
                public override string ContainerType {
                        get {
                                return "lambda expression";
index bff39a7238b176a07d58dc5f86509cf23fa3655f..3a3018797415a4709efbd90d1b25d9b12d3341ea 100644 (file)
@@ -20,28 +20,24 @@ namespace Mono.CSharp.Linq
        //
        //
 
-       public class QueryExpression : AQueryClause
+       class QueryExpression : AQueryClause
        {
-               LocatedToken variable;
-
-               public QueryExpression (LocatedToken variable, AQueryClause query)
-                       : base (null, query.Location)
+               public QueryExpression (Block block, AQueryClause query)
+                       : base (null, null, query.Location)
                {
-                       this.variable = variable;
                        this.next = query;
                }
 
-               public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parentParameter, TransparentIdentifiersScope ti)
+               public override Expression BuildQueryClause (EmitContext ec, Expression lSide)
                {
-                       Parameter p = CreateBlockParameter (variable);
-                       return next.BuildQueryClause (ec, lSide, p, ti);
+                       return next.BuildQueryClause (ec, lSide);
                }
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       int counter = TransparentParameter.Counter;
+                       int counter = QueryBlock.TransparentParameter.Counter;
 
-                       Expression e = BuildQueryClause (ec, null, null, null);
+                       Expression e = BuildQueryClause (ec, null);
                        e = e.Resolve (ec);
 
                        //
@@ -49,7 +45,7 @@ namespace Mono.CSharp.Linq
                        // identifier anonymous types are created only once
                        //
                        if (ec.IsInProbingMode)
-                               TransparentParameter.Counter = counter;
+                               QueryBlock.TransparentParameter.Counter = counter;
 
                        return e;
                }
@@ -59,7 +55,7 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public abstract class AQueryClause : Expression
+       abstract class AQueryClause : Expression
        {
                class QueryExpressionAccess : MemberAccess
                {
@@ -97,6 +93,15 @@ namespace Mono.CSharp.Linq
                                return rmg;
                        }
 
+                       public bool AmbiguousCall (MethodBase ambiguous)
+                       {
+                               Report.SymbolRelatedToPreviousError ((MethodInfo) mg);
+                               Report.SymbolRelatedToPreviousError (ambiguous);
+                               Report.Error (1940, loc, "Ambiguous implementation of the query pattern `{0}' for source type `{1}'",
+                                       mg.Name, mg.InstanceExpression.GetSignatureForError ());
+                               return true;
+                       }
+
                        public bool NoExactMatch (EmitContext ec, MethodBase method)
                        {
 #if GMCS_SOURCE                                
@@ -123,9 +128,15 @@ namespace Mono.CSharp.Linq
                                if (!method.IsGenericMethod)
                                        return false;
 
-                               Report.Error (1942, loc, "Type inference failed to infer type argument for `{0}' clause. " +
-                                       "Try specifying the type argument explicitly",
-                                       mg.Name.ToLower ());
+                               if (mg.Name == "SelectMany") {
+                                       Report.Error (1943, loc,
+                                               "An expression type is incorrect in a subsequent `from' clause in a query expression with source type `{0}'",
+                                               ((Argument) Arguments [0]).GetSignatureForError ());
+                               } else {
+                                       Report.Error (1942, loc,
+                                               "An expression type in `{0}' clause is incorrect. Type inference failed in the call to `{1}'",
+                                               mg.Name.ToLower (), mg.Name);
+                               }
                                return true;
 #else
                                return false;
@@ -133,11 +144,14 @@ namespace Mono.CSharp.Linq
                        }
                }
 
+               // TODO: protected
                public AQueryClause next;
-               /*protected*/ public Expression expr;
+               public Expression expr;
+               protected ToplevelBlock block;
 
-               protected AQueryClause (Expression expr, Location loc)
+               protected AQueryClause (ToplevelBlock block, Expression expr, Location loc)
                {
+                       this.block = block;
                        this.expr = expr;
                        this.loc = loc;
                }
@@ -147,9 +161,12 @@ namespace Mono.CSharp.Linq
                        AQueryClause t = (AQueryClause) target;
                        if (expr != null)
                                t.expr = expr.Clone (clonectx);
-                       
+
+                       if (block != null)
+                               t.block = (ToplevelBlock) block.Clone (clonectx);
+
                        if (next != null)
-                               t.next = (AQueryClause)next.Clone (clonectx);
+                               t.next = (AQueryClause) next.Clone (clonectx);
                }
 
                public override Expression CreateExpressionTree (EmitContext ec)
@@ -163,27 +180,33 @@ namespace Mono.CSharp.Linq
                        return expr.DoResolve (ec);
                }
 
-               public virtual Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
+               public virtual Expression BuildQueryClause (EmitContext ec, Expression lSide)
                {
-                       ArrayList args = new ArrayList (1);
-                       args.Add (CreateSelectorArgument (ec, expr, parameter, ti));
+                       ArrayList args;
+                       CreateArguments (ec, out args);
                        lSide = CreateQueryExpression (lSide, args);
                        if (next != null) {
                                Select s = next as Select;
-                               if (s == null || s.IsRequired (parameter))
-                                       return next.BuildQueryClause (ec, lSide, parameter, ti);
+                               if (s == null || s.IsRequired)
+                                       return next.BuildQueryClause (ec, lSide);
                                        
                                // Skip transparent select clause if any clause follows
                                if (next.next != null)
-                                       return next.next.BuildQueryClause (ec, lSide, parameter, ti);
+                                       return next.next.BuildQueryClause (ec, lSide);
                        }
 
                        return lSide;
                }
 
-               protected static Parameter CreateBlockParameter (LocatedToken li)
+               protected virtual void CreateArguments (EmitContext ec, out ArrayList args)
                {
-                       return new ImplicitQueryParameter (li);
+                       args = new ArrayList (2);
+
+                       LambdaExpression selector = new LambdaExpression (loc);
+                       selector.Block = block;
+                       selector.Block.AddStatement (new ContextualReturn (expr));
+
+                       args.Add (new Argument (selector));
                }
 
                protected Invocation CreateQueryExpression (Expression lSide, ArrayList arguments)
@@ -198,22 +221,6 @@ namespace Mono.CSharp.Linq
                                new QueryExpressionAccess (lSide, MethodName, typeArguments, loc), arguments);
                }
 
-               protected Argument CreateSelectorArgument (EmitContext ec, Expression expr, Parameter parameter, TransparentIdentifiersScope ti)
-               {
-                       return CreateSelectorArgument (ec, expr, new Parameter [] { parameter }, ti);
-               }
-
-               protected Argument CreateSelectorArgument (EmitContext ec, Expression expr, Parameter[] parameters, TransparentIdentifiersScope ti)
-               {
-                       Parameters p = new Parameters (parameters);
-
-                       LambdaExpression selector = new LambdaExpression (loc);
-                       selector.Block = new SelectorBlock (ec.CurrentBlock, p, ti, loc);
-                       selector.Block.AddStatement (new ContextualReturn (expr));
-
-                       return new Argument (selector);
-               }
-
                public override void Emit (EmitContext ec)
                {
                        throw new NotSupportedException ();
@@ -242,100 +249,51 @@ namespace Mono.CSharp.Linq
        //
        // A query clause with an identifier (range variable)
        //
-       public abstract class ARangeVariableQueryClause : AQueryClause
+       abstract class ARangeVariableQueryClause : AQueryClause
        {
-               LocatedToken variable;
-               protected Expression element_selector;
-
-               protected ARangeVariableQueryClause (LocatedToken variable, Expression expr, Location loc)
-                       : base (expr, loc)
+               sealed class RangeAnonymousTypeParameter : AnonymousTypeParameter
                {
-                       this.variable = variable;
-               }
-
-               protected virtual void AddSelectorArguments (EmitContext ec, ArrayList args, Parameter parentParameter,
-                       ref Parameter parameter, TransparentIdentifiersScope ti)
-               {
-                       args.Add (CreateSelectorArgument (ec, expr, parentParameter, ti));
-                       args.Add (CreateSelectorArgument (ec, element_selector,
-                               new Parameter [] { parentParameter, parameter }, ti));
-               }
-
-               //
-               // Customization for range variables which not only creates a lambda expression but
-               // also builds a chain of range varible pairs
-               //
-               public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parentParameter, TransparentIdentifiersScope ti)
-               {
-                       Parameter parameter = CreateBlockParameter (variable);
-
-                       if (next != null) {
-                               //
-                               // Builds transparent identifiers, each identifier includes its parent
-                               // type at index 0, and new value at index 1. This is not valid for the
-                               // first one which includes two values directly.
-                               //
-                               ArrayList transp_args = new ArrayList (2);
-                               transp_args.Add (new AnonymousTypeParameter (parentParameter));
-                               transp_args.Add (CreateAnonymousTypeVariable (parameter));
-                               element_selector = new AnonymousTypeDeclaration (transp_args, (TypeContainer) ec.TypeContainer, loc);
+                       public RangeAnonymousTypeParameter (Expression initializer, LocatedToken parameter)
+                               : base (initializer, parameter.Value, parameter.Location)
+                       {
                        }
 
-                       ArrayList args = new ArrayList ();
-                       AddSelectorArguments (ec, args, parentParameter, ref parameter, ti);
-
-                       lSide = CreateQueryExpression (lSide, args);
-                       if (next != null) {
-                               //
-                               // Parameter identifiers go to the scope
-                               //
-                               string[] identifiers;
-                               if (ti == null) {
-                                       identifiers = new string [] { parentParameter.Name, parameter.Name };
-                               } else {
-                                       identifiers = new string [] { parameter.Name };
-                               }
-
-                               TransparentParameter tp = new TransparentParameter (loc);
-                               return next.BuildQueryClause (ec, lSide, tp,
-                                       new TransparentIdentifiersScope (ti, tp, identifiers));
+                       protected override void Error_InvalidInitializer (string initializer)
+                       {
+                               Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'",
+                                       Name, initializer);
                        }
-
-                       return lSide;
                }
-               
-               protected override void CloneTo (CloneContext clonectx, Expression target)
+
+               protected ARangeVariableQueryClause (ToplevelBlock block, Expression expr)
+                       : base (block, expr, expr.Location)
                {
-                       ARangeVariableQueryClause t = (ARangeVariableQueryClause) target;
-                       if (element_selector != null)
-                               t.element_selector = element_selector.Clone (clonectx);
-                       base.CloneTo (clonectx, t);
                }
-               
-               //
-               // For transparent identifiers, creates an instance of variable expression
-               //
-               protected virtual AnonymousTypeParameter CreateAnonymousTypeVariable (Parameter parameter)
+
+               protected static Expression CreateRangeVariableType (ToplevelBlock block, TypeContainer container, LocatedToken name, Expression init)
                {
-                       return new AnonymousTypeParameter (parameter);
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new AnonymousTypeParameter (block.Parameters [0]));
+                       args.Add (new RangeAnonymousTypeParameter (init, name));
+                       return new AnonymousTypeDeclaration (args, container, name.Location);
                }
        }
 
-       public class QueryStartClause : AQueryClause
+       class QueryStartClause : AQueryClause
        {
                public QueryStartClause (Expression expr)
-                       : base (expr, expr.Location)
+                       : base (null, expr, expr.Location)
                {
                }
 
-               public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
+               public override Expression BuildQueryClause (EmitContext ec, Expression lSide)
                {
-                       return next.BuildQueryClause (ec, expr, parameter, ti);
+                       return next.BuildQueryClause (ec, expr);
                }
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       Expression e = BuildQueryClause (ec, null, null, null);
+                       Expression e = BuildQueryClause (ec, null);
                        return e.Resolve (ec);
                }
 
@@ -344,7 +302,7 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public class Cast : QueryStartClause
+       class Cast : QueryStartClause
        {
                // We don't have to clone cast type
                readonly FullNamedExpression type_expr;
@@ -355,11 +313,11 @@ namespace Mono.CSharp.Linq
                        this.type_expr = type;
                }
                
-               public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
+               public override Expression BuildQueryClause (EmitContext ec, Expression lSide)
                {
                        lSide = CreateQueryExpression (expr, new TypeArguments (type_expr), null);
                        if (next != null)
-                               return next.BuildQueryClause (ec, lSide, parameter, ti);
+                               return next.BuildQueryClause (ec, lSide);
 
                        return lSide;
                }
@@ -369,36 +327,43 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public class GroupBy : AQueryClause
+       class GroupBy : AQueryClause
        {
                Expression element_selector;
+               ToplevelBlock element_block;
                
-               public GroupBy (Expression elementSelector, Expression keySelector, Location loc)
-                       : base (keySelector, loc)
+               public GroupBy (ToplevelBlock block, Expression elementSelector, ToplevelBlock elementBlock, Expression keySelector, Location loc)
+                       : base (block, keySelector, loc)
                {
-                       this.element_selector = elementSelector;
+                       //
+                       // Optimizes clauses like `group A by A'
+                       //
+                       if (!elementSelector.Equals (keySelector)) {
+                               this.element_selector = elementSelector;
+                               this.element_block = elementBlock;
+                       }
                }
 
-               public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
+               protected override void CreateArguments (EmitContext ec, out ArrayList args)
                {
-                       ArrayList args = new ArrayList (2);
-                       args.Add (CreateSelectorArgument (ec, expr, parameter, ti));
-
-                       // A query can be optimized when selector is not group by specific
-                       if (!element_selector.Equals (lSide))
-                               args.Add (CreateSelectorArgument (ec, element_selector, parameter, ti));
+                       base.CreateArguments (ec, out args);
 
-                       lSide = CreateQueryExpression (lSide, args);
-                       if (next != null)
-                               return next.BuildQueryClause (ec, lSide, parameter, ti);
-
-                       return lSide;
+                       if (element_selector != null) {
+                               LambdaExpression lambda = new LambdaExpression (element_selector.Location);
+                               lambda.Block = element_block;
+                               lambda.Block.AddStatement (new ContextualReturn (element_selector));
+                               args.Add (new Argument (lambda));
+                       }
                }
-       
+
                protected override void CloneTo (CloneContext clonectx, Expression target)
                {
                        GroupBy t = (GroupBy) target;
-                       t.element_selector = element_selector.Clone (clonectx);
+                       if (element_selector != null) {
+                               t.element_selector = element_selector.Clone (clonectx);
+                               t.element_block = (ToplevelBlock) element_block.Clone (clonectx);
+                       }
+
                        base.CloneTo (clonectx, t);
                }
 
@@ -407,87 +372,85 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public class Join : ARangeVariableQueryClause
+       class Join : ARangeVariableQueryClause
        {
-               Expression projection;
-               Expression inner_selector, outer_selector;
+               readonly LocatedToken lt;
+               ToplevelBlock inner_selector, outer_selector;
 
-               public Join (LocatedToken variable, Expression inner, Expression outerSelector, Expression innerSelector, Location loc)
-                       : base (variable, inner, loc)
+               public Join (ToplevelBlock block, LocatedToken lt, Expression inner, ToplevelBlock outerSelector, ToplevelBlock innerSelector, Location loc)
+                       : base (block, inner)
                {
+                       this.lt = lt;
                        this.outer_selector = outerSelector;
                        this.inner_selector = innerSelector;
                }
 
-               protected override void AddSelectorArguments (EmitContext ec, ArrayList args, Parameter parentParameter,
-                       ref Parameter parameter, TransparentIdentifiersScope ti)
+               protected override void CreateArguments (EmitContext ec, out ArrayList args)
                {
+                       args = new ArrayList (4);
+
                        args.Add (new Argument (expr));
-                       args.Add (CreateSelectorArgument (ec, outer_selector, parentParameter, ti));
-                       args.Add (CreateSelectorArgument (ec, inner_selector, parameter, ti));
-
-                       parameter = CreateResultSelectorParameter (parameter);
-                       if (projection == null) {
-                               ArrayList join_args = new ArrayList (2);
-                               join_args.Add (new AnonymousTypeParameter (parentParameter));
-                               join_args.Add (new AnonymousTypeParameter (parameter));
-                               projection = new AnonymousTypeDeclaration (join_args, (TypeContainer) ec.TypeContainer, loc);
+
+                       LambdaExpression lambda = new LambdaExpression (outer_selector.StartLocation);
+                       lambda.Block = outer_selector;
+                       args.Add (new Argument (lambda));
+
+                       lambda = new LambdaExpression (inner_selector.StartLocation);
+                       lambda.Block = inner_selector;
+                       args.Add (new Argument (lambda));
+
+                       Expression result_selector_expr;
+                       LocatedToken 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, (TypeContainer) ec.TypeContainer, into_variable,
+                                       new SimpleName (into_variable.Value, into_variable.Location));
                        }
 
-                       args.Add (CreateSelectorArgument (ec, projection,
-                               new Parameter [] { parentParameter, parameter }, ti));
+                       LambdaExpression result_selector = new LambdaExpression (lt.Location);
+                       result_selector.Block = new QueryBlock (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 LocatedToken GetIntoVariable ()
+               {
+                       return lt;
                }
-       
+
                protected override void CloneTo (CloneContext clonectx, Expression target)
                {
                        Join t = (Join) target;
-                       t.projection = projection.Clone (clonectx);
-                       t.inner_selector = inner_selector.Clone (clonectx);
-                       t.outer_selector = outer_selector.Clone (clonectx);
+                       t.inner_selector = (ToplevelBlock) inner_selector.Clone (clonectx);
+                       t.outer_selector = (ToplevelBlock) outer_selector.Clone (clonectx);
                        base.CloneTo (clonectx, t);
                }       
 
-               protected virtual Parameter CreateResultSelectorParameter (Parameter parameter)
-               {
-                       return parameter;
-               }
-
-               public override AQueryClause Next {
-                       set {
-                               // Use select as join projection
-                               if (value is Select) {
-                                       projection = value.expr;
-                                       next = value.next;
-                                       return;
-                               }
-
-                               base.Next = value;
-                       }
-               }
-
                protected override string MethodName {
                        get { return "Join"; }
                }
        }
 
-       public class GroupJoin : Join
+       class GroupJoin : Join
        {
-               readonly LocatedToken into_variable;
+               readonly LocatedToken into;
 
-               public GroupJoin (LocatedToken variable, Expression inner, Expression outerSelector, Expression innerSelector,
-                       LocatedToken into, Location loc)
-                       : base (variable, inner, outerSelector, innerSelector, loc)
+               public GroupJoin (ToplevelBlock block, LocatedToken lt, Expression inner,
+                       ToplevelBlock outerSelector, ToplevelBlock innerSelector, LocatedToken into, Location loc)
+                       : base (block, lt, inner, outerSelector, innerSelector, loc)
                {
-                       this.into_variable = into;
+                       this.into = into;
                }
 
-               protected override Parameter CreateResultSelectorParameter (Parameter parameter)
+               protected override LocatedToken GetIntoVariable ()
                {
-                       //
-                       // into variable is used as result selector and it's passed as
-                       // transparent identifiers to the next clause
-                       //
-                       return CreateBlockParameter (into_variable);
+                       return into;
                }
 
                protected override string MethodName {
@@ -495,63 +458,22 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public class Let : ARangeVariableQueryClause
+       class Let : ARangeVariableQueryClause
        {
-               class RangeAnonymousTypeParameter : AnonymousTypeParameter
-               {
-                       readonly Parameter parameter;
-
-                       public RangeAnonymousTypeParameter (Expression initializer, Parameter parameter)
-                               : base (initializer, parameter.Name, parameter.Location)
-                       {
-                               this.parameter = parameter;
-                       }
-
-                       public override Expression DoResolve (EmitContext ec)
-                       {
-                               Expression e = base.DoResolve (ec);
-                               if (e != null) {
-                                       //
-                                       // Spread resolved initializer type
-                                       //
-                                       ((ImplicitLambdaParameter) parameter).Type = type;
-                               }
-
-                               return e;
-                       }
-
-                       protected override void Error_InvalidInitializer (string initializer)
-                       {
-                               Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'",
-                                       Name, initializer);
-                       }                       
-               }
-
-               public Let (LocatedToken variable, Expression expr, Location loc)
-                       : base (variable, expr, loc)
+               public Let (ToplevelBlock block, TypeContainer container, LocatedToken identifier, Expression expr)
+                       : base (block, CreateRangeVariableType (block, container, identifier, expr))
                {
                }
 
-               protected override void AddSelectorArguments (EmitContext ec, ArrayList args, Parameter parentParameter,
-                       ref Parameter parameter, TransparentIdentifiersScope ti)
-               {
-                       args.Add (CreateSelectorArgument (ec, element_selector, parentParameter, ti));
-               }
-
-               protected override AnonymousTypeParameter CreateAnonymousTypeVariable (Parameter parameter)
-               {
-                       return new RangeAnonymousTypeParameter (expr, parameter);
-               }
-
                protected override string MethodName {
                        get { return "Select"; }
                }
        }
 
-       public class Select : AQueryClause
+       class Select : AQueryClause
        {
-               public Select (Expression expr, Location loc)
-                       : base (expr, loc)
+               public Select (ToplevelBlock block, Expression expr, Location loc)
+                       : base (block, expr, loc)
                {
                }
                
@@ -559,13 +481,14 @@ 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 (Parameter parameter)
-               {
-                       SimpleName sn = expr as SimpleName;
-                       if (sn == null)
-                               return true;
+               public bool IsRequired {
+                       get {
+                               SimpleName sn = expr as SimpleName;
+                               if (sn == null)
+                                       return true;
 
-                       return sn.Name != parameter.Name;
+                               return sn.Name != block.Parameters[0].Name;
+                       }
                }
 
                protected override string MethodName {
@@ -573,34 +496,47 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public class SelectMany : ARangeVariableQueryClause
+       class SelectMany : ARangeVariableQueryClause
        {
-               public SelectMany (LocatedToken variable, Expression expr)
-                       : base (variable, expr, expr.Location)
+               LocatedToken lt;
+
+               public SelectMany (ToplevelBlock block, LocatedToken lt, Expression expr)
+                       : base (block, expr)
                {
+                       this.lt = lt;
                }
 
-               protected override string MethodName {
-                       get { return "SelectMany"; }
-               }
+               protected override void CreateArguments (EmitContext ec, out ArrayList args)
+               {
+                       base.CreateArguments (ec, out args);
 
-               public override AQueryClause Next {
-                       set {
-                               element_selector = value.expr;
+                       Expression result_selector_expr;
+                       //
+                       // When select follow use is as result selector
+                       //
+                       if (next is Select) {
+                               result_selector_expr = next.expr;
+                               next = next.next;
+                       } else {
+                               result_selector_expr = CreateRangeVariableType (block, (TypeContainer)ec.TypeContainer, lt, new SimpleName (lt.Value, lt.Location));
+                       }
 
-                               // Can be optimized as SelectMany element selector
-                               if (value is Select)
-                                       return;
+                       LambdaExpression result_selector = new LambdaExpression (lt.Location);
+                       result_selector.Block = new QueryBlock (block.Parent, block.Parameters, lt, block.StartLocation);
+                       result_selector.Block.AddStatement (new ContextualReturn (result_selector_expr));
 
-                               next = value;
-                       }
+                       args.Add (new Argument (result_selector));
+               }
+
+               protected override string MethodName {
+                       get { return "SelectMany"; }
                }
        }
 
-       public class Where : AQueryClause
+       class Where : AQueryClause
        {
-               public Where (Expression expr, Location loc)
-                       : base (expr, loc)
+               public Where (ToplevelBlock block, Expression expr, Location loc)
+                       : base (block, expr, loc)
                {
                }
 
@@ -609,10 +545,10 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public class OrderByAscending : AQueryClause
+       class OrderByAscending : AQueryClause
        {
-               public OrderByAscending (Expression expr)
-                       : base (expr, expr.Location)
+               public OrderByAscending (ToplevelBlock block,Expression expr)
+                       : base (block, expr, expr.Location)
                {
                }
 
@@ -621,10 +557,10 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public class OrderByDescending : AQueryClause
+       class OrderByDescending : AQueryClause
        {
-               public OrderByDescending (Expression expr)
-                       : base (expr, expr.Location)
+               public OrderByDescending (ToplevelBlock block, Expression expr)
+                       : base (block, expr, expr.Location)
                {
                }
 
@@ -633,10 +569,10 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public class ThenByAscending : OrderByAscending
+       class ThenByAscending : OrderByAscending
        {
-               public ThenByAscending (Expression expr)
-                       : base (expr)
+               public ThenByAscending (ToplevelBlock block, Expression expr)
+                       : base (block, expr)
                {
                }
 
@@ -645,10 +581,10 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       public class ThenByDescending : OrderByDescending
+       class ThenByDescending : OrderByDescending
        {
-               public ThenByDescending (Expression expr)
-                       : base (expr)
+               public ThenByDescending (ToplevelBlock block, Expression expr)
+                       : base (block, expr)
                {
                }
 
@@ -657,169 +593,110 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       class ImplicitQueryParameter : ImplicitLambdaParameter
+       //
+       // Implicit query block
+       //
+       class QueryBlock : ToplevelBlock
        {
-               public sealed class ImplicitType : Expression
+               //
+               // Transparent parameters are used to package up the intermediate results
+               // and pass them onto next clause
+               //
+               public sealed class TransparentParameter : ImplicitLambdaParameter
                {
-                       public static ImplicitType Instance = new ImplicitType ();
-
-                       private ImplicitType ()
-                       {
-                       }
-
-                       protected override void CloneTo (CloneContext clonectx, Expression target)
-                       {
-                               // Nothing to clone
-                       }
+                       public static int Counter;
+                       const string ParameterNamePrefix = "<>__TranspIdent";
 
-                       public override Expression CreateExpressionTree (EmitContext ec)
-                       {
-                               throw new NotSupportedException ();
-                       }
+                       public readonly Parameters Parent;
+                       public readonly string Identifier;
 
-                       public override Expression DoResolve (EmitContext ec)
+                       public TransparentParameter (Parameters parent, LocatedToken identifier)
+                               : base (ParameterNamePrefix + Counter++, identifier.Location)
                        {
-                               throw new NotSupportedException ();
+                               Parent = parent;
+                               Identifier = identifier.Value;
                        }
 
-                       public override void Emit (EmitContext ec)
+                       public static void Reset ()
                        {
-                               throw new NotSupportedException ();
+                               Counter = 0;
                        }
+               }
 
-                       public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               public sealed class ImplicitQueryParameter : ImplicitLambdaParameter
+               {
+                       public ImplicitQueryParameter (string name, Location loc)
+                               : base (name, loc)
                        {
-                               throw new NotSupportedException ();
                        }
                }
 
-               public ImplicitQueryParameter (LocatedToken variable)
-                       : base (variable.Value, variable.Location)
+               public QueryBlock (Block parent, LocatedToken lt, Location start)
+                       : base (parent, new Parameters (new ImplicitQueryParameter (lt.Value, lt.Location)), start)
                {
+                       if (parent != null)
+                               base.CheckParentConflictName (parent.Toplevel, lt.Value, lt.Location);
                }
-       }
 
-       //
-       // Transparent parameters are used to package up the intermediate results
-       // and pass them onto next clause
-       //
-       public class TransparentParameter : ImplicitLambdaParameter
-       {
-               public static int Counter;
-               const string ParameterNamePrefix = "<>__TranspIdent";
-
-               public TransparentParameter (Location loc)
-                       : base (ParameterNamePrefix + Counter++, loc)
+               public QueryBlock (Block parent, Parameters parameters, LocatedToken lt, Location start)
+                       : base (parent, new Parameters (parameters [0].Clone (), new ImplicitQueryParameter (lt.Value, lt.Location)), start)
                {
                }
-       }
-
-       //
-       // Transparent identifiers are stored in nested anonymous types, each type can contain
-       // up to 2 identifiers or 1 identifier and parent type.
-       //
-       public class TransparentIdentifiersScope
-       {
-               readonly string [] identifiers;
-               readonly TransparentIdentifiersScope parent;
-               readonly TransparentParameter parameter;
 
-               public TransparentIdentifiersScope (TransparentIdentifiersScope parent,
-                       TransparentParameter parameter, string [] identifiers)
+               public QueryBlock (Block parent, Location start)
+                       : base (parent, parent.Toplevel.Parameters.Clone (), start)
                {
-                       this.parent = parent;
-                       this.parameter = parameter;
-                       this.identifiers = identifiers;
                }
 
-               public MemberAccess GetIdentifier (string name)
+               public void AddTransparentParameter (LocatedToken name)
                {
-                       TransparentIdentifiersScope ident = FindIdentifier (name);
-                       if (ident == null)
-                               return null;
+                       base.CheckParentConflictName (this, name.Value, name.Location);
 
-                       return new MemberAccess (CreateIdentifierNestingExpression (ident), name);
+                       parameters = new Parameters (new TransparentParameter (parameters, name));
                }
 
-               TransparentIdentifiersScope FindIdentifier (string name)
+               protected override bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
                {
-                       foreach (string s in identifiers) {
-                               if (s == name)
-                                       return this;
-                       }
-
-                       if (parent == null)
-                               return null;
-
-                       return parent.FindIdentifier (name);
+                       return true;
                }
 
-               Expression CreateIdentifierNestingExpression (TransparentIdentifiersScope end)
+               // 
+               // Query parameter reference can include transparent parameters
+               //
+               protected override Expression GetParameterReferenceExpression (string name, Location loc)
                {
-                       Expression expr = new SimpleName (parameter.Name, parameter.Location);
-                       TransparentIdentifiersScope current = this;
-                       while (current != end)
-                       {
-                               current = current.parent;
-                               expr = new MemberAccess (expr, current.parameter.Name);
-                       }
-
-                       return expr;
-               }
-       }
-
-       //
-       // Lambda expression block which contains transparent identifiers
-       //
-       class SelectorBlock : ToplevelBlock
-       {
-               readonly TransparentIdentifiersScope transparent_identifiers;
+                       Expression expr = base.GetParameterReferenceExpression (name, loc);
+                       if (expr != null)
+                               return expr;
 
-               public SelectorBlock (Block block, Parameters parameters, 
-                       TransparentIdentifiersScope transparentIdentifiers, Location loc)
-                       : base (block, parameters, loc)
-               {
-                       this.transparent_identifiers = transparentIdentifiers;
-               }
+                       TransparentParameter tp = parameters [0] as TransparentParameter;
+                       while (tp != null) {
+                               if (tp.Identifier == name)
+                                       break;
 
-               public override Expression GetTransparentIdentifier (string name)
-               {
-                       Expression expr = null;
-                       if (transparent_identifiers != null)
-                               expr = transparent_identifiers.GetIdentifier (name);
+                               TransparentParameter tp_next = tp.Parent [0] as TransparentParameter;
+                               if (tp_next == null) {
+                                       if (tp.Parent.GetParameterIndexByName (name) >= 0)
+                                               break;
+                               }
 
-                       if (expr != null || Container == null)
-                               return expr;
-                       
-                       return Container.GetTransparentIdentifier (name);
-               }
-       }
+                               tp = tp_next;
+                       }
 
-       //
-       // This block is actually never used, it is used by parser only
-       //
-       public class QueryBlock : ExplicitBlock
-       {
-               public QueryBlock (Block parent, Location start)
-                       : base (parent, start, Location.Null)
-               {
-                       range_variables = new System.Collections.Specialized.HybridDictionary ();
-               }
+                       if (tp != null) {
+                               expr = new SimpleName (parameters[0].Name, loc);
+                               TransparentParameter tp_cursor = (TransparentParameter) parameters[0];
+                               while (tp_cursor != tp) {
+                                       tp_cursor = (TransparentParameter) tp_cursor.Parent[0];
+                                       expr = new MemberAccess (expr, tp_cursor.Name);
+                               }
 
-               protected override void AddVariable (LocalInfo li)
-               {
-                       string name = li.Name;
-                       if (range_variables.Contains (name)) {
-                               LocalInfo conflict = (LocalInfo) range_variables [name];
-                               Report.SymbolRelatedToPreviousError (conflict.Location, name);
-                               Error_AlreadyDeclared (li.Location, name);
-                               return;
+                               return new MemberAccess (expr, name);
                        }
 
-                       range_variables.Add (name, li);
-                       Explicit.AddKnownVariable (name, li);
+                       return null;
                }
-               
+
                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}'",
@@ -832,7 +709,7 @@ namespace Mono.CSharp.Linq
                                var);           
                }
                
-               protected override void Error_AlreadyDeclaredTypeParameter (Location loc, string name)
+               public override void Error_AlreadyDeclaredTypeParameter (Location loc, string name, string conflict)
                {
                        Report.Error (1948, loc, "A range variable `{0}' conflicts with a method type parameter",
                                name);
index 75b04f33c0e426de6e488266bfef9f55ab4301ba..e5fcae8576581a39864147e9bb03609758788fe2 100644 (file)
@@ -915,8 +915,7 @@ namespace Mono.CSharp {
                                        if (base_name != parameters [j].Name)
                                                continue;
 
-                                       Report.Error (100, parameters [i].Location,
-                                               "The parameter name `{0}' is a duplicate", base_name);
+                                       ErrorDuplicateName (parameters [i]);
                                        i = j;
                                }
                        }
@@ -984,6 +983,11 @@ namespace Mono.CSharp {
                        return parameters;
                }
 
+               protected virtual void ErrorDuplicateName (Parameter p)
+               {
+                       Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
+               }
+
                /// <summary>
                ///    Returns the parameter information based on the name
                /// </summary>
@@ -1086,8 +1090,9 @@ namespace Mono.CSharp {
                {
                        Parameters p = (Parameters) MemberwiseClone ();
 
+                       p.parameters = new IParameterData [parameters.Length];
                        for (int i = 0; i < Count; ++i)
-                               p.FixedParameters [i] = this [i].Clone ();
+                               p.parameters [i] = this [i].Clone ();
 
                        return p;
                }
index bc08ed49dadc8f6981abfacc77637d906349c589..3dd81fc2e59adba3dce636ea9366de5f803c1547 100644 (file)
@@ -1559,7 +1559,6 @@ namespace Mono.CSharp {
                // Keeps track of (name, type) pairs
                //
                IDictionary variables;
-               protected IDictionary range_variables;
 
                //
                // Keeps track of constants
@@ -1811,34 +1810,45 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               public LocalInfo AddVariable (Expression type, string name, Location l)
+               protected virtual bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
                {
                        LocalInfo vi = GetLocalInfo (name);
                        if (vi != null) {
                                Report.SymbolRelatedToPreviousError (vi.Location, name);
                                if (Explicit == vi.Block.Explicit) {
-                                       if (type is Linq.ImplicitQueryParameter.ImplicitType && type == vi.Type)
-                                               Error_AlreadyDeclared (l, name);
-                                       else
-                                               Error_AlreadyDeclared (l, name, null);
+                                       Error_AlreadyDeclared (l, name, null);
                                } else {
-                                       Error_AlreadyDeclared (l, name, "parent");
+                                       Error_AlreadyDeclared (l, name, this is ToplevelBlock ?
+                                               "parent or current" : "parent");
                                }
-                               return null;
+                               return false;
                        }
 
-                       Expression e = Toplevel.GetParameterReference (name, Location.Null);
-                       if (e != null) {
-                               //Report.SymbolRelatedToPreviousError (pi.Parameter.Location, name);
-                               Error_AlreadyDeclared (loc, name, "parent or current");
-                               return null;
+                       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))
+                                               Error_AlreadyDeclared (loc, name);
+                                       else
+                                               Error_AlreadyDeclared (loc, name, "parent or current");
+                                       return false;
+                               }
                        }
-                       
+
+                       return true;
+               }
+
+               public LocalInfo AddVariable (Expression type, string name, Location l)
+               {
+                       if (!CheckParentConflictName (Toplevel, name, l))
+                               return null;
+
                        if (Toplevel.GenericMethod != null) {
                                foreach (TypeParameter tp in Toplevel.GenericMethod.CurrentTypeParameters) {
                                        if (tp.Name == name) {
                                                Report.SymbolRelatedToPreviousError (tp);
-                                               Error_AlreadyDeclaredTypeParameter (loc, name);
+                                               Error_AlreadyDeclaredTypeParameter (loc, name, "local variable");
                                                return null;
                                        }
                                }
@@ -1851,7 +1861,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       vi = new LocalInfo (type, name, this, l);
+                       LocalInfo vi = new LocalInfo (type, name, this, l);
                        AddVariable (vi);
 
                        if ((flags & Flags.VariablesInitialized) != 0)
@@ -1885,9 +1895,10 @@ namespace Mono.CSharp {
                                "A local variable named `{0}' is already defined in this scope", name);
                }
                                        
-               protected virtual void Error_AlreadyDeclaredTypeParameter (Location loc, string name)
+               public virtual void Error_AlreadyDeclaredTypeParameter (Location loc, string name, string conflict)
                {
-                       GenericMethod.Error_ParameterNameCollision (loc, name, "local variable");
+                       Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
+                               name, conflict);
                }                                       
 
                public bool AddConstant (Expression type, string name, Expression value, Location l)
@@ -1932,12 +1943,6 @@ namespace Mono.CSharp {
                                        if (ret != null)
                                                return ret;
                                }
-
-                               if (b.range_variables != null) {
-                                       ret = (LocalInfo) b.range_variables [name];
-                                       if (ret != null)
-                                               return ret;
-                               }
                        }
 
                        return null;
@@ -2600,7 +2605,7 @@ namespace Mono.CSharp {
        public class ToplevelBlock : ExplicitBlock {
                GenericMethod generic;
                FlowBranchingToplevel top_level_branching;
-               Parameters parameters;
+               protected Parameters parameters;
                ToplevelParameterInfo[] parameter_info;
                LocalInfo this_variable;
 
@@ -2696,15 +2701,11 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public virtual Expression GetTransparentIdentifier (string name)
-               {
-                       return null;
-               }
-
                void ProcessParameters ()
                {
                        int n = parameters.Count;
                        parameter_info = new ToplevelParameterInfo [n];
+                       ToplevelBlock top_parent = Parent == null ? null : Parent.Toplevel;
                        for (int i = 0; i < n; ++i) {
                                parameter_info [i] = new ToplevelParameterInfo (this, i);
 
@@ -2713,23 +2714,8 @@ namespace Mono.CSharp {
                                        continue;
 
                                string name = p.Name;
-                               LocalInfo vi = GetLocalInfo (name);
-                               if (vi != null) {
-                                       Report.SymbolRelatedToPreviousError (vi.Location, name);
-                                       Error_AlreadyDeclared (loc, name, "parent or current");
-                                       continue;
-                               }
-
-                               if (Parent != null) {
-                                       Expression e = Parent.Toplevel.GetParameterReference (name, loc);
-                                       if (e != null) {
-                                               //Report.SymbolRelatedToPreviousError (pi.Location, name);
-                                               Error_AlreadyDeclared (loc, name, "parent or current");
-                                               continue;
-                                       }
-                               }
-
-                               AddKnownVariable (name, parameter_info [i]);
+                               if (CheckParentConflictName (top_parent, name, loc))
+                                       AddKnownVariable (name, parameter_info [i]);
                        }
 
                        // mark this block as "used" so that we create local declarations in a sub-block
@@ -2787,8 +2773,8 @@ namespace Mono.CSharp {
                }
 
                //
-               // Returns a `ParameterReference' for the given name, or null if there
-               // is no such parameter
+               // Returns a parameter reference expression for the given name,
+               // or null if there is no such parameter
                //
                public Expression GetParameterReference (string name, Location loc)
                {
@@ -2801,11 +2787,11 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               Expression GetParameterReferenceExpression (string name, Location loc)
+               protected virtual Expression GetParameterReferenceExpression (string name, Location loc)
                {
                        int idx = parameters.GetParameterIndexByName (name);
                        return idx < 0 ?
-                               null : new ParameterReference (parameter_info[idx], loc);
+                               null : new ParameterReference (parameter_info [idx], loc);
                }
 
                // <summary>