// Keeps track of global data changes to undo on parser error
//
public Undo undo;
+
+ // Stack<ToplevelBlock>
+ Stack linq_clause_blocks;
// A counter to create new class names in interactive mode
static int class_count;
Report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration",
GetSymbolName (yyToken));
$$ = null;
+ lexer.parsing_generic_declaration = false;
}
;
first_from_clause
: FROM IDENTIFIER IN expression
{
- current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
- LocatedToken lt = (LocatedToken) $2;
-
- current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance, lt.Value, lt.Location);
- $$ = new Linq.QueryExpression (lt, new Linq.QueryStartClause ((Expression)$4));
+ $$ = new Linq.QueryExpression (current_block, new Linq.QueryStartClause ((Expression)$4));
+ current_block = new Linq.QueryBlock (current_block, (LocatedToken) $2, GetLocation ($1));
}
| FROM type IDENTIFIER IN expression
{
- current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
- LocatedToken lt = (LocatedToken) $3;
-
- FullNamedExpression type = (FullNamedExpression)$2;
- current_block.AddVariable (type, lt.Value, lt.Location);
- $$ = new Linq.QueryExpression (lt, new Linq.Cast (type, (Expression)$5));
+ $$ = new Linq.QueryExpression (current_block, new Linq.Cast ((FullNamedExpression)$2, (Expression)$5));
+ current_block = new Linq.QueryBlock (current_block, (LocatedToken) $3, GetLocation ($1));
}
;
from_clause
- : FROM IDENTIFIER IN expression
+ : FROM IDENTIFIER IN
+ {
+ current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
+ }
+ expression
{
LocatedToken lt = (LocatedToken) $2;
+ $$ = new Linq.SelectMany (current_block.Toplevel, lt, (Expression)$5);
- current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
- lt.Value, lt.Location);
-
- $$ = new Linq.SelectMany (lt, (Expression)$4);
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ ((Linq.QueryBlock)current_block).AddTransparentParameter (lt);
+ }
+ | FROM type IDENTIFIER IN
+ {
+ current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
}
- | FROM type IDENTIFIER IN expression
+ expression
{
LocatedToken lt = (LocatedToken) $3;
-
FullNamedExpression type = (FullNamedExpression)$2;
- current_block.AddVariable (type, lt.Value, lt.Location);
- $$ = new Linq.SelectMany (lt, new Linq.Cast (type, (FullNamedExpression)$5));
+
+ $$ = new Linq.SelectMany (current_block.Toplevel, lt, new Linq.Cast (type, (FullNamedExpression)$6));
+
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ ((Linq.QueryBlock)current_block).AddTransparentParameter (lt);
}
;
;
select_or_group_clause
- : SELECT expression
+ : SELECT
{
- $$ = new Linq.Select ((Expression)$2, GetLocation ($1));
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
}
- | GROUP expression BY expression
+ expression
{
- $$ = new Linq.GroupBy ((Expression)$2, (Expression)$4, GetLocation ($1));
+ $$ = new Linq.Select (current_block.Toplevel, (Expression)$3, GetLocation ($1));
+
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+ }
+ | GROUP
+ {
+ if (linq_clause_blocks == null)
+ linq_clause_blocks = new Stack ();
+
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
+ linq_clause_blocks.Push (current_block);
+ }
+ expression
+ {
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
+ }
+ BY expression
+ {
+ $$ = new Linq.GroupBy (current_block.Toplevel, (Expression)$3, (ToplevelBlock) linq_clause_blocks.Pop (), (Expression)$6, GetLocation ($1));
+
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
}
;
;
let_clause
- : LET IDENTIFIER ASSIGN expression
+ : LET IDENTIFIER ASSIGN
+ {
+ current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
+ }
+ expression
{
LocatedToken lt = (LocatedToken) $2;
- current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
- lt.Value, lt.Location);
- $$ = new Linq.Let (lt, (Expression)$4, GetLocation ($1));
+ $$ = new Linq.Let (current_block.Toplevel, current_container, lt, (Expression)$5);
+
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ ((Linq.QueryBlock)current_block).AddTransparentParameter (lt);
}
;
where_clause
- : WHERE boolean_expression
+ : WHERE
{
- $$ = new Linq.Where ((Expression)$2, GetLocation ($1));
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
+ }
+ boolean_expression
+ {
+ $$ = new Linq.Where (current_block.Toplevel, (Expression)$3, GetLocation ($1));
+
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
}
;
join_clause
- : JOIN IDENTIFIER IN expression ON expression EQUALS expression opt_join_into
+ : JOIN IDENTIFIER IN
+ {
+ if (linq_clause_blocks == null)
+ linq_clause_blocks = new Stack ();
+
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
+ linq_clause_blocks.Push (current_block);
+ }
+ expression ON
+ {
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
+ linq_clause_blocks.Push (current_block);
+ }
+ expression EQUALS
+ {
+ current_block.AddStatement (new ContextualReturn ((Expression) $8));
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ current_block = new Linq.QueryBlock (current_block, (LocatedToken) $2, lexer.Location);
+ }
+ expression opt_join_into
{
- Location loc = GetLocation ($1);
LocatedToken lt = (LocatedToken) $2;
- current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
- lt.Value, lt.Location);
- if ($9 == null) {
- $$ = new Linq.Join (lt, (Expression)$4, (Expression)$6,
- (Expression)$8, loc);
+ ToplevelBlock outer_selector = (ToplevelBlock) linq_clause_blocks.Pop ();
+ ToplevelBlock block = (ToplevelBlock) linq_clause_blocks.Pop ();
+
+ if ($12 == null) {
+ $$ = new Linq.Join (block, lt, (Expression)$5, outer_selector, current_block.Toplevel, GetLocation ($1));
} else {
- LocatedToken lt_into = (LocatedToken) $9;
- $$ = new Linq.GroupJoin (lt, (Expression)$4, (Expression)$6,
- (Expression)$8, lt_into, loc);
+ $$ = new Linq.GroupJoin (block, lt, (Expression)$5, outer_selector, current_block.Toplevel,
+ (LocatedToken) $12, GetLocation ($1));
}
+
+ current_block.AddStatement (new ContextualReturn ((Expression) $11));
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ if ($12 == null)
+ ((Linq.QueryBlock)current_block).AddTransparentParameter (lt);
+ else
+ ((Linq.QueryBlock)current_block).AddTransparentParameter ((LocatedToken) $12);
}
- | JOIN type IDENTIFIER IN expression ON expression EQUALS expression opt_join_into
+ | JOIN type IDENTIFIER IN
+ {
+ if (linq_clause_blocks == null)
+ linq_clause_blocks = new Stack ();
+
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
+ linq_clause_blocks.Push (current_block);
+ }
+ expression ON
+ {
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
+ linq_clause_blocks.Push (current_block);
+ }
+ expression EQUALS
+ {
+ current_block.AddStatement (new ContextualReturn ((Expression) $9));
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ current_block = new Linq.QueryBlock (current_block, (LocatedToken) $3, lexer.Location);
+ }
+ expression opt_join_into
{
- Location loc = GetLocation ($1);
LocatedToken lt = (LocatedToken) $3;
- current_block.AddVariable ((FullNamedExpression)$2, lt.Value, lt.Location);
+ ToplevelBlock outer_selector = (ToplevelBlock) linq_clause_blocks.Pop ();
+ ToplevelBlock block = (ToplevelBlock) linq_clause_blocks.Pop ();
- Linq.Cast cast = new Linq.Cast ((FullNamedExpression)$2, (Expression)$5);
- if ($10 == null) {
- $$ = new Linq.Join (lt, cast, (Expression)$7,
- (Expression)$9, loc);
+ Linq.Cast cast = new Linq.Cast ((FullNamedExpression)$2, (Expression)$6);
+ if ($13 == null) {
+ $$ = new Linq.Join (block, lt, cast, outer_selector, current_block.Toplevel, GetLocation ($1));
} else {
- LocatedToken lt_into = (LocatedToken) $10;
- $$ = new Linq.GroupJoin (lt, cast, (Expression)$7,
- (Expression)$9, lt_into, loc);
+ $$ = new Linq.GroupJoin (block, lt, cast, outer_selector, current_block.Toplevel,
+ (LocatedToken) $13, GetLocation ($1));
}
+
+ current_block.AddStatement (new ContextualReturn ((Expression) $12));
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ if ($13 == null)
+ ((Linq.QueryBlock)current_block).AddTransparentParameter (lt);
+ else
+ ((Linq.QueryBlock)current_block).AddTransparentParameter ((LocatedToken) $13);
}
;
: /* empty */
| INTO IDENTIFIER
{
- $$ = $2;
+ $$ = $2;
}
;
orderby_clause
- : ORDERBY orderings
+ : ORDERBY
{
- $$ = $2;
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
+ }
+ orderings
+ {
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ $$ = $3;
}
;
orderings
: order_by
- | order_by COMMA orderings_then_by
+ | order_by COMMA
+ {
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
+ }
+ orderings_then_by
{
- ((Linq.AQueryClause)$1).Next = (Linq.AQueryClause)$3;
+ ((Linq.AQueryClause)$1).Next = (Linq.AQueryClause)$4;
$$ = $1;
}
;
orderings_then_by
: then_by
- {
- $$ = $1;
- }
- | orderings_then_by COMMA then_by
- {
+ | orderings_then_by COMMA
+ {
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+
+ current_block = new Linq.QueryBlock (current_block, lexer.Location);
+ }
+ then_by
+ {
((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$3;
$$ = $1;
- }
+ }
;
order_by
: expression
{
- $$ = new Linq.OrderByAscending ((Expression)$1);
+ $$ = new Linq.OrderByAscending (current_block.Toplevel, (Expression)$1);
}
| expression ASCENDING
{
- $$ = new Linq.OrderByAscending ((Expression)$1);
+ $$ = new Linq.OrderByAscending (current_block.Toplevel, (Expression)$1);
}
| expression DESCENDING
{
- $$ = new Linq.OrderByDescending ((Expression)$1);
+ $$ = new Linq.OrderByDescending (current_block.Toplevel, (Expression)$1);
}
;
then_by
: expression
{
- $$ = new Linq.ThenByAscending ((Expression)$1);
+ $$ = new Linq.ThenByAscending (current_block.Toplevel, (Expression)$1);
}
| expression ASCENDING
{
- $$ = new Linq.ThenByAscending ((Expression)$1);
+ $$ = new Linq.ThenByAscending (current_block.Toplevel, (Expression)$1);
}
| expression DESCENDING
{
- $$ = new Linq.ThenByDescending ((Expression)$1);
+ $$ = new Linq.ThenByDescending (current_block.Toplevel, (Expression)$1);
}
;
current_block.SetEndLocation (GetLocation ($1));
current_block = current_block.Parent;
- current_block = new Linq.QueryBlock (current_block, GetLocation ($1));
- LocatedToken lt = (LocatedToken) $2;
- current_block.AddVariable (Linq.ImplicitQueryParameter.ImplicitType.Instance,
- lt.Value, lt.Location);
+ current_block = new Linq.QueryBlock (current_block, (LocatedToken) $2, GetLocation ($1));
}
query_body
{
- $$ = new Linq.QueryExpression ((LocatedToken) $2,
- (Linq.AQueryClause)$4);
+ $$ = new Linq.QueryExpression (current_block, (Linq.AQueryClause)$4);
}
;
//
//
- public class QueryExpression : AQueryClause
+ class QueryExpression : AQueryClause
{
- LocatedToken variable;
-
- public QueryExpression (LocatedToken variable, AQueryClause query)
- : base (null, query.Location)
+ public QueryExpression (Block block, AQueryClause query)
+ : base (null, null, query.Location)
{
- this.variable = variable;
this.next = query;
}
- public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parentParameter, TransparentIdentifiersScope ti)
+ public override Expression BuildQueryClause (EmitContext ec, Expression lSide)
{
- Parameter p = CreateBlockParameter (variable);
- return next.BuildQueryClause (ec, lSide, p, ti);
+ return next.BuildQueryClause (ec, lSide);
}
public override Expression DoResolve (EmitContext ec)
{
- int counter = TransparentParameter.Counter;
+ int counter = QueryBlock.TransparentParameter.Counter;
- Expression e = BuildQueryClause (ec, null, null, null);
+ Expression e = BuildQueryClause (ec, null);
e = e.Resolve (ec);
//
// identifier anonymous types are created only once
//
if (ec.IsInProbingMode)
- TransparentParameter.Counter = counter;
+ QueryBlock.TransparentParameter.Counter = counter;
return e;
}
}
}
- public abstract class AQueryClause : Expression
+ abstract class AQueryClause : Expression
{
class QueryExpressionAccess : MemberAccess
{
return rmg;
}
+ public bool AmbiguousCall (MethodBase ambiguous)
+ {
+ Report.SymbolRelatedToPreviousError ((MethodInfo) mg);
+ Report.SymbolRelatedToPreviousError (ambiguous);
+ 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)
{
#if GMCS_SOURCE
if (!method.IsGenericMethod)
return false;
- Report.Error (1942, loc, "Type inference failed to infer type argument for `{0}' clause. " +
- "Try specifying the type argument explicitly",
- mg.Name.ToLower ());
+ if (mg.Name == "SelectMany") {
+ 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 ());
+ } else {
+ 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;
}
}
+ // TODO: protected
public AQueryClause next;
- /*protected*/ public Expression expr;
+ public Expression expr;
+ protected ToplevelBlock block;
- protected AQueryClause (Expression expr, Location loc)
+ protected AQueryClause (ToplevelBlock block, Expression expr, Location loc)
{
+ this.block = block;
this.expr = expr;
this.loc = loc;
}
AQueryClause t = (AQueryClause) target;
if (expr != null)
t.expr = expr.Clone (clonectx);
-
+
+ if (block != null)
+ t.block = (ToplevelBlock) block.Clone (clonectx);
+
if (next != null)
- t.next = (AQueryClause)next.Clone (clonectx);
+ t.next = (AQueryClause) next.Clone (clonectx);
}
public override Expression CreateExpressionTree (EmitContext ec)
return expr.DoResolve (ec);
}
- public virtual Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
+ public virtual Expression BuildQueryClause (EmitContext ec, Expression lSide)
{
- ArrayList args = new ArrayList (1);
- args.Add (CreateSelectorArgument (ec, expr, parameter, ti));
+ ArrayList args;
+ CreateArguments (ec, out args);
lSide = CreateQueryExpression (lSide, args);
if (next != null) {
Select s = next as Select;
- if (s == null || s.IsRequired (parameter))
- return next.BuildQueryClause (ec, lSide, parameter, ti);
+ if (s == null || s.IsRequired)
+ return next.BuildQueryClause (ec, lSide);
// Skip transparent select clause if any clause follows
if (next.next != null)
- return next.next.BuildQueryClause (ec, lSide, parameter, ti);
+ return next.next.BuildQueryClause (ec, lSide);
}
return lSide;
}
- protected static Parameter CreateBlockParameter (LocatedToken li)
+ protected virtual void CreateArguments (EmitContext ec, out ArrayList args)
{
- return new ImplicitQueryParameter (li);
+ args = new ArrayList (2);
+
+ LambdaExpression selector = new LambdaExpression (loc);
+ selector.Block = block;
+ selector.Block.AddStatement (new ContextualReturn (expr));
+
+ args.Add (new Argument (selector));
}
protected Invocation CreateQueryExpression (Expression lSide, ArrayList arguments)
new QueryExpressionAccess (lSide, MethodName, typeArguments, loc), arguments);
}
- protected Argument CreateSelectorArgument (EmitContext ec, Expression expr, Parameter parameter, TransparentIdentifiersScope ti)
- {
- return CreateSelectorArgument (ec, expr, new Parameter [] { parameter }, ti);
- }
-
- protected Argument CreateSelectorArgument (EmitContext ec, Expression expr, Parameter[] parameters, TransparentIdentifiersScope ti)
- {
- Parameters p = new Parameters (parameters);
-
- LambdaExpression selector = new LambdaExpression (loc);
- selector.Block = new SelectorBlock (ec.CurrentBlock, p, ti, loc);
- selector.Block.AddStatement (new ContextualReturn (expr));
-
- return new Argument (selector);
- }
-
public override void Emit (EmitContext ec)
{
throw new NotSupportedException ();
//
// A query clause with an identifier (range variable)
//
- public abstract class ARangeVariableQueryClause : AQueryClause
+ abstract class ARangeVariableQueryClause : AQueryClause
{
- LocatedToken variable;
- protected Expression element_selector;
-
- protected ARangeVariableQueryClause (LocatedToken variable, Expression expr, Location loc)
- : base (expr, loc)
+ sealed class RangeAnonymousTypeParameter : AnonymousTypeParameter
{
- this.variable = variable;
- }
-
- protected virtual void AddSelectorArguments (EmitContext ec, ArrayList args, Parameter parentParameter,
- ref Parameter parameter, TransparentIdentifiersScope ti)
- {
- args.Add (CreateSelectorArgument (ec, expr, parentParameter, ti));
- args.Add (CreateSelectorArgument (ec, element_selector,
- new Parameter [] { parentParameter, parameter }, ti));
- }
-
- //
- // Customization for range variables which not only creates a lambda expression but
- // also builds a chain of range varible pairs
- //
- public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parentParameter, TransparentIdentifiersScope ti)
- {
- Parameter parameter = CreateBlockParameter (variable);
-
- if (next != null) {
- //
- // Builds transparent identifiers, each identifier includes its parent
- // type at index 0, and new value at index 1. This is not valid for the
- // first one which includes two values directly.
- //
- ArrayList transp_args = new ArrayList (2);
- transp_args.Add (new AnonymousTypeParameter (parentParameter));
- transp_args.Add (CreateAnonymousTypeVariable (parameter));
- element_selector = new AnonymousTypeDeclaration (transp_args, (TypeContainer) ec.TypeContainer, loc);
+ public RangeAnonymousTypeParameter (Expression initializer, LocatedToken parameter)
+ : base (initializer, parameter.Value, parameter.Location)
+ {
}
- ArrayList args = new ArrayList ();
- AddSelectorArguments (ec, args, parentParameter, ref parameter, ti);
-
- lSide = CreateQueryExpression (lSide, args);
- if (next != null) {
- //
- // Parameter identifiers go to the scope
- //
- string[] identifiers;
- if (ti == null) {
- identifiers = new string [] { parentParameter.Name, parameter.Name };
- } else {
- identifiers = new string [] { parameter.Name };
- }
-
- TransparentParameter tp = new TransparentParameter (loc);
- return next.BuildQueryClause (ec, lSide, tp,
- new TransparentIdentifiersScope (ti, tp, identifiers));
+ protected override void Error_InvalidInitializer (string initializer)
+ {
+ Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'",
+ Name, initializer);
}
-
- return lSide;
}
-
- protected override void CloneTo (CloneContext clonectx, Expression target)
+
+ protected ARangeVariableQueryClause (ToplevelBlock block, Expression expr)
+ : base (block, expr, expr.Location)
{
- ARangeVariableQueryClause t = (ARangeVariableQueryClause) target;
- if (element_selector != null)
- t.element_selector = element_selector.Clone (clonectx);
- base.CloneTo (clonectx, t);
}
-
- //
- // For transparent identifiers, creates an instance of variable expression
- //
- protected virtual AnonymousTypeParameter CreateAnonymousTypeVariable (Parameter parameter)
+
+ protected static Expression CreateRangeVariableType (ToplevelBlock block, TypeContainer container, LocatedToken name, Expression init)
{
- return new AnonymousTypeParameter (parameter);
+ ArrayList args = new ArrayList (2);
+ args.Add (new AnonymousTypeParameter (block.Parameters [0]));
+ args.Add (new RangeAnonymousTypeParameter (init, name));
+ return new AnonymousTypeDeclaration (args, container, name.Location);
}
}
- public class QueryStartClause : AQueryClause
+ class QueryStartClause : AQueryClause
{
public QueryStartClause (Expression expr)
- : base (expr, expr.Location)
+ : base (null, expr, expr.Location)
{
}
- public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
+ public override Expression BuildQueryClause (EmitContext ec, Expression lSide)
{
- return next.BuildQueryClause (ec, expr, parameter, ti);
+ return next.BuildQueryClause (ec, expr);
}
public override Expression DoResolve (EmitContext ec)
{
- Expression e = BuildQueryClause (ec, null, null, null);
+ Expression e = BuildQueryClause (ec, null);
return e.Resolve (ec);
}
}
}
- public class Cast : QueryStartClause
+ class Cast : QueryStartClause
{
// We don't have to clone cast type
readonly FullNamedExpression type_expr;
this.type_expr = type;
}
- public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
+ public override Expression BuildQueryClause (EmitContext ec, Expression lSide)
{
lSide = CreateQueryExpression (expr, new TypeArguments (type_expr), null);
if (next != null)
- return next.BuildQueryClause (ec, lSide, parameter, ti);
+ return next.BuildQueryClause (ec, lSide);
return lSide;
}
}
}
- public class GroupBy : AQueryClause
+ class GroupBy : AQueryClause
{
Expression element_selector;
+ ToplevelBlock element_block;
- public GroupBy (Expression elementSelector, Expression keySelector, Location loc)
- : base (keySelector, loc)
+ public GroupBy (ToplevelBlock block, Expression elementSelector, ToplevelBlock elementBlock, Expression keySelector, Location loc)
+ : base (block, keySelector, loc)
{
- this.element_selector = elementSelector;
+ //
+ // Optimizes clauses like `group A by A'
+ //
+ if (!elementSelector.Equals (keySelector)) {
+ this.element_selector = elementSelector;
+ this.element_block = elementBlock;
+ }
}
- public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
+ protected override void CreateArguments (EmitContext ec, out ArrayList args)
{
- ArrayList args = new ArrayList (2);
- args.Add (CreateSelectorArgument (ec, expr, parameter, ti));
-
- // A query can be optimized when selector is not group by specific
- if (!element_selector.Equals (lSide))
- args.Add (CreateSelectorArgument (ec, element_selector, parameter, ti));
+ base.CreateArguments (ec, out args);
- lSide = CreateQueryExpression (lSide, args);
- if (next != null)
- return next.BuildQueryClause (ec, lSide, parameter, ti);
-
- return lSide;
+ if (element_selector != null) {
+ LambdaExpression lambda = new LambdaExpression (element_selector.Location);
+ lambda.Block = element_block;
+ lambda.Block.AddStatement (new ContextualReturn (element_selector));
+ args.Add (new Argument (lambda));
+ }
}
-
+
protected override void CloneTo (CloneContext clonectx, Expression target)
{
GroupBy t = (GroupBy) target;
- t.element_selector = element_selector.Clone (clonectx);
+ if (element_selector != null) {
+ t.element_selector = element_selector.Clone (clonectx);
+ t.element_block = (ToplevelBlock) element_block.Clone (clonectx);
+ }
+
base.CloneTo (clonectx, t);
}
}
}
- public class Join : ARangeVariableQueryClause
+ class Join : ARangeVariableQueryClause
{
- Expression projection;
- Expression inner_selector, outer_selector;
+ readonly LocatedToken lt;
+ ToplevelBlock inner_selector, outer_selector;
- public Join (LocatedToken variable, Expression inner, Expression outerSelector, Expression innerSelector, Location loc)
- : base (variable, inner, loc)
+ public Join (ToplevelBlock block, LocatedToken lt, Expression inner, ToplevelBlock outerSelector, ToplevelBlock innerSelector, Location loc)
+ : base (block, inner)
{
+ this.lt = lt;
this.outer_selector = outerSelector;
this.inner_selector = innerSelector;
}
- protected override void AddSelectorArguments (EmitContext ec, ArrayList args, Parameter parentParameter,
- ref Parameter parameter, TransparentIdentifiersScope ti)
+ protected override void CreateArguments (EmitContext ec, out ArrayList args)
{
+ args = new ArrayList (4);
+
args.Add (new Argument (expr));
- args.Add (CreateSelectorArgument (ec, outer_selector, parentParameter, ti));
- args.Add (CreateSelectorArgument (ec, inner_selector, parameter, ti));
-
- parameter = CreateResultSelectorParameter (parameter);
- if (projection == null) {
- ArrayList join_args = new ArrayList (2);
- join_args.Add (new AnonymousTypeParameter (parentParameter));
- join_args.Add (new AnonymousTypeParameter (parameter));
- projection = new AnonymousTypeDeclaration (join_args, (TypeContainer) ec.TypeContainer, loc);
+
+ LambdaExpression lambda = new LambdaExpression (outer_selector.StartLocation);
+ lambda.Block = outer_selector;
+ args.Add (new Argument (lambda));
+
+ lambda = new LambdaExpression (inner_selector.StartLocation);
+ lambda.Block = inner_selector;
+ args.Add (new Argument (lambda));
+
+ Expression result_selector_expr;
+ LocatedToken into_variable = GetIntoVariable ();
+ //
+ // When select follows use is as result selector
+ //
+ if (next is Select) {
+ result_selector_expr = next.expr;
+ next = next.next;
+ } else {
+ result_selector_expr = CreateRangeVariableType (block, (TypeContainer) ec.TypeContainer, into_variable,
+ new SimpleName (into_variable.Value, into_variable.Location));
}
- args.Add (CreateSelectorArgument (ec, projection,
- new Parameter [] { parentParameter, parameter }, ti));
+ LambdaExpression result_selector = new LambdaExpression (lt.Location);
+ result_selector.Block = new QueryBlock (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 ()
+ {
+ return lt;
}
-
+
protected override void CloneTo (CloneContext clonectx, Expression target)
{
Join t = (Join) target;
- t.projection = projection.Clone (clonectx);
- t.inner_selector = inner_selector.Clone (clonectx);
- t.outer_selector = outer_selector.Clone (clonectx);
+ t.inner_selector = (ToplevelBlock) inner_selector.Clone (clonectx);
+ t.outer_selector = (ToplevelBlock) outer_selector.Clone (clonectx);
base.CloneTo (clonectx, t);
}
- protected virtual Parameter CreateResultSelectorParameter (Parameter parameter)
- {
- return parameter;
- }
-
- public override AQueryClause Next {
- set {
- // Use select as join projection
- if (value is Select) {
- projection = value.expr;
- next = value.next;
- return;
- }
-
- base.Next = value;
- }
- }
-
protected override string MethodName {
get { return "Join"; }
}
}
- public class GroupJoin : Join
+ class GroupJoin : Join
{
- readonly LocatedToken into_variable;
+ readonly LocatedToken into;
- public GroupJoin (LocatedToken variable, Expression inner, Expression outerSelector, Expression innerSelector,
- LocatedToken into, Location loc)
- : base (variable, inner, outerSelector, innerSelector, loc)
+ public GroupJoin (ToplevelBlock block, LocatedToken lt, Expression inner,
+ ToplevelBlock outerSelector, ToplevelBlock innerSelector, LocatedToken into, Location loc)
+ : base (block, lt, inner, outerSelector, innerSelector, loc)
{
- this.into_variable = into;
+ this.into = into;
}
- protected override Parameter CreateResultSelectorParameter (Parameter parameter)
+ protected override LocatedToken GetIntoVariable ()
{
- //
- // into variable is used as result selector and it's passed as
- // transparent identifiers to the next clause
- //
- return CreateBlockParameter (into_variable);
+ return into;
}
protected override string MethodName {
}
}
- public class Let : ARangeVariableQueryClause
+ class Let : ARangeVariableQueryClause
{
- class RangeAnonymousTypeParameter : AnonymousTypeParameter
- {
- readonly Parameter parameter;
-
- public RangeAnonymousTypeParameter (Expression initializer, Parameter parameter)
- : base (initializer, parameter.Name, parameter.Location)
- {
- this.parameter = parameter;
- }
-
- public override Expression DoResolve (EmitContext ec)
- {
- Expression e = base.DoResolve (ec);
- if (e != null) {
- //
- // Spread resolved initializer type
- //
- ((ImplicitLambdaParameter) parameter).Type = type;
- }
-
- return e;
- }
-
- protected override void Error_InvalidInitializer (string initializer)
- {
- Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'",
- Name, initializer);
- }
- }
-
- public Let (LocatedToken variable, Expression expr, Location loc)
- : base (variable, expr, loc)
+ public Let (ToplevelBlock block, TypeContainer container, LocatedToken identifier, Expression expr)
+ : base (block, CreateRangeVariableType (block, container, identifier, expr))
{
}
- protected override void AddSelectorArguments (EmitContext ec, ArrayList args, Parameter parentParameter,
- ref Parameter parameter, TransparentIdentifiersScope ti)
- {
- args.Add (CreateSelectorArgument (ec, element_selector, parentParameter, ti));
- }
-
- protected override AnonymousTypeParameter CreateAnonymousTypeVariable (Parameter parameter)
- {
- return new RangeAnonymousTypeParameter (expr, parameter);
- }
-
protected override string MethodName {
get { return "Select"; }
}
}
- public class Select : AQueryClause
+ class Select : AQueryClause
{
- public Select (Expression expr, Location loc)
- : base (expr, loc)
+ public Select (ToplevelBlock block, Expression expr, Location loc)
+ : base (block, expr, loc)
{
}
// For queries like `from a orderby a select a'
// the projection is transparent and select clause can be safely removed
//
- public bool IsRequired (Parameter parameter)
- {
- SimpleName sn = expr as SimpleName;
- if (sn == null)
- return true;
+ public bool IsRequired {
+ get {
+ SimpleName sn = expr as SimpleName;
+ if (sn == null)
+ return true;
- return sn.Name != parameter.Name;
+ return sn.Name != block.Parameters[0].Name;
+ }
}
protected override string MethodName {
}
}
- public class SelectMany : ARangeVariableQueryClause
+ class SelectMany : ARangeVariableQueryClause
{
- public SelectMany (LocatedToken variable, Expression expr)
- : base (variable, expr, expr.Location)
+ LocatedToken lt;
+
+ public SelectMany (ToplevelBlock block, LocatedToken lt, Expression expr)
+ : base (block, expr)
{
+ this.lt = lt;
}
- protected override string MethodName {
- get { return "SelectMany"; }
- }
+ protected override void CreateArguments (EmitContext ec, out ArrayList args)
+ {
+ base.CreateArguments (ec, out args);
- public override AQueryClause Next {
- set {
- element_selector = value.expr;
+ Expression result_selector_expr;
+ //
+ // When select follow use is as result selector
+ //
+ if (next is Select) {
+ result_selector_expr = next.expr;
+ next = next.next;
+ } else {
+ result_selector_expr = CreateRangeVariableType (block, (TypeContainer)ec.TypeContainer, lt, new SimpleName (lt.Value, lt.Location));
+ }
- // Can be optimized as SelectMany element selector
- if (value is Select)
- return;
+ LambdaExpression result_selector = new LambdaExpression (lt.Location);
+ result_selector.Block = new QueryBlock (block.Parent, block.Parameters, lt, block.StartLocation);
+ result_selector.Block.AddStatement (new ContextualReturn (result_selector_expr));
- next = value;
- }
+ args.Add (new Argument (result_selector));
+ }
+
+ protected override string MethodName {
+ get { return "SelectMany"; }
}
}
- public class Where : AQueryClause
+ class Where : AQueryClause
{
- public Where (Expression expr, Location loc)
- : base (expr, loc)
+ public Where (ToplevelBlock block, Expression expr, Location loc)
+ : base (block, expr, loc)
{
}
}
}
- public class OrderByAscending : AQueryClause
+ class OrderByAscending : AQueryClause
{
- public OrderByAscending (Expression expr)
- : base (expr, expr.Location)
+ public OrderByAscending (ToplevelBlock block,Expression expr)
+ : base (block, expr, expr.Location)
{
}
}
}
- public class OrderByDescending : AQueryClause
+ class OrderByDescending : AQueryClause
{
- public OrderByDescending (Expression expr)
- : base (expr, expr.Location)
+ public OrderByDescending (ToplevelBlock block, Expression expr)
+ : base (block, expr, expr.Location)
{
}
}
}
- public class ThenByAscending : OrderByAscending
+ class ThenByAscending : OrderByAscending
{
- public ThenByAscending (Expression expr)
- : base (expr)
+ public ThenByAscending (ToplevelBlock block, Expression expr)
+ : base (block, expr)
{
}
}
}
- public class ThenByDescending : OrderByDescending
+ class ThenByDescending : OrderByDescending
{
- public ThenByDescending (Expression expr)
- : base (expr)
+ public ThenByDescending (ToplevelBlock block, Expression expr)
+ : base (block, expr)
{
}
}
}
- class ImplicitQueryParameter : ImplicitLambdaParameter
+ //
+ // Implicit query block
+ //
+ class QueryBlock : ToplevelBlock
{
- public sealed class ImplicitType : Expression
+ //
+ // Transparent parameters are used to package up the intermediate results
+ // and pass them onto next clause
+ //
+ public sealed class TransparentParameter : ImplicitLambdaParameter
{
- public static ImplicitType Instance = new ImplicitType ();
-
- private ImplicitType ()
- {
- }
-
- protected override void CloneTo (CloneContext clonectx, Expression target)
- {
- // Nothing to clone
- }
+ public static int Counter;
+ const string ParameterNamePrefix = "<>__TranspIdent";
- public override Expression CreateExpressionTree (EmitContext ec)
- {
- throw new NotSupportedException ();
- }
+ public readonly Parameters Parent;
+ public readonly string Identifier;
- public override Expression DoResolve (EmitContext ec)
+ public TransparentParameter (Parameters parent, LocatedToken identifier)
+ : base (ParameterNamePrefix + Counter++, identifier.Location)
{
- throw new NotSupportedException ();
+ Parent = parent;
+ Identifier = identifier.Value;
}
- public override void Emit (EmitContext ec)
+ public static void Reset ()
{
- throw new NotSupportedException ();
+ Counter = 0;
}
+ }
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+ public sealed class ImplicitQueryParameter : ImplicitLambdaParameter
+ {
+ public ImplicitQueryParameter (string name, Location loc)
+ : base (name, loc)
{
- throw new NotSupportedException ();
}
}
- public ImplicitQueryParameter (LocatedToken variable)
- : base (variable.Value, variable.Location)
+ public QueryBlock (Block parent, LocatedToken lt, Location start)
+ : base (parent, new Parameters (new ImplicitQueryParameter (lt.Value, lt.Location)), start)
{
+ if (parent != null)
+ base.CheckParentConflictName (parent.Toplevel, lt.Value, lt.Location);
}
- }
- //
- // Transparent parameters are used to package up the intermediate results
- // and pass them onto next clause
- //
- public class TransparentParameter : ImplicitLambdaParameter
- {
- public static int Counter;
- const string ParameterNamePrefix = "<>__TranspIdent";
-
- public TransparentParameter (Location loc)
- : base (ParameterNamePrefix + Counter++, loc)
+ public QueryBlock (Block parent, Parameters parameters, LocatedToken lt, Location start)
+ : base (parent, new Parameters (parameters [0].Clone (), new ImplicitQueryParameter (lt.Value, lt.Location)), start)
{
}
- }
-
- //
- // Transparent identifiers are stored in nested anonymous types, each type can contain
- // up to 2 identifiers or 1 identifier and parent type.
- //
- public class TransparentIdentifiersScope
- {
- readonly string [] identifiers;
- readonly TransparentIdentifiersScope parent;
- readonly TransparentParameter parameter;
- public TransparentIdentifiersScope (TransparentIdentifiersScope parent,
- TransparentParameter parameter, string [] identifiers)
+ public QueryBlock (Block parent, Location start)
+ : base (parent, parent.Toplevel.Parameters.Clone (), start)
{
- this.parent = parent;
- this.parameter = parameter;
- this.identifiers = identifiers;
}
- public MemberAccess GetIdentifier (string name)
+ public void AddTransparentParameter (LocatedToken name)
{
- TransparentIdentifiersScope ident = FindIdentifier (name);
- if (ident == null)
- return null;
+ base.CheckParentConflictName (this, name.Value, name.Location);
- return new MemberAccess (CreateIdentifierNestingExpression (ident), name);
+ parameters = new Parameters (new TransparentParameter (parameters, name));
}
- TransparentIdentifiersScope FindIdentifier (string name)
+ protected override bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
{
- foreach (string s in identifiers) {
- if (s == name)
- return this;
- }
-
- if (parent == null)
- return null;
-
- return parent.FindIdentifier (name);
+ return true;
}
- Expression CreateIdentifierNestingExpression (TransparentIdentifiersScope end)
+ //
+ // Query parameter reference can include transparent parameters
+ //
+ protected override Expression GetParameterReferenceExpression (string name, Location loc)
{
- Expression expr = new SimpleName (parameter.Name, parameter.Location);
- TransparentIdentifiersScope current = this;
- while (current != end)
- {
- current = current.parent;
- expr = new MemberAccess (expr, current.parameter.Name);
- }
-
- return expr;
- }
- }
-
- //
- // Lambda expression block which contains transparent identifiers
- //
- class SelectorBlock : ToplevelBlock
- {
- readonly TransparentIdentifiersScope transparent_identifiers;
+ Expression expr = base.GetParameterReferenceExpression (name, loc);
+ if (expr != null)
+ return expr;
- public SelectorBlock (Block block, Parameters parameters,
- TransparentIdentifiersScope transparentIdentifiers, Location loc)
- : base (block, parameters, loc)
- {
- this.transparent_identifiers = transparentIdentifiers;
- }
+ TransparentParameter tp = parameters [0] as TransparentParameter;
+ while (tp != null) {
+ if (tp.Identifier == name)
+ break;
- public override Expression GetTransparentIdentifier (string name)
- {
- Expression expr = null;
- if (transparent_identifiers != null)
- expr = transparent_identifiers.GetIdentifier (name);
+ TransparentParameter tp_next = tp.Parent [0] as TransparentParameter;
+ if (tp_next == null) {
+ if (tp.Parent.GetParameterIndexByName (name) >= 0)
+ break;
+ }
- if (expr != null || Container == null)
- return expr;
-
- return Container.GetTransparentIdentifier (name);
- }
- }
+ tp = tp_next;
+ }
- //
- // This block is actually never used, it is used by parser only
- //
- public class QueryBlock : ExplicitBlock
- {
- public QueryBlock (Block parent, Location start)
- : base (parent, start, Location.Null)
- {
- range_variables = new System.Collections.Specialized.HybridDictionary ();
- }
+ if (tp != null) {
+ expr = new SimpleName (parameters[0].Name, loc);
+ TransparentParameter tp_cursor = (TransparentParameter) parameters[0];
+ while (tp_cursor != tp) {
+ tp_cursor = (TransparentParameter) tp_cursor.Parent[0];
+ expr = new MemberAccess (expr, tp_cursor.Name);
+ }
- protected override void AddVariable (LocalInfo li)
- {
- string name = li.Name;
- if (range_variables.Contains (name)) {
- LocalInfo conflict = (LocalInfo) range_variables [name];
- Report.SymbolRelatedToPreviousError (conflict.Location, name);
- Error_AlreadyDeclared (li.Location, name);
- return;
+ return new MemberAccess (expr, name);
}
- range_variables.Add (name, li);
- Explicit.AddKnownVariable (name, li);
+ return null;
}
-
+
protected override void Error_AlreadyDeclared (Location loc, string var, string reason)
{
Report.Error (1931, loc, "A range variable `{0}' conflicts with a previous declaration of `{0}'",
var);
}
- protected override void Error_AlreadyDeclaredTypeParameter (Location loc, string name)
+ public override void Error_AlreadyDeclaredTypeParameter (Location loc, string name, string conflict)
{
Report.Error (1948, loc, "A range variable `{0}' conflicts with a method type parameter",
name);