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