Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / mcs / linq.cs
1 //
2 // linq.cs: support for query expressions
3 //
4 // Authors: Marek Safar (marek.safar@gmail.com)
5 //
6 // Dual licensed under the terms of the MIT X11 or GNU GPL
7 //
8 // Copyright 2007-2008 Novell, Inc
9 // Copyright 2011 Xamarin Inc
10 //
11
12 using System;
13 using System.Collections.Generic;
14
15 namespace Mono.CSharp.Linq
16 {
17         public class QueryExpression : AQueryClause
18         {
19                 public QueryExpression (AQueryClause start)
20                         : base (null, null, start.Location)
21                 {
22                         this.next = start;
23                 }
24
25                 public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parentParameter)
26                 {
27                         return next.BuildQueryClause (ec, lSide, parentParameter);
28                 }
29
30                 protected override Expression DoResolve (ResolveContext ec)
31                 {
32                         int counter = QueryBlock.TransparentParameter.Counter;
33
34                         Expression e = BuildQueryClause (ec, null, null);
35                         if (e != null)
36                                 e = e.Resolve (ec);
37
38                         //
39                         // Reset counter in probing mode to ensure that all transparent
40                         // identifier anonymous types are created only once
41                         //
42                         if (ec.IsInProbingMode)
43                                 QueryBlock.TransparentParameter.Counter = counter;
44
45                         return e;
46                 }
47
48                 protected override string MethodName {
49                         get { throw new NotSupportedException (); }
50                 }
51         }
52
53         public abstract class AQueryClause : ShimExpression
54         {
55                 protected class QueryExpressionAccess : MemberAccess
56                 {
57                         public QueryExpressionAccess (Expression expr, string methodName, Location loc)
58                                 : base (expr, methodName, loc)
59                         {
60                         }
61
62                         public QueryExpressionAccess (Expression expr, string methodName, TypeArguments typeArguments, Location loc)
63                                 : base (expr, methodName, typeArguments, loc)
64                         {
65                         }
66
67                         public override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
68                         {
69                                 ec.Report.Error (1935, loc, "An implementation of `{0}' query expression pattern could not be found. " +
70                                         "Are you missing `System.Linq' using directive or `System.Core.dll' assembly reference?",
71                                         name);
72                         }
73                 }
74
75                 protected class QueryExpressionInvocation : Invocation, OverloadResolver.IErrorHandler
76                 {
77                         public QueryExpressionInvocation (QueryExpressionAccess expr, Arguments arguments)
78                                 : base (expr, arguments)
79                         {
80                         }
81
82                         protected override MethodGroupExpr DoResolveOverload (ResolveContext rc)
83                         {
84                                 using (rc.Set (ResolveContext.Options.QueryClauseScope)) {
85                                         return mg.OverloadResolve (rc, ref arguments, this, OverloadResolver.Restrictions.None);
86                                 }
87                         }
88
89                         protected override Expression DoResolveDynamic (ResolveContext ec, Expression memberExpr)
90                         {
91                                 ec.Report.Error (1979, loc,
92                                         "Query expressions with a source or join sequence of type `dynamic' are not allowed");
93                                 return null;
94                         }
95
96                         #region IErrorHandler Members
97
98                         bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous)
99                         {
100                                 var emg = mg as ExtensionMethodGroupExpr;
101                                 var type = emg == null ? mg.InstanceExpression : emg.ExtensionExpression;
102
103                                 ec.Report.SymbolRelatedToPreviousError (best);
104                                 ec.Report.SymbolRelatedToPreviousError (ambiguous);
105                                 ec.Report.Error (1940, loc, "Ambiguous implementation of the query pattern `{0}' for source type `{1}'",
106                                         best.Name, type.Type.GetSignatureForError ());
107                                 return true;
108                         }
109
110                         bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index)
111                         {
112                                 return false;
113                         }
114
115                         bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best)
116                         {
117                                 return false;
118                         }
119
120                         bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best)
121                         {
122                                 var ms = (MethodSpec) best;
123                                 TypeSpec source_type = ms.Parameters.ExtensionMethodType;
124                                 if (source_type != null) {
125                                         Argument a = arguments[0];
126
127                                         if (TypeManager.IsGenericType (source_type) && InflatedTypeSpec.ContainsTypeParameter (source_type)) {
128                                                 TypeInferenceContext tic = new TypeInferenceContext (source_type.TypeArguments);
129                                                 tic.OutputTypeInference (rc, a.Expr, source_type);
130                                                 if (tic.FixAllTypes (rc)) {
131                                                         source_type = source_type.GetDefinition ().MakeGenericType (rc, tic.InferredTypeArguments);
132                                                 }
133                                         }
134
135                                         if (!Convert.ImplicitConversionExists (rc, a.Expr, source_type)) {
136                                                 rc.Report.Error (1936, loc, "An implementation of `{0}' query expression pattern for source type `{1}' could not be found",
137                                                         best.Name, a.Type.GetSignatureForError ());
138                                                 return true;
139                                         }
140                                 }
141
142                                 if (best.Name == "SelectMany") {
143                                         rc.Report.Error (1943, loc,
144                                                 "An expression type is incorrect in a subsequent `from' clause in a query expression with source type `{0}'",
145                                                 arguments[0].GetSignatureForError ());
146                                 } else {
147                                         rc.Report.Error (1942, loc,
148                                                 "An expression type in `{0}' clause is incorrect. Type inference failed in the call to `{1}'",
149                                                 best.Name.ToLowerInvariant (), best.Name);
150                                 }
151
152                                 return true;
153                         }
154
155                         #endregion
156                 }
157
158                 public AQueryClause next;
159                 public QueryBlock block;
160
161                 protected AQueryClause (QueryBlock block, Expression expr, Location loc)
162                          : base (expr)
163                 {
164                         this.block = block;
165                         this.loc = loc;
166                 }
167                 
168                 protected override void CloneTo (CloneContext clonectx, Expression target)
169                 {
170                         base.CloneTo (clonectx, target);
171
172                         AQueryClause t = (AQueryClause) target;
173
174                         if (block != null)
175                                 t.block = (QueryBlock) clonectx.LookupBlock (block);
176
177                         if (next != null)
178                                 t.next = (AQueryClause) next.Clone (clonectx);
179                 }
180
181                 protected override Expression DoResolve (ResolveContext ec)
182                 {
183                         return expr.Resolve (ec);
184                 }
185
186                 public virtual Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter)
187                 {
188                         Arguments args = null;
189                         CreateArguments (ec, parameter, ref args);
190                         lSide = CreateQueryExpression (lSide, args);
191                         if (next != null) {
192                                 parameter = CreateChildrenParameters (parameter);
193
194                                 Select s = next as Select;
195                                 if (s == null || s.IsRequired (parameter))
196                                         return next.BuildQueryClause (ec, lSide, parameter);
197                                         
198                                 // Skip transparent select clause if any clause follows
199                                 if (next.next != null)
200                                         return next.next.BuildQueryClause (ec, lSide, parameter);
201                         }
202
203                         return lSide;
204                 }
205
206                 protected virtual Parameter CreateChildrenParameters (Parameter parameter)
207                 {
208                         // Have to clone the parameter for any children use, it carries block sensitive data
209                         return parameter.Clone ();
210                 }
211
212                 protected virtual void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
213                 {
214                         args = new Arguments (2);
215
216                         LambdaExpression selector = new LambdaExpression (loc);
217
218                         block.SetParameter (parameter);
219                         selector.Block = block;
220                         selector.Block.AddStatement (new ContextualReturn (expr));
221
222                         args.Add (new Argument (selector));
223                 }
224
225                 protected Invocation CreateQueryExpression (Expression lSide, Arguments arguments)
226                 {
227                         return new QueryExpressionInvocation (
228                                 new QueryExpressionAccess (lSide, MethodName, loc), arguments);
229                 }
230
231                 protected abstract string MethodName { get; }
232
233                 public AQueryClause Next {
234                         set {
235                                 next = value;
236                         }
237                 }
238
239                 public AQueryClause Tail {
240                         get {
241                                 return next == null ? this : next.Tail;
242                         }
243                 }
244         }
245
246         //
247         // A query clause with an identifier (range variable)
248         //
249         public abstract class ARangeVariableQueryClause : AQueryClause
250         {
251                 sealed class RangeAnonymousTypeParameter : AnonymousTypeParameter
252                 {
253                         public RangeAnonymousTypeParameter (Expression initializer, RangeVariable parameter)
254                                 : base (initializer, parameter.Name, parameter.Location)
255                         {
256                         }
257
258                         protected override void Error_InvalidInitializer (ResolveContext ec, string initializer)
259                         {
260                                 ec.Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'",
261                                         Name, initializer);
262                         }
263                 }
264
265                 class RangeParameterReference : ParameterReference
266                 {
267                         Parameter parameter;
268
269                         public RangeParameterReference (Parameter p)
270                                 : base (null, p.Location)
271                         {
272                                 this.parameter = p;
273                         }
274
275                         protected override Expression DoResolve (ResolveContext ec)
276                         {
277                                 pi = ec.CurrentBlock.ParametersBlock.GetParameterInfo (parameter);
278                                 return base.DoResolve (ec);
279                         }
280                 }
281
282                 protected RangeVariable identifier;
283
284                 protected ARangeVariableQueryClause (QueryBlock block, RangeVariable identifier, Expression expr, Location loc)
285                         : base (block, expr, loc)
286                 {
287                         this.identifier = identifier;
288                 }
289
290                 public RangeVariable Identifier {
291                         get {
292                                 return identifier;
293                         }
294                 }
295
296                 public FullNamedExpression IdentifierType { get; set; }
297
298                 protected Invocation CreateCastExpression (Expression lSide)
299                 {
300                         return new QueryExpressionInvocation (
301                                 new QueryExpressionAccess (lSide, "Cast", new TypeArguments (IdentifierType), loc), null);
302                 }
303
304                 protected override Parameter CreateChildrenParameters (Parameter parameter)
305                 {
306                         return new QueryBlock.TransparentParameter (parameter.Clone (), GetIntoVariable ());
307                 }
308
309                 protected static Expression CreateRangeVariableType (ResolveContext rc, Parameter parameter, RangeVariable name, Expression init)
310                 {
311                         var args = new List<AnonymousTypeParameter> (2);
312
313                         //
314                         // The first argument is the reference to the parameter
315                         //
316                         args.Add (new AnonymousTypeParameter (new RangeParameterReference (parameter), parameter.Name, parameter.Location));
317
318                         //
319                         // The second argument is the linq expression
320                         //
321                         args.Add (new RangeAnonymousTypeParameter (init, name));
322
323                         //
324                         // Create unique anonymous type
325                         //
326                         return new NewAnonymousType (args, rc.MemberContext.CurrentMemberDefinition.Parent, name.Location);
327                 }
328
329                 protected virtual RangeVariable GetIntoVariable ()
330                 {
331                         return identifier;
332                 }
333         }
334
335         public sealed class RangeVariable : INamedBlockVariable
336         {
337                 Block block;
338
339                 public RangeVariable (string name, Location loc)
340                 {
341                         Name = name;
342                         Location = loc;
343                 }
344
345                 #region Properties
346
347                 public Block Block {
348                         get {
349                                 return block;
350                         }
351                         set {
352                                 block = value;
353                         }
354                 }
355
356                 public bool IsDeclared {
357                         get {
358                                 return true;
359                         }
360                 }
361
362                 public bool IsParameter {
363                         get {
364                                 return false;
365                         }
366                 }
367
368                 public Location Location { get; private set; }
369
370                 public string Name { get; private set; }
371
372                 #endregion
373
374                 public Expression CreateReferenceExpression (ResolveContext rc, Location loc)
375                 {
376                         // 
377                         // We know the variable name is somewhere in the scope. This generates
378                         // an access expression from current block
379                         //
380                         var pb = rc.CurrentBlock.ParametersBlock;
381                         while (true) {
382                                 if (pb is QueryBlock) {
383                                         for (int i = pb.Parameters.Count - 1; i >= 0; --i) {
384                                                 var p = pb.Parameters[i];
385                                                 if (p.Name == Name)
386                                                         return pb.GetParameterReference (i, loc);
387
388                                                 Expression expr = null;
389                                                 var tp = p as QueryBlock.TransparentParameter;
390                                                 while (tp != null) {
391                                                         if (expr == null)
392                                                                 expr = pb.GetParameterReference (i, loc);
393                                                         else
394                                                                 expr = new TransparentMemberAccess (expr, tp.Name);
395
396                                                         if (tp.Identifier == Name)
397                                                                 return new TransparentMemberAccess (expr, Name);
398
399                                                         if (tp.Parent.Name == Name)
400                                                                 return new TransparentMemberAccess (expr, Name);
401
402                                                         tp = tp.Parent as QueryBlock.TransparentParameter;
403                                                 }
404                                         }
405                                 }
406
407                                 if (pb == block)
408                                         return null;
409
410                                 pb = pb.Parent.ParametersBlock;
411                         }
412                 }
413         }
414
415         public class QueryStartClause : ARangeVariableQueryClause
416         {
417                 public QueryStartClause (QueryBlock block, Expression expr, RangeVariable identifier, Location loc)
418                         : base (block, identifier, expr, loc)
419                 {
420                         block.AddRangeVariable (identifier);
421                 }
422
423                 public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter)
424                 {
425                         if (IdentifierType != null)
426                                 expr = CreateCastExpression (expr);
427
428                         if (parameter == null)
429                                 lSide = expr;
430
431                         return next.BuildQueryClause (ec, lSide, new ImplicitLambdaParameter (identifier.Name, identifier.Location));
432                 }
433
434                 protected override Expression DoResolve (ResolveContext ec)
435                 {
436                         Expression e = BuildQueryClause (ec, null, null);
437                         return e.Resolve (ec);
438                 }
439
440                 protected override string MethodName {
441                         get { throw new NotSupportedException (); }
442                 }
443         }
444
445         public class GroupBy : AQueryClause
446         {
447                 Expression element_selector;
448                 QueryBlock element_block;
449
450                 public GroupBy (QueryBlock block, Expression elementSelector, QueryBlock elementBlock, Expression keySelector, Location loc)
451                         : base (block, keySelector, loc)
452                 {
453                         //
454                         // Optimizes clauses like `group A by A'
455                         //
456                         if (!elementSelector.Equals (keySelector)) {
457                                 this.element_selector = elementSelector;
458                                 this.element_block = elementBlock;
459                         }
460                 }
461
462                 public Expression SelectorExpression {
463                         get {
464                                 return element_selector;
465                         }
466                 }
467
468                 protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
469                 {
470                         base.CreateArguments (ec, parameter, ref args);
471
472                         if (element_selector != null) {
473                                 LambdaExpression lambda = new LambdaExpression (element_selector.Location);
474
475                                 element_block.SetParameter (parameter.Clone ());
476                                 lambda.Block = element_block;
477                                 lambda.Block.AddStatement (new ContextualReturn (element_selector));
478                                 args.Add (new Argument (lambda));
479                         }
480                 }
481
482                 protected override void CloneTo (CloneContext clonectx, Expression target)
483                 {
484                         GroupBy t = (GroupBy) target;
485                         if (element_selector != null) {
486                                 t.element_selector = element_selector.Clone (clonectx);
487                                 t.element_block = (QueryBlock) element_block.Clone (clonectx);
488                         }
489
490                         base.CloneTo (clonectx, t);
491                 }
492
493                 protected override string MethodName {
494                         get { return "GroupBy"; }
495                 }
496                 
497                 public override object Accept (StructuralVisitor visitor)
498                 {
499                         return visitor.Visit (this);
500                 }
501         }
502
503         public class Join : SelectMany
504         {
505                 QueryBlock inner_selector, outer_selector;
506
507                 public Join (QueryBlock block, RangeVariable lt, Expression inner, QueryBlock outerSelector, QueryBlock innerSelector, Location loc)
508                         : base (block, lt, inner, loc)
509                 {
510                         this.outer_selector = outerSelector;
511                         this.inner_selector = innerSelector;
512                 }
513
514                 public QueryBlock InnerSelector {
515                         get {
516                                 return inner_selector;
517                         }
518                 }
519                 
520                 public QueryBlock OuterSelector {
521                         get {
522                                 return outer_selector;
523                         }
524                 }
525
526                 protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
527                 {
528                         args = new Arguments (4);
529
530                         if (IdentifierType != null)
531                                 expr = CreateCastExpression (expr);
532
533                         args.Add (new Argument (expr));
534
535                         outer_selector.SetParameter (parameter.Clone ());
536                         var lambda = new LambdaExpression (outer_selector.StartLocation);
537                         lambda.Block = outer_selector;
538                         args.Add (new Argument (lambda));
539
540                         inner_selector.SetParameter (new ImplicitLambdaParameter (identifier.Name, identifier.Location));
541                         lambda = new LambdaExpression (inner_selector.StartLocation);
542                         lambda.Block = inner_selector;
543                         args.Add (new Argument (lambda));
544
545                         base.CreateArguments (ec, parameter, ref args);
546                 }
547
548                 protected override void CloneTo (CloneContext clonectx, Expression target)
549                 {
550                         Join t = (Join) target;
551                         t.inner_selector = (QueryBlock) inner_selector.Clone (clonectx);
552                         t.outer_selector = (QueryBlock) outer_selector.Clone (clonectx);
553                         base.CloneTo (clonectx, t);
554                 }       
555
556                 protected override string MethodName {
557                         get { return "Join"; }
558                 }
559                 
560                 public override object Accept (StructuralVisitor visitor)
561                 {
562                         return visitor.Visit (this);
563                 }
564         }
565
566         public class GroupJoin : Join
567         {
568                 readonly RangeVariable into;
569
570                 public GroupJoin (QueryBlock block, RangeVariable lt, Expression inner,
571                         QueryBlock outerSelector, QueryBlock innerSelector, RangeVariable into, Location loc)
572                         : base (block, lt, inner, outerSelector, innerSelector, loc)
573                 {
574                         this.into = into;
575                 }
576
577                 protected override RangeVariable GetIntoVariable ()
578                 {
579                         return into;
580                 }
581
582                 protected override string MethodName {
583                         get { return "GroupJoin"; }
584                 }
585                 
586                 public override object Accept (StructuralVisitor visitor)
587                 {
588                         return visitor.Visit (this);
589                 }
590         }
591
592         public class Let : ARangeVariableQueryClause
593         {
594                 public Let (QueryBlock block, RangeVariable identifier, Expression expr, Location loc)
595                         : base (block, identifier, expr, loc)
596                 {
597                 }
598
599                 protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
600                 {
601                         expr = CreateRangeVariableType (ec, parameter, identifier, expr);
602                         base.CreateArguments (ec, parameter, ref args);
603                 }
604
605                 protected override string MethodName {
606                         get { return "Select"; }
607                 }
608                 
609                 public override object Accept (StructuralVisitor visitor)
610                 {
611                         return visitor.Visit (this);
612                 }
613         }
614
615         public class Select : AQueryClause
616         {
617                 public Select (QueryBlock block, Expression expr, Location loc)
618                         : base (block, expr, loc)
619                 {
620                 }
621                 
622                 //
623                 // For queries like `from a orderby a select a'
624                 // the projection is transparent and select clause can be safely removed 
625                 //
626                 public bool IsRequired (Parameter parameter)
627                 {
628                         SimpleName sn = expr as SimpleName;
629                         if (sn == null)
630                                 return true;
631
632                         return sn.Name != parameter.Name;
633                 }
634
635                 protected override string MethodName {
636                         get { return "Select"; }
637                 }
638                 
639                 public override object Accept (StructuralVisitor visitor)
640                 {
641                         return visitor.Visit (this);
642                 }
643
644         }
645
646         public class SelectMany : ARangeVariableQueryClause
647         {
648                 public SelectMany (QueryBlock block, RangeVariable identifier, Expression expr, Location loc)
649                         : base (block, identifier, expr, loc)
650                 {
651                 }
652
653                 protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args)
654                 {
655                         if (args == null) {
656                                 if (IdentifierType != null)
657                                         expr = CreateCastExpression (expr);
658
659                                 base.CreateArguments (ec, parameter.Clone (), ref args);
660                         }
661
662                         Expression result_selector_expr;
663                         QueryBlock result_block;
664
665                         var target = GetIntoVariable ();
666                         var target_param = new ImplicitLambdaParameter (target.Name, target.Location);
667
668                         //
669                         // When select follows use it as a result selector
670                         //
671                         if (next is Select) {
672                                 result_selector_expr = next.Expr;
673
674                                 result_block = next.block;
675                                 result_block.SetParameters (parameter, target_param);
676
677                                 next = next.next;
678                         } else {
679                                 result_selector_expr = CreateRangeVariableType (ec, parameter, target, new SimpleName (target.Name, target.Location));
680
681                                 result_block = new QueryBlock (block.Parent, block.StartLocation);
682                                 result_block.SetParameters (parameter, target_param);
683                         }
684
685                         LambdaExpression result_selector = new LambdaExpression (Location);
686                         result_selector.Block = result_block;
687                         result_selector.Block.AddStatement (new ContextualReturn (result_selector_expr));
688
689                         args.Add (new Argument (result_selector));
690                 }
691
692                 protected override string MethodName {
693                         get { return "SelectMany"; }
694                 }
695
696                 public override object Accept (StructuralVisitor visitor)
697                 {
698                         return visitor.Visit (this);
699                 }
700         }
701
702         public class Where : AQueryClause
703         {
704                 public Where (QueryBlock block, Expression expr, Location loc)
705                         : base (block, expr, loc)
706                 {
707                 }
708
709                 protected override string MethodName {
710                         get { return "Where"; }
711                 }
712
713                 public override object Accept (StructuralVisitor visitor)
714                 {
715                         return visitor.Visit (this);
716                 }
717         }
718
719         public class OrderByAscending : AQueryClause
720         {
721                 public OrderByAscending (QueryBlock block, Expression expr)
722                         : base (block, expr, expr.Location)
723                 {
724                 }
725
726                 protected override string MethodName {
727                         get { return "OrderBy"; }
728                 }
729
730                 public override object Accept (StructuralVisitor visitor)
731                 {
732                         return visitor.Visit (this);
733                 }
734         }
735
736         public class OrderByDescending : AQueryClause
737         {
738                 public OrderByDescending (QueryBlock block, Expression expr)
739                         : base (block, expr, expr.Location)
740                 {
741                 }
742
743                 protected override string MethodName {
744                         get { return "OrderByDescending"; }
745                 }
746
747                 public override object Accept (StructuralVisitor visitor)
748                 {
749                         return visitor.Visit (this);
750                 }
751         }
752
753         public class ThenByAscending : OrderByAscending
754         {
755                 public ThenByAscending (QueryBlock block, Expression expr)
756                         : base (block, expr)
757                 {
758                 }
759
760                 protected override string MethodName {
761                         get { return "ThenBy"; }
762                 }
763
764                 public override object Accept (StructuralVisitor visitor)
765                 {
766                         return visitor.Visit (this);
767                 }
768         }
769
770         public class ThenByDescending : OrderByDescending
771         {
772                 public ThenByDescending (QueryBlock block, Expression expr)
773                         : base (block, expr)
774                 {
775                 }
776
777                 protected override string MethodName {
778                         get { return "ThenByDescending"; }
779                 }
780
781                 public override object Accept (StructuralVisitor visitor)
782                 {
783                         return visitor.Visit (this);
784                 }
785         }
786
787         //
788         // Implicit query block
789         //
790         public class QueryBlock : ParametersBlock
791         {
792                 //
793                 // Transparent parameters are used to package up the intermediate results
794                 // and pass them onto next clause
795                 //
796                 public sealed class TransparentParameter : ImplicitLambdaParameter
797                 {
798                         public static int Counter;
799                         const string ParameterNamePrefix = "<>__TranspIdent";
800
801                         public readonly Parameter Parent;
802                         public readonly string Identifier;
803
804                         public TransparentParameter (Parameter parent, RangeVariable identifier)
805                                 : base (ParameterNamePrefix + Counter++, identifier.Location)
806                         {
807                                 Parent = parent;
808                                 Identifier = identifier.Name;
809                         }
810
811                         public static void Reset ()
812                         {
813                                 Counter = 0;
814                         }
815                 }
816
817                 public QueryBlock (Block parent, Location start)
818                         : base (parent, ParametersCompiled.EmptyReadOnlyParameters, start, Flags.CompilerGenerated)
819                 {
820                 }
821
822                 public void AddRangeVariable (RangeVariable variable)
823                 {
824                         variable.Block = this;
825                         TopBlock.AddLocalName (variable.Name, variable, true);
826                 }
827
828                 public override void Error_AlreadyDeclared (string name, INamedBlockVariable variable, string reason)
829                 {
830                         TopBlock.Report.Error (1931, variable.Location,
831                                 "A range variable `{0}' conflicts with a previous declaration of `{0}'",
832                                 name);
833                 }
834
835                 public override void Error_AlreadyDeclared (string name, INamedBlockVariable variable)
836                 {
837                         TopBlock.Report.Error (1930, variable.Location,
838                                 "A range variable `{0}' has already been declared in this scope",
839                                 name);          
840                 }
841
842                 public override void Error_AlreadyDeclaredTypeParameter (string name, Location loc)
843                 {
844                         TopBlock.Report.Error (1948, loc,
845                                 "A range variable `{0}' conflicts with a method type parameter",
846                                 name);
847                 }
848
849                 public void SetParameter (Parameter parameter)
850                 {
851                         base.parameters = new ParametersCompiled (parameter);
852                         base.parameter_info = new ParameterInfo[] {
853                                 new ParameterInfo (this, 0)
854                         };
855                 }
856
857                 public void SetParameters (Parameter first, Parameter second)
858                 {
859                         base.parameters = new ParametersCompiled (first, second);
860                         base.parameter_info = new ParameterInfo[] {
861                                 new ParameterInfo (this, 0),
862                                 new ParameterInfo (this, 1)
863                         };
864                 }
865         }
866
867         sealed class TransparentMemberAccess : MemberAccess
868         {
869                 public TransparentMemberAccess (Expression expr, string name)
870                         : base (expr, name)
871                 {
872                 }
873
874                 public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
875                 {
876                         rc.Report.Error (1947, loc,
877                                 "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value",
878                                 Name);
879
880                         return null;
881                 }
882         }
883 }