From: Marek Safar Date: Sun, 28 Dec 2008 14:43:49 +0000 (-0000) Subject: 2008-12-28 Marek Safar X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=7f31b7689066a9ee63094b99849b482b7d12d161;p=mono.git 2008-12-28 Marek Safar 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 --- diff --git a/mcs/mcs/ChangeLog b/mcs/mcs/ChangeLog index 2ad6cbaa293..81b6546f455 100644 --- a/mcs/mcs/ChangeLog +++ b/mcs/mcs/ChangeLog @@ -1,3 +1,11 @@ +2008-12-28 Marek Safar + + 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 A fix for bug #460229 diff --git a/mcs/mcs/anonymous.cs b/mcs/mcs/anonymous.cs index d4ca17df155..72fc1c4c915 100644 --- a/mcs/mcs/anonymous.cs +++ b/mcs/mcs/anonymous.cs @@ -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; } diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs index 670f956068e..29f30db2151 100644 --- a/mcs/mcs/class.cs +++ b/mcs/mcs/class.cs @@ -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 diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index c67858d2e88..9b1ff66ed8c 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -131,6 +131,9 @@ namespace Mono.CSharp // Keeps track of global data changes to undo on parser error // public Undo undo; + + // Stack + 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); } ; diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs index 77cd1355dde..2baa0b24e39 100644 --- a/mcs/mcs/delegate.cs +++ b/mcs/mcs/delegate.cs @@ -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 } diff --git a/mcs/mcs/driver.cs b/mcs/mcs/driver.cs index 7c5e99d01fe..27a5b003b12 100644 --- a/mcs/mcs/driver.cs +++ b/mcs/mcs/driver.cs @@ -2004,6 +2004,7 @@ namespace Mono.CSharp AnonymousMethodStorey.Reset (); SymbolWriter.Reset (); Switch.Reset (); + Linq.QueryBlock.TransparentParameter.Reset (); } } diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index eb67a4d965e..e7f92208ef9 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -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 { diff --git a/mcs/mcs/flowanalysis.cs b/mcs/mcs/flowanalysis.cs index f07ea4baa67..bedc9d74e50 100644 --- a/mcs/mcs/flowanalysis.cs +++ b/mcs/mcs/flowanalysis.cs @@ -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]; diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs index 10632b6b9d1..bd4a3b6d7b4 100644 --- a/mcs/mcs/generic.cs +++ b/mcs/mcs/generic.cs @@ -1646,7 +1646,7 @@ namespace Mono.CSharp { /// Define and resolve the type parameters. /// We're called from Method.Define(). /// - 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); - } - /// /// We're called from MethodData.Define() after creating the MethodBuilder. /// diff --git a/mcs/mcs/lambda.cs b/mcs/mcs/lambda.cs index b8e009343a2..46a86df477b 100644 --- a/mcs/mcs/lambda.cs +++ b/mcs/mcs/lambda.cs @@ -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"; diff --git a/mcs/mcs/linq.cs b/mcs/mcs/linq.cs index bff39a7238b..3a301879741 100644 --- a/mcs/mcs/linq.cs +++ b/mcs/mcs/linq.cs @@ -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); diff --git a/mcs/mcs/parameter.cs b/mcs/mcs/parameter.cs index 75b04f33c0e..e5fcae85765 100644 --- a/mcs/mcs/parameter.cs +++ b/mcs/mcs/parameter.cs @@ -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); + } + /// /// Returns the parameter information based on the name /// @@ -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; } diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs index bc08ed49dad..3dd81fc2e59 100644 --- a/mcs/mcs/statement.cs +++ b/mcs/mcs/statement.cs @@ -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); } //