importing messaging-2008 branch to trunk.
[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 //
10
11 using System;
12 using System.Reflection;
13 using System.Collections;
14
15 namespace Mono.CSharp.Linq
16 {
17         // NOTES:
18         // Expression should be IExpression to save some memory and make a few things
19         // easier to read
20         //
21         //
22
23         public class QueryExpression : AQueryClause
24         {
25                 LocatedToken variable;
26
27                 public QueryExpression (LocatedToken variable, AQueryClause query)
28                         : base (null, query.Location)
29                 {
30                         this.variable = variable;
31                         this.next = query;
32                 }
33
34                 public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parentParameter, TransparentIdentifiersScope ti)
35                 {
36                         Parameter p = CreateBlockParameter (variable);
37                         return next.BuildQueryClause (ec, lSide, p, ti);
38                 }
39
40                 public override Expression DoResolve (EmitContext ec)
41                 {
42                         int counter = TransparentParameter.Counter;
43
44                         Expression e = BuildQueryClause (ec, null, null, null);
45                         e = e.Resolve (ec);
46
47                         //
48                         // Reset counter in probing mode to ensure that all transparent
49                         // identifier anonymous types are created only once
50                         //
51                         if (ec.IsInProbingMode)
52                                 TransparentParameter.Counter = counter;
53
54                         return e;
55                 }
56
57                 protected override string MethodName {
58                         get { throw new NotSupportedException (); }
59                 }
60         }
61
62         public abstract class AQueryClause : Expression
63         {
64                 class QueryExpressionAccess : MemberAccess
65                 {
66                         public QueryExpressionAccess (Expression expr, string methodName, Location loc)
67                                 : base (expr, methodName, loc)
68                         {
69                         }
70
71                         public QueryExpressionAccess (Expression expr, string methodName, TypeArguments typeArguments, Location loc)
72                                 : base (expr, methodName, typeArguments, loc)
73                         {
74                         }
75
76                         protected override Expression Error_MemberLookupFailed (Type container_type, Type qualifier_type,
77                                 Type queried_type, string name, string class_name, MemberTypes mt, BindingFlags bf)
78                         {
79                                 Report.Error (1935, loc, "An implementation of `{0}' query expression pattern could not be found. " +
80                                         "Are you missing `System.Linq' using directive or `System.Core.dll' assembly reference?",
81                                         name);
82                                 return null;
83                         }
84                 }
85
86                 class QueryExpressionInvocation : Invocation, MethodGroupExpr.IErrorHandler
87                 {
88                         public QueryExpressionInvocation (QueryExpressionAccess expr, ArrayList arguments)
89                                 : base (expr, arguments)
90                         {
91                         }
92
93                         protected override MethodGroupExpr DoResolveOverload (EmitContext ec)
94                         {
95                                 mg.CustomErrorHandler = this;
96                                 MethodGroupExpr rmg = mg.OverloadResolve (ec, ref Arguments, false, loc);
97                                 return rmg;
98                         }
99
100                         public bool NoExactMatch (EmitContext ec, MethodBase method)
101                         {
102 #if GMCS_SOURCE                         
103                                 AParametersCollection pd = TypeManager.GetParameterData (method);
104                                 Type source_type = pd.ExtensionMethodType;
105                                 if (source_type != null) {
106                                         Argument a = (Argument) Arguments [0];
107
108                                         if (source_type.IsGenericType && source_type.ContainsGenericParameters) {
109                                                 TypeInferenceContext tic = new TypeInferenceContext (source_type.GetGenericArguments ());
110                                                 tic.OutputTypeInference (ec, a.Expr, source_type);
111                                                 if (tic.FixAllTypes ()) {
112                                                         source_type = source_type.GetGenericTypeDefinition ().MakeGenericType (tic.InferredTypeArguments);
113                                                 }
114                                         }
115
116                                         if (!Convert.ImplicitConversionExists (ec, a.Expr, source_type)) {
117                                                 Report.Error (1936, loc, "An implementation of `{0}' query expression pattern for source type `{1}' could not be found",
118                                                         mg.Name, TypeManager.CSharpName (a.Type));
119                                                 return true;
120                                         }
121                                 }
122
123                                 if (!method.IsGenericMethod)
124                                         return false;
125
126                                 Report.Error (1942, loc, "Type inference failed to infer type argument for `{0}' clause. " +
127                                         "Try specifying the type argument explicitly",
128                                         mg.Name.ToLower ());
129                                 return true;
130 #else
131                                 return false;
132 #endif
133                         }
134                 }
135
136                 public AQueryClause next;
137                 /*protected*/ public Expression expr;
138
139                 protected AQueryClause (Expression expr, Location loc)
140                 {
141                         this.expr = expr;
142                         this.loc = loc;
143                 }
144                 
145                 protected override void CloneTo (CloneContext clonectx, Expression target)
146                 {
147                         AQueryClause t = (AQueryClause) target;
148                         if (expr != null)
149                                 t.expr = expr.Clone (clonectx);
150                         
151                         if (next != null)
152                                 t.next = (AQueryClause)next.Clone (clonectx);
153                 }
154
155                 public override Expression CreateExpressionTree (EmitContext ec)
156                 {
157                         // Should not be reached
158                         throw new NotSupportedException ("ET");
159                 }
160
161                 public override Expression DoResolve (EmitContext ec)
162                 {
163                         return expr.DoResolve (ec);
164                 }
165
166                 public virtual Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
167                 {
168                         ArrayList args = new ArrayList (1);
169                         args.Add (CreateSelectorArgument (ec, expr, parameter, ti));
170                         lSide = CreateQueryExpression (lSide, args);
171                         if (next != null) {
172                                 Select s = next as Select;
173                                 if (s == null || s.IsRequired (parameter))
174                                         return next.BuildQueryClause (ec, lSide, parameter, ti);
175                                         
176                                 // Skip transparent select clause if any clause follows
177                                 if (next.next != null)
178                                         return next.next.BuildQueryClause (ec, lSide, parameter, ti);
179                         }
180
181                         return lSide;
182                 }
183
184                 protected static Parameter CreateBlockParameter (LocatedToken li)
185                 {
186                         return new ImplicitQueryParameter (li);
187                 }
188
189                 protected Invocation CreateQueryExpression (Expression lSide, ArrayList arguments)
190                 {
191                         return new QueryExpressionInvocation (
192                                 new QueryExpressionAccess (lSide, MethodName, loc), arguments);
193                 }
194
195                 protected Invocation CreateQueryExpression (Expression lSide, TypeArguments typeArguments, ArrayList arguments)
196                 {
197                         return new QueryExpressionInvocation (
198                                 new QueryExpressionAccess (lSide, MethodName, typeArguments, loc), arguments);
199                 }
200
201                 protected Argument CreateSelectorArgument (EmitContext ec, Expression expr, Parameter parameter, TransparentIdentifiersScope ti)
202                 {
203                         return CreateSelectorArgument (ec, expr, new Parameter [] { parameter }, ti);
204                 }
205
206                 protected Argument CreateSelectorArgument (EmitContext ec, Expression expr, Parameter[] parameters, TransparentIdentifiersScope ti)
207                 {
208                         Parameters p = new Parameters (parameters);
209
210                         LambdaExpression selector = new LambdaExpression (loc);
211                         selector.Block = new SelectorBlock (ec.CurrentBlock, p, ti, loc);
212                         selector.Block.AddStatement (new ContextualReturn (expr));
213
214                         return new Argument (selector);
215                 }
216
217                 public override void Emit (EmitContext ec)
218                 {
219                         throw new NotSupportedException ();
220                 }
221
222                 protected abstract string MethodName { get; }
223
224                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
225                 {
226                         // Nothing to mutate
227                 }
228
229                 public virtual AQueryClause Next {
230                         set {
231                                 next = value;
232                         }
233                 }
234
235                 public AQueryClause Tail {
236                         get {
237                                 return next == null ? this : next.Tail;
238                         }
239                 }
240         }
241
242         //
243         // A query clause with an identifier (range variable)
244         //
245         public abstract class ARangeVariableQueryClause : AQueryClause
246         {
247                 LocatedToken variable;
248                 protected Expression element_selector;
249
250                 protected ARangeVariableQueryClause (LocatedToken variable, Expression expr, Location loc)
251                         : base (expr, loc)
252                 {
253                         this.variable = variable;
254                 }
255
256                 protected virtual void AddSelectorArguments (EmitContext ec, ArrayList args, Parameter parentParameter,
257                         ref Parameter parameter, TransparentIdentifiersScope ti)
258                 {
259                         args.Add (CreateSelectorArgument (ec, expr, parentParameter, ti));
260                         args.Add (CreateSelectorArgument (ec, element_selector,
261                                 new Parameter [] { parentParameter, parameter }, ti));
262                 }
263
264                 //
265                 // Customization for range variables which not only creates a lambda expression but
266                 // also builds a chain of range varible pairs
267                 //
268                 public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parentParameter, TransparentIdentifiersScope ti)
269                 {
270                         Parameter parameter = CreateBlockParameter (variable);
271
272                         if (next != null) {
273                                 //
274                                 // Builds transparent identifiers, each identifier includes its parent
275                                 // type at index 0, and new value at index 1. This is not valid for the
276                                 // first one which includes two values directly.
277                                 //
278                                 ArrayList transp_args = new ArrayList (2);
279                                 transp_args.Add (new AnonymousTypeParameter (parentParameter));
280                                 transp_args.Add (CreateAnonymousTypeVariable (parameter));
281                                 element_selector = new AnonymousTypeDeclaration (transp_args, (TypeContainer) ec.TypeContainer, loc);
282                         }
283
284                         ArrayList args = new ArrayList ();
285                         AddSelectorArguments (ec, args, parentParameter, ref parameter, ti);
286
287                         lSide = CreateQueryExpression (lSide, args);
288                         if (next != null) {
289                                 //
290                                 // Parameter identifiers go to the scope
291                                 //
292                                 string[] identifiers;
293                                 if (ti == null) {
294                                         identifiers = new string [] { parentParameter.Name, parameter.Name };
295                                 } else {
296                                         identifiers = new string [] { parameter.Name };
297                                 }
298
299                                 TransparentParameter tp = new TransparentParameter (loc);
300                                 return next.BuildQueryClause (ec, lSide, tp,
301                                         new TransparentIdentifiersScope (ti, tp, identifiers));
302                         }
303
304                         return lSide;
305                 }
306                 
307                 protected override void CloneTo (CloneContext clonectx, Expression target)
308                 {
309                         ARangeVariableQueryClause t = (ARangeVariableQueryClause) target;
310                         if (element_selector != null)
311                                 t.element_selector = element_selector.Clone (clonectx);
312                         base.CloneTo (clonectx, t);
313                 }
314                 
315                 //
316                 // For transparent identifiers, creates an instance of variable expression
317                 //
318                 protected virtual AnonymousTypeParameter CreateAnonymousTypeVariable (Parameter parameter)
319                 {
320                         return new AnonymousTypeParameter (parameter);
321                 }
322         }
323
324         public class QueryStartClause : AQueryClause
325         {
326                 public QueryStartClause (Expression expr)
327                         : base (expr, expr.Location)
328                 {
329                 }
330
331                 public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
332                 {
333                         return next.BuildQueryClause (ec, expr, parameter, ti);
334                 }
335
336                 public override Expression DoResolve (EmitContext ec)
337                 {
338                         Expression e = BuildQueryClause (ec, null, null, null);
339                         return e.Resolve (ec);
340                 }
341
342                 protected override string MethodName {
343                         get { throw new NotSupportedException (); }
344                 }
345         }
346
347         public class Cast : QueryStartClause
348         {
349                 // We don't have to clone cast type
350                 readonly FullNamedExpression type_expr;
351
352                 public Cast (FullNamedExpression type, Expression expr)
353                         : base (expr)
354                 {
355                         this.type_expr = type;
356                 }
357                 
358                 public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
359                 {
360                         lSide = CreateQueryExpression (expr, new TypeArguments (type_expr), null);
361                         if (next != null)
362                                 return next.BuildQueryClause (ec, lSide, parameter, ti);
363
364                         return lSide;
365                 }
366
367                 protected override string MethodName {
368                         get { return "Cast"; }
369                 }
370         }
371
372         public class GroupBy : AQueryClause
373         {
374                 Expression element_selector;
375                 
376                 public GroupBy (Expression elementSelector, Expression keySelector, Location loc)
377                         : base (keySelector, loc)
378                 {
379                         this.element_selector = elementSelector;
380                 }
381
382                 public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
383                 {
384                         ArrayList args = new ArrayList (2);
385                         args.Add (CreateSelectorArgument (ec, expr, parameter, ti));
386
387                         // A query can be optimized when selector is not group by specific
388                         if (!element_selector.Equals (lSide))
389                                 args.Add (CreateSelectorArgument (ec, element_selector, parameter, ti));
390
391                         lSide = CreateQueryExpression (lSide, args);
392                         if (next != null)
393                                 return next.BuildQueryClause (ec, lSide, parameter, ti);
394
395                         return lSide;
396                 }
397         
398                 protected override void CloneTo (CloneContext clonectx, Expression target)
399                 {
400                         GroupBy t = (GroupBy) target;
401                         t.element_selector = element_selector.Clone (clonectx);
402                         base.CloneTo (clonectx, t);
403                 }
404
405                 protected override string MethodName {
406                         get { return "GroupBy"; }
407                 }
408         }
409
410         public class Join : ARangeVariableQueryClause
411         {
412                 Expression projection;
413                 Expression inner_selector, outer_selector;
414
415                 public Join (LocatedToken variable, Expression inner, Expression outerSelector, Expression innerSelector, Location loc)
416                         : base (variable, inner, loc)
417                 {
418                         this.outer_selector = outerSelector;
419                         this.inner_selector = innerSelector;
420                 }
421
422                 protected override void AddSelectorArguments (EmitContext ec, ArrayList args, Parameter parentParameter,
423                         ref Parameter parameter, TransparentIdentifiersScope ti)
424                 {
425                         args.Add (new Argument (expr));
426                         args.Add (CreateSelectorArgument (ec, outer_selector, parentParameter, ti));
427                         args.Add (CreateSelectorArgument (ec, inner_selector, parameter, ti));
428
429                         parameter = CreateResultSelectorParameter (parameter);
430                         if (projection == null) {
431                                 ArrayList join_args = new ArrayList (2);
432                                 join_args.Add (new AnonymousTypeParameter (parentParameter));
433                                 join_args.Add (new AnonymousTypeParameter (parameter));
434                                 projection = new AnonymousTypeDeclaration (join_args, (TypeContainer) ec.TypeContainer, loc);
435                         }
436
437                         args.Add (CreateSelectorArgument (ec, projection,
438                                 new Parameter [] { parentParameter, parameter }, ti));
439                 }
440         
441                 protected override void CloneTo (CloneContext clonectx, Expression target)
442                 {
443                         Join t = (Join) target;
444                         t.projection = projection.Clone (clonectx);
445                         t.inner_selector = inner_selector.Clone (clonectx);
446                         t.outer_selector = outer_selector.Clone (clonectx);
447                         base.CloneTo (clonectx, t);
448                 }       
449
450                 protected virtual Parameter CreateResultSelectorParameter (Parameter parameter)
451                 {
452                         return parameter;
453                 }
454
455                 public override AQueryClause Next {
456                         set {
457                                 // Use select as join projection
458                                 if (value is Select) {
459                                         projection = value.expr;
460                                         next = value.next;
461                                         return;
462                                 }
463
464                                 base.Next = value;
465                         }
466                 }
467
468                 protected override string MethodName {
469                         get { return "Join"; }
470                 }
471         }
472
473         public class GroupJoin : Join
474         {
475                 readonly LocatedToken into_variable;
476
477                 public GroupJoin (LocatedToken variable, Expression inner, Expression outerSelector, Expression innerSelector,
478                         LocatedToken into, Location loc)
479                         : base (variable, inner, outerSelector, innerSelector, loc)
480                 {
481                         this.into_variable = into;
482                 }
483
484                 protected override Parameter CreateResultSelectorParameter (Parameter parameter)
485                 {
486                         //
487                         // into variable is used as result selector and it's passed as
488                         // transparent identifiers to the next clause
489                         //
490                         return CreateBlockParameter (into_variable);
491                 }
492
493                 protected override string MethodName {
494                         get { return "GroupJoin"; }
495                 }
496         }
497
498         public class Let : ARangeVariableQueryClause
499         {
500                 class RangeAnonymousTypeParameter : AnonymousTypeParameter
501                 {
502                         readonly Parameter parameter;
503
504                         public RangeAnonymousTypeParameter (Expression initializer, Parameter parameter)
505                                 : base (initializer, parameter.Name, parameter.Location)
506                         {
507                                 this.parameter = parameter;
508                         }
509
510                         public override Expression DoResolve (EmitContext ec)
511                         {
512                                 Expression e = base.DoResolve (ec);
513                                 if (e != null) {
514                                         //
515                                         // Spread resolved initializer type
516                                         //
517                                         ((ImplicitLambdaParameter) parameter).Type = type;
518                                 }
519
520                                 return e;
521                         }
522
523                         protected override void Error_InvalidInitializer (string initializer)
524                         {
525                                 Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'",
526                                         Name, initializer);
527                         }                       
528                 }
529
530                 public Let (LocatedToken variable, Expression expr, Location loc)
531                         : base (variable, expr, loc)
532                 {
533                 }
534
535                 protected override void AddSelectorArguments (EmitContext ec, ArrayList args, Parameter parentParameter,
536                         ref Parameter parameter, TransparentIdentifiersScope ti)
537                 {
538                         args.Add (CreateSelectorArgument (ec, element_selector, parentParameter, ti));
539                 }
540
541                 protected override AnonymousTypeParameter CreateAnonymousTypeVariable (Parameter parameter)
542                 {
543                         return new RangeAnonymousTypeParameter (expr, parameter);
544                 }
545
546                 protected override string MethodName {
547                         get { return "Select"; }
548                 }
549         }
550
551         public class Select : AQueryClause
552         {
553                 public Select (Expression expr, Location loc)
554                         : base (expr, loc)
555                 {
556                 }
557                 
558                 //
559                 // For queries like `from a orderby a select a'
560                 // the projection is transparent and select clause can be safely removed 
561                 //
562                 public bool IsRequired (Parameter parameter)
563                 {
564                         SimpleName sn = expr as SimpleName;
565                         if (sn == null)
566                                 return true;
567
568                         return sn.Name != parameter.Name;
569                 }
570
571                 protected override string MethodName {
572                         get { return "Select"; }
573                 }
574         }
575
576         public class SelectMany : ARangeVariableQueryClause
577         {
578                 public SelectMany (LocatedToken variable, Expression expr)
579                         : base (variable, expr, expr.Location)
580                 {
581                 }
582
583                 protected override string MethodName {
584                         get { return "SelectMany"; }
585                 }
586
587                 public override AQueryClause Next {
588                         set {
589                                 element_selector = value.expr;
590
591                                 // Can be optimized as SelectMany element selector
592                                 if (value is Select)
593                                         return;
594
595                                 next = value;
596                         }
597                 }
598         }
599
600         public class Where : AQueryClause
601         {
602                 public Where (Expression expr, Location loc)
603                         : base (expr, loc)
604                 {
605                 }
606
607                 protected override string MethodName {
608                         get { return "Where"; }
609                 }
610         }
611
612         public class OrderByAscending : AQueryClause
613         {
614                 public OrderByAscending (Expression expr)
615                         : base (expr, expr.Location)
616                 {
617                 }
618
619                 protected override string MethodName {
620                         get { return "OrderBy"; }
621                 }
622         }
623
624         public class OrderByDescending : AQueryClause
625         {
626                 public OrderByDescending (Expression expr)
627                         : base (expr, expr.Location)
628                 {
629                 }
630
631                 protected override string MethodName {
632                         get { return "OrderByDescending"; }
633                 }
634         }
635
636         public class ThenByAscending : OrderByAscending
637         {
638                 public ThenByAscending (Expression expr)
639                         : base (expr)
640                 {
641                 }
642
643                 protected override string MethodName {
644                         get { return "ThenBy"; }
645                 }
646         }
647
648         public class ThenByDescending : OrderByDescending
649         {
650                 public ThenByDescending (Expression expr)
651                         : base (expr)
652                 {
653                 }
654
655                 protected override string MethodName {
656                         get { return "ThenByDescending"; }
657                 }
658         }
659
660         class ImplicitQueryParameter : ImplicitLambdaParameter
661         {
662                 public sealed class ImplicitType : Expression
663                 {
664                         public static ImplicitType Instance = new ImplicitType ();
665
666                         private ImplicitType ()
667                         {
668                         }
669
670                         protected override void CloneTo (CloneContext clonectx, Expression target)
671                         {
672                                 // Nothing to clone
673                         }
674
675                         public override Expression CreateExpressionTree (EmitContext ec)
676                         {
677                                 throw new NotSupportedException ();
678                         }
679
680                         public override Expression DoResolve (EmitContext ec)
681                         {
682                                 throw new NotSupportedException ();
683                         }
684
685                         public override void Emit (EmitContext ec)
686                         {
687                                 throw new NotSupportedException ();
688                         }
689
690                         public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
691                         {
692                                 throw new NotSupportedException ();
693                         }
694                 }
695
696                 public ImplicitQueryParameter (LocatedToken variable)
697                         : base (variable.Value, variable.Location)
698                 {
699                 }
700         }
701
702         //
703         // Transparent parameters are used to package up the intermediate results
704         // and pass them onto next clause
705         //
706         public class TransparentParameter : ImplicitLambdaParameter
707         {
708                 public static int Counter;
709                 const string ParameterNamePrefix = "<>__TranspIdent";
710
711                 public TransparentParameter (Location loc)
712                         : base (ParameterNamePrefix + Counter++, loc)
713                 {
714                 }
715         }
716
717         //
718         // Transparent identifiers are stored in nested anonymous types, each type can contain
719         // up to 2 identifiers or 1 identifier and parent type.
720         //
721         public class TransparentIdentifiersScope
722         {
723                 readonly string [] identifiers;
724                 readonly TransparentIdentifiersScope parent;
725                 readonly TransparentParameter parameter;
726
727                 public TransparentIdentifiersScope (TransparentIdentifiersScope parent,
728                         TransparentParameter parameter, string [] identifiers)
729                 {
730                         this.parent = parent;
731                         this.parameter = parameter;
732                         this.identifiers = identifiers;
733                 }
734
735                 public MemberAccess GetIdentifier (string name)
736                 {
737                         TransparentIdentifiersScope ident = FindIdentifier (name);
738                         if (ident == null)
739                                 return null;
740
741                         return new MemberAccess (CreateIdentifierNestingExpression (ident), name);
742                 }
743
744                 TransparentIdentifiersScope FindIdentifier (string name)
745                 {
746                         foreach (string s in identifiers) {
747                                 if (s == name)
748                                         return this;
749                         }
750
751                         if (parent == null)
752                                 return null;
753
754                         return parent.FindIdentifier (name);
755                 }
756
757                 Expression CreateIdentifierNestingExpression (TransparentIdentifiersScope end)
758                 {
759                         Expression expr = new SimpleName (parameter.Name, parameter.Location);
760                         TransparentIdentifiersScope current = this;
761                         while (current != end)
762                         {
763                                 current = current.parent;
764                                 expr = new MemberAccess (expr, current.parameter.Name);
765                         }
766
767                         return expr;
768                 }
769         }
770
771         //
772         // Lambda expression block which contains transparent identifiers
773         //
774         class SelectorBlock : ToplevelBlock
775         {
776                 readonly TransparentIdentifiersScope transparent_identifiers;
777
778                 public SelectorBlock (Block block, Parameters parameters, 
779                         TransparentIdentifiersScope transparentIdentifiers, Location loc)
780                         : base (block, parameters, loc)
781                 {
782                         this.transparent_identifiers = transparentIdentifiers;
783                 }
784
785                 public override Expression GetTransparentIdentifier (string name)
786                 {
787                         Expression expr = null;
788                         if (transparent_identifiers != null)
789                                 expr = transparent_identifiers.GetIdentifier (name);
790
791                         if (expr != null || Container == null)
792                                 return expr;
793                         
794                         return Container.GetTransparentIdentifier (name);
795                 }
796         }
797
798         //
799         // This block is actually never used, it is used by parser only
800         //
801         public class QueryBlock : ExplicitBlock
802         {
803                 public QueryBlock (Block parent, Location start)
804                         : base (parent, start, Location.Null)
805                 {
806                         range_variables = new System.Collections.Specialized.HybridDictionary ();
807                 }
808
809                 protected override void AddVariable (LocalInfo li)
810                 {
811                         string name = li.Name;
812                         if (range_variables.Contains (name)) {
813                                 LocalInfo conflict = (LocalInfo) range_variables [name];
814                                 Report.SymbolRelatedToPreviousError (conflict.Location, name);
815                                 Error_AlreadyDeclared (li.Location, name);
816                                 return;
817                         }
818
819                         range_variables.Add (name, li);
820                         Explicit.AddKnownVariable (name, li);
821                 }
822                 
823                 protected override void Error_AlreadyDeclared (Location loc, string var, string reason)
824                 {
825                         Report.Error (1931, loc, "A range variable `{0}' conflicts with a previous declaration of `{0}'",
826                                 var);
827                 }
828                 
829                 protected override void Error_AlreadyDeclared (Location loc, string var)
830                 {
831                         Report.Error (1930, loc, "A range variable `{0}' has already been declared in this scope",
832                                 var);           
833                 }
834                 
835                 protected override void Error_AlreadyDeclaredTypeParameter (Location loc, string name)
836                 {
837                         Report.Error (1948, loc, "A range variable `{0}' conflicts with a method type parameter",
838                                 name);
839                 }
840         }
841 }