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