New tests.
[mono.git] / mcs / mcs / linq.cs
index b77a0b6bdab136888f2176870657368c8ac4c9e5..420dae4bf832e7c4fcc18125e7c51c3f31bb855b 100644 (file)
@@ -10,7 +10,7 @@
 
 using System;
 using System.Reflection;
-using System.Collections;
+using System.Collections.Generic;
 
 namespace Mono.CSharp.Linq
 {
@@ -28,17 +28,18 @@ namespace Mono.CSharp.Linq
                        this.next = query;
                }
 
-               public override Expression BuildQueryClause (EmitContext ec, Expression lSide)
+               public override Expression BuildQueryClause (ResolveContext ec, Expression lSide)
                {
                        return next.BuildQueryClause (ec, lSide);
                }
 
-               public override Expression DoResolve (EmitContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        int counter = QueryBlock.TransparentParameter.Counter;
 
                        Expression e = BuildQueryClause (ec, null);
-                       e = e.Resolve (ec);
+                       if (e != null)
+                               e = e.Resolve (ec);
 
                        //
                        // Reset counter in probing mode to ensure that all transparent
@@ -55,7 +56,7 @@ namespace Mono.CSharp.Linq
                }
        }
 
-       abstract class AQueryClause : Expression
+       abstract class AQueryClause : ShimExpression
        {
                class QueryExpressionAccess : MemberAccess
                {
@@ -69,10 +70,10 @@ namespace Mono.CSharp.Linq
                        {
                        }
 
-                       protected override Expression Error_MemberLookupFailed (Type container_type, Type qualifier_type,
-                               Type queried_type, string name, string class_name, MemberTypes mt, BindingFlags bf)
+                       protected override Expression Error_MemberLookupFailed (ResolveContext ec, TypeSpec container_type, TypeSpec qualifier_type,
+                               TypeSpec queried_type, string name, int arity, string class_name, MemberKind mt, BindingRestriction bf)
                        {
-                               Report.Error (1935, loc, "An implementation of `{0}' query expression pattern could not be found. " +
+                               ec.Report.Error (1935, loc, "An implementation of `{0}' query expression pattern could not be found. " +
                                        "Are you missing `System.Linq' using directive or `System.Core.dll' assembly reference?",
                                        name);
                                return null;
@@ -81,86 +82,82 @@ namespace Mono.CSharp.Linq
 
                class QueryExpressionInvocation : Invocation, MethodGroupExpr.IErrorHandler
                {
-                       public QueryExpressionInvocation (QueryExpressionAccess expr, ArrayList arguments)
+                       public QueryExpressionInvocation (QueryExpressionAccess expr, Arguments arguments)
                                : base (expr, arguments)
                        {
                        }
 
-                       protected override MethodGroupExpr DoResolveOverload (EmitContext ec)
+                       protected override MethodGroupExpr DoResolveOverload (ResolveContext ec)
                        {
                                mg.CustomErrorHandler = this;
-                               MethodGroupExpr rmg = mg.OverloadResolve (ec, ref Arguments, false, loc);
+                               MethodGroupExpr rmg = mg.OverloadResolve (ec, ref arguments, false, loc);
                                return rmg;
                        }
 
-                       public bool AmbiguousCall (MethodBase ambiguous)
+                       public bool AmbiguousCall (ResolveContext ec, MethodSpec ambiguous)
                        {
-                               Report.SymbolRelatedToPreviousError ((MethodInfo) mg);
-                               Report.SymbolRelatedToPreviousError (ambiguous);
-                               Report.Error (1940, loc, "Ambiguous implementation of the query pattern `{0}' for source type `{1}'",
+                               ec.Report.SymbolRelatedToPreviousError (mg.BestCandidate);
+                               ec.Report.SymbolRelatedToPreviousError (ambiguous);
+                               ec.Report.Error (1940, loc, "Ambiguous implementation of the query pattern `{0}' for source type `{1}'",
                                        mg.Name, mg.InstanceExpression.GetSignatureForError ());
                                return true;
                        }
 
-                       public bool NoExactMatch (EmitContext ec, MethodBase method)
+                       public bool NoExactMatch (ResolveContext ec, MethodSpec method)
                        {
-#if GMCS_SOURCE                                
-                               AParametersCollection pd = TypeManager.GetParameterData (method);
-                               Type source_type = pd.ExtensionMethodType;
+                               var pd = method.Parameters;
+                               TypeSpec source_type = pd.ExtensionMethodType;
                                if (source_type != null) {
-                                       Argument a = (Argument) Arguments [0];
+                                       Argument a = arguments [0];
 
-                                       if (source_type.IsGenericType && source_type.ContainsGenericParameters) {
-                                               TypeInferenceContext tic = new TypeInferenceContext (source_type.GetGenericArguments ());
+                                       if (TypeManager.IsGenericType (source_type) && TypeManager.ContainsGenericParameters (source_type)) {
+                                               TypeInferenceContext tic = new TypeInferenceContext (source_type.TypeArguments);
                                                tic.OutputTypeInference (ec, a.Expr, source_type);
-                                               if (tic.FixAllTypes ()) {
-                                                       source_type = source_type.GetGenericTypeDefinition ().MakeGenericType (tic.InferredTypeArguments);
+                                               if (tic.FixAllTypes (ec)) {
+                                                       source_type = source_type.GetDefinition ().MakeGenericType (tic.InferredTypeArguments);
                                                }
                                        }
 
                                        if (!Convert.ImplicitConversionExists (ec, a.Expr, source_type)) {
-                                               Report.Error (1936, loc, "An implementation of `{0}' query expression pattern for source type `{1}' could not be found",
+                                               ec.Report.Error (1936, loc, "An implementation of `{0}' query expression pattern for source type `{1}' could not be found",
                                                        mg.Name, TypeManager.CSharpName (a.Type));
                                                return true;
                                        }
                                }
 
-                               if (!method.IsGenericMethod)
+                               if (!method.IsGeneric)
                                        return false;
 
                                if (mg.Name == "SelectMany") {
-                                       Report.Error (1943, loc,
+                                       ec.Report.Error (1943, loc,
                                                "An expression type is incorrect in a subsequent `from' clause in a query expression with source type `{0}'",
-                                               ((Argument) Arguments [0]).GetSignatureForError ());
+                                               arguments [0].GetSignatureForError ());
                                } else {
-                                       Report.Error (1942, loc,
+                                       ec.Report.Error (1942, loc,
                                                "An expression type in `{0}' clause is incorrect. Type inference failed in the call to `{1}'",
                                                mg.Name.ToLower (), mg.Name);
                                }
+
                                return true;
-#else
-                               return false;
-#endif
                        }
                }
 
                // TODO: protected
                public AQueryClause next;
-               public Expression expr;
                protected ToplevelBlock block;
 
                protected AQueryClause (ToplevelBlock block, Expression expr, Location loc)
+                        : base (expr)
                {
                        this.block = block;
-                       this.expr = expr;
                        this.loc = loc;
                }
                
                protected override void CloneTo (CloneContext clonectx, Expression target)
                {
+                       base.CloneTo (clonectx, target);
+
                        AQueryClause t = (AQueryClause) target;
-                       if (expr != null)
-                               t.expr = expr.Clone (clonectx);
 
                        if (block != null)
                                t.block = (ToplevelBlock) block.Clone (clonectx);
@@ -169,20 +166,14 @@ namespace Mono.CSharp.Linq
                                t.next = (AQueryClause) next.Clone (clonectx);
                }
 
-               public override Expression CreateExpressionTree (EmitContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
-                       // Should not be reached
-                       throw new NotSupportedException ("ET");
+                       return expr.Resolve (ec);
                }
 
-               public override Expression DoResolve (EmitContext ec)
+               public virtual Expression BuildQueryClause (ResolveContext ec, Expression lSide)
                {
-                       return expr.DoResolve (ec);
-               }
-
-               public virtual Expression BuildQueryClause (EmitContext ec, Expression lSide)
-               {
-                       ArrayList args;
+                       Arguments args;
                        CreateArguments (ec, out args);
                        lSide = CreateQueryExpression (lSide, args);
                        if (next != null) {
@@ -198,9 +189,9 @@ namespace Mono.CSharp.Linq
                        return lSide;
                }
 
-               protected virtual void CreateArguments (EmitContext ec, out ArrayList args)
+               protected virtual void CreateArguments (ResolveContext ec, out Arguments args)
                {
-                       args = new ArrayList (2);
+                       args = new Arguments (2);
 
                        LambdaExpression selector = new LambdaExpression (loc);
                        selector.Block = block;
@@ -209,30 +200,20 @@ namespace Mono.CSharp.Linq
                        args.Add (new Argument (selector));
                }
 
-               protected Invocation CreateQueryExpression (Expression lSide, ArrayList arguments)
+               protected Invocation CreateQueryExpression (Expression lSide, Arguments arguments)
                {
                        return new QueryExpressionInvocation (
                                new QueryExpressionAccess (lSide, MethodName, loc), arguments);
                }
 
-               protected Invocation CreateQueryExpression (Expression lSide, TypeArguments typeArguments, ArrayList arguments)
+               protected Invocation CreateQueryExpression (Expression lSide, TypeArguments typeArguments, Arguments arguments)
                {
                        return new QueryExpressionInvocation (
                                new QueryExpressionAccess (lSide, MethodName, typeArguments, loc), arguments);
                }
 
-               public override void Emit (EmitContext ec)
-               {
-                       throw new NotSupportedException ();
-               }
-
                protected abstract string MethodName { get; }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       // Nothing to mutate
-               }
-
                public virtual AQueryClause Next {
                        set {
                                next = value;
@@ -253,14 +234,14 @@ namespace Mono.CSharp.Linq
        {
                sealed class RangeAnonymousTypeParameter : AnonymousTypeParameter
                {
-                       public RangeAnonymousTypeParameter (Expression initializer, LocatedToken parameter)
+                       public RangeAnonymousTypeParameter (Expression initializer, SimpleMemberName parameter)
                                : base (initializer, parameter.Value, parameter.Location)
                        {
                        }
 
-                       protected override void Error_InvalidInitializer (string initializer)
+                       protected override void Error_InvalidInitializer (ResolveContext ec, string initializer)
                        {
-                               Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'",
+                               ec.Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'",
                                        Name, initializer);
                        }
                }
@@ -270,12 +251,12 @@ namespace Mono.CSharp.Linq
                {
                }
 
-               protected static Expression CreateRangeVariableType (ToplevelBlock block, TypeContainer container, LocatedToken name, Expression init)
+               protected static Expression CreateRangeVariableType (ToplevelBlock block, TypeContainer container, SimpleMemberName name, Expression init)
                {
-                       ArrayList args = new ArrayList (2);
+                       var args = new List<AnonymousTypeParameter> (2);
                        args.Add (new AnonymousTypeParameter (block.Parameters [0]));
                        args.Add (new RangeAnonymousTypeParameter (init, name));
-                       return new AnonymousTypeDeclaration (args, container, name.Location);
+                       return new NewAnonymousType (args, container, name.Location);
                }
        }
 
@@ -286,12 +267,23 @@ namespace Mono.CSharp.Linq
                {
                }
 
-               public override Expression BuildQueryClause (EmitContext ec, Expression lSide)
+               public override Expression BuildQueryClause (ResolveContext ec, Expression lSide)
                {
+                       expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return null;
+
+                       if (expr.Type == InternalType.Dynamic || expr.Type == TypeManager.void_type) {
+                               ec.Report.Error (1979, expr.Location,
+                                       "Query expression with a source or join sequence of type `{0}' is not allowed",
+                                       TypeManager.CSharpName (expr.Type));
+                               return null;
+                       }
+
                        return next.BuildQueryClause (ec, expr);
                }
 
-               public override Expression DoResolve (EmitContext ec)
+               protected override Expression DoResolve (ResolveContext ec)
                {
                        Expression e = BuildQueryClause (ec, null);
                        return e.Resolve (ec);
@@ -313,7 +305,7 @@ namespace Mono.CSharp.Linq
                        this.type_expr = type;
                }
                
-               public override Expression BuildQueryClause (EmitContext ec, Expression lSide)
+               public override Expression BuildQueryClause (ResolveContext ec, Expression lSide)
                {
                        lSide = CreateQueryExpression (expr, new TypeArguments (type_expr), null);
                        if (next != null)
@@ -344,7 +336,7 @@ namespace Mono.CSharp.Linq
                        }
                }
 
-               protected override void CreateArguments (EmitContext ec, out ArrayList args)
+               protected override void CreateArguments (ResolveContext ec, out Arguments args)
                {
                        base.CreateArguments (ec, out args);
 
@@ -374,10 +366,10 @@ namespace Mono.CSharp.Linq
 
        class Join : ARangeVariableQueryClause
        {
-               readonly LocatedToken lt;
+               readonly SimpleMemberName lt;
                ToplevelBlock inner_selector, outer_selector;
 
-               public Join (ToplevelBlock block, LocatedToken lt, Expression inner, ToplevelBlock outerSelector, ToplevelBlock innerSelector, Location loc)
+               public Join (ToplevelBlock block, SimpleMemberName lt, Expression inner, ToplevelBlock outerSelector, ToplevelBlock innerSelector, Location loc)
                        : base (block, inner)
                {
                        this.lt = lt;
@@ -385,9 +377,9 @@ namespace Mono.CSharp.Linq
                        this.inner_selector = innerSelector;
                }
 
-               protected override void CreateArguments (EmitContext ec, out ArrayList args)
+               protected override void CreateArguments (ResolveContext ec, out Arguments args)
                {
-                       args = new ArrayList (4);
+                       args = new Arguments (4);
 
                        args.Add (new Argument (expr));
 
@@ -400,26 +392,26 @@ namespace Mono.CSharp.Linq
                        args.Add (new Argument (lambda));
 
                        Expression result_selector_expr;
-                       LocatedToken into_variable = GetIntoVariable ();
+                       SimpleMemberName into_variable = GetIntoVariable ();
                        //
                        // When select follows use is as result selector
                        //
                        if (next is Select) {
-                               result_selector_expr = next.expr;
+                               result_selector_expr = next.Expr;
                                next = next.next;
                        } else {
-                               result_selector_expr = CreateRangeVariableType (block, (TypeContainer) ec.TypeContainer, into_variable,
+                               result_selector_expr = CreateRangeVariableType (block, ec.MemberContext.CurrentMemberDefinition.Parent, into_variable,
                                        new SimpleName (into_variable.Value, into_variable.Location));
                        }
 
                        LambdaExpression result_selector = new LambdaExpression (lt.Location);
-                       result_selector.Block = new QueryBlock (block.Parent, block.Parameters, into_variable, block.StartLocation);
+                       result_selector.Block = new QueryBlock (ec.Compiler, block.Parent, block.Parameters, into_variable, block.StartLocation);
                        result_selector.Block.AddStatement (new ContextualReturn (result_selector_expr));
 
                        args.Add (new Argument (result_selector));
                }
 
-               protected virtual LocatedToken GetIntoVariable ()
+               protected virtual SimpleMemberName GetIntoVariable ()
                {
                        return lt;
                }
@@ -439,16 +431,16 @@ namespace Mono.CSharp.Linq
 
        class GroupJoin : Join
        {
-               readonly LocatedToken into;
+               readonly SimpleMemberName into;
 
-               public GroupJoin (ToplevelBlock block, LocatedToken lt, Expression inner,
-                       ToplevelBlock outerSelector, ToplevelBlock innerSelector, LocatedToken into, Location loc)
+               public GroupJoin (ToplevelBlock block, SimpleMemberName lt, Expression inner,
+                       ToplevelBlock outerSelector, ToplevelBlock innerSelector, SimpleMemberName into, Location loc)
                        : base (block, lt, inner, outerSelector, innerSelector, loc)
                {
                        this.into = into;
                }
 
-               protected override LocatedToken GetIntoVariable ()
+               protected override SimpleMemberName GetIntoVariable ()
                {
                        return into;
                }
@@ -460,7 +452,7 @@ namespace Mono.CSharp.Linq
 
        class Let : ARangeVariableQueryClause
        {
-               public Let (ToplevelBlock block, TypeContainer container, LocatedToken identifier, Expression expr)
+               public Let (ToplevelBlock block, TypeContainer container, SimpleMemberName identifier, Expression expr)
                        : base (block, CreateRangeVariableType (block, container, identifier, expr))
                {
                }
@@ -498,15 +490,15 @@ namespace Mono.CSharp.Linq
 
        class SelectMany : ARangeVariableQueryClause
        {
-               LocatedToken lt;
+               SimpleMemberName lt;
 
-               public SelectMany (ToplevelBlock block, LocatedToken lt, Expression expr)
+               public SelectMany (ToplevelBlock block, SimpleMemberName lt, Expression expr)
                        : base (block, expr)
                {
                        this.lt = lt;
                }
 
-               protected override void CreateArguments (EmitContext ec, out ArrayList args)
+               protected override void CreateArguments (ResolveContext ec, out Arguments args)
                {
                        base.CreateArguments (ec, out args);
 
@@ -515,14 +507,14 @@ namespace Mono.CSharp.Linq
                        // When select follow use is as result selector
                        //
                        if (next is Select) {
-                               result_selector_expr = next.expr;
+                               result_selector_expr = next.Expr;
                                next = next.next;
                        } else {
-                               result_selector_expr = CreateRangeVariableType (block, (TypeContainer)ec.TypeContainer, lt, new SimpleName (lt.Value, lt.Location));
+                               result_selector_expr = CreateRangeVariableType (block, ec.MemberContext.CurrentMemberDefinition.Parent, lt, new SimpleName (lt.Value, lt.Location));
                        }
 
                        LambdaExpression result_selector = new LambdaExpression (lt.Location);
-                       result_selector.Block = new QueryBlock (block.Parent, block.Parameters, lt, block.StartLocation);
+                       result_selector.Block = new QueryBlock (ec.Compiler, block.Parent, block.Parameters, lt, block.StartLocation);
                        result_selector.Block.AddStatement (new ContextualReturn (result_selector_expr));
 
                        args.Add (new Argument (result_selector));
@@ -535,7 +527,7 @@ namespace Mono.CSharp.Linq
 
        class Where : AQueryClause
        {
-               public Where (ToplevelBlock block, Expression expr, Location loc)
+               public Where (ToplevelBlock block, BooleanExpression expr, Location loc)
                        : base (block, expr, loc)
                {
                }
@@ -610,14 +602,14 @@ namespace Mono.CSharp.Linq
                        public readonly ParametersCompiled Parent;
                        public readonly string Identifier;
 
-                       public TransparentParameter (ParametersCompiled parent, LocatedToken identifier)
+                       public TransparentParameter (ParametersCompiled parent, SimpleMemberName identifier)
                                : base (ParameterNamePrefix + Counter++, identifier.Location)
                        {
                                Parent = parent;
                                Identifier = identifier.Value;
                        }
 
-                       public static void Reset ()
+                       public new static void Reset ()
                        {
                                Counter = 0;
                        }
@@ -631,28 +623,28 @@ namespace Mono.CSharp.Linq
                        }
                }
 
-               public QueryBlock (Block parent, LocatedToken lt, Location start)
-                       : base (parent, new ParametersCompiled (new ImplicitQueryParameter (lt.Value, lt.Location)), start)
+               public QueryBlock (CompilerContext ctx, Block parent, SimpleMemberName lt, Location start)
+                       : base (ctx, parent, new ParametersCompiled (ctx, new ImplicitQueryParameter (lt.Value, lt.Location)), start)
                {
                        if (parent != null)
                                base.CheckParentConflictName (parent.Toplevel, lt.Value, lt.Location);
                }
 
-               public QueryBlock (Block parent, ParametersCompiled parameters, LocatedToken lt, Location start)
-                       : base (parent, new ParametersCompiled (parameters [0].Clone (), new ImplicitQueryParameter (lt.Value, lt.Location)), start)
+               public QueryBlock (CompilerContext ctx, Block parent, ParametersCompiled parameters, SimpleMemberName lt, Location start)
+                       : base (ctx, parent, new ParametersCompiled (ctx, parameters [0].Clone (), new ImplicitQueryParameter (lt.Value, lt.Location)), start)
                {
                }
 
-               public QueryBlock (Block parent, Location start)
-                       : base (parent, parent.Toplevel.Parameters.Clone (), start)
+               public QueryBlock (CompilerContext ctx, Block parent, Location start)
+                       : base (ctx, parent, parent.Toplevel.Parameters.Clone (), start)
                {
                }
 
-               public void AddTransparentParameter (LocatedToken name)
+               public void AddTransparentParameter (CompilerContext ctx, SimpleMemberName name)
                {
                        base.CheckParentConflictName (this, name.Value, name.Location);
 
-                       parameters = new ParametersCompiled (new TransparentParameter (parameters, name));
+                       parameters = new ParametersCompiled (ctx, new TransparentParameter (parameters, name));
                }
 
                protected override bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
@@ -709,9 +701,9 @@ namespace Mono.CSharp.Linq
                                var);           
                }
                
-               public override void Error_AlreadyDeclaredTypeParameter (Location loc, string name, string conflict)
+               public override void Error_AlreadyDeclaredTypeParameter (Report r, Location loc, string name, string conflict)
                {
-                       Report.Error (1948, loc, "A range variable `{0}' conflicts with a method type parameter",
+                       r.Error (1948, loc, "A range variable `{0}' conflicts with a method type parameter",
                                name);
                }
        }