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