//
//
- public class QueryExpression : ARangeVariableQueryClause
+ public class QueryExpression : AQueryClause
{
- public QueryExpression (Block block, AQueryClause query)
- : base (block, null, query.Location)
+ LocatedToken variable;
+
+ public QueryExpression (LocatedToken variable, AQueryClause query)
+ : base (null, query.Location)
{
+ this.variable = variable;
this.next = query;
}
+ public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parentParameter, TransparentIdentifiersScope ti)
+ {
+ Parameter p = CreateBlockParameter (variable);
+ return next.BuildQueryClause (ec, lSide, p, ti);
+ }
+
public override Expression DoResolve (EmitContext ec)
{
Expression e = BuildQueryClause (ec, null, null, null);
}
}
- class QueryExpressionInvocation : Invocation
+ class QueryExpressionInvocation : Invocation, MethodGroupExpr.IErrorHandler
{
public QueryExpressionInvocation (QueryExpressionAccess expr, ArrayList arguments)
: base (expr, arguments)
protected override MethodGroupExpr DoResolveOverload (EmitContext ec)
{
- int errors = Report.Errors;
- MethodGroupExpr rmg = mg.OverloadResolve (ec, Arguments, true, loc);
- if (rmg == null && errors == Report.Errors) {
- // TODO: investigate whether would be better to re-use extension methods error handling
- Report.Error (1936, loc, "An implementation of `{0}' query expression pattern for source type `{1}' could not be found",
- mg.Name, TypeManager.CSharpName (mg.Type));
+ MethodGroupExpr.CustomErrorHandler = this;
+ MethodGroupExpr rmg = mg.OverloadResolve (ec, Arguments, false, loc);
+ MethodGroupExpr.CustomErrorHandler = null;
+ return rmg;
+ }
+
+ public bool NoExactMatch (EmitContext ec, MethodBase method)
+ {
+ ParameterData pd = TypeManager.GetParameterData (method);
+ Type source_type = pd.ExtensionMethodType;
+ if (source_type != null) {
+ Argument a = (Argument) Arguments [0];
+
+ if (source_type.IsGenericType && source_type.ContainsGenericParameters) {
+ TypeInferenceContext tic = new TypeInferenceContext (source_type.GetGenericArguments ());
+ tic.OutputTypeInference (ec, a.Expr, source_type);
+ if (tic.FixAllTypes ()) {
+ source_type = source_type.GetGenericTypeDefinition ().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",
+ mg.Name, TypeManager.CSharpName (a.Type));
+ return true;
+ }
}
- return rmg;
+ 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 ());
+ return true;
}
}
this.expr = expr;
this.loc = loc;
}
+
+ protected override void CloneTo (CloneContext clonectx, Expression target)
+ {
+ AQueryClause t = (AQueryClause) target;
+ if (expr != null)
+ t.expr = expr.Clone (clonectx);
+
+ if (next != null)
+ t.next = (AQueryClause)next.Clone (clonectx);
+ }
public override Expression DoResolve (EmitContext ec)
{
Select s = next as Select;
if (s == null || s.IsRequired (parameter))
return next.BuildQueryClause (ec, lSide, parameter, ti);
+
+ // Skip transparent select clause if any clause follows
+ if (next.next != null)
+ return next.next.BuildQueryClause (ec, lSide, parameter, ti);
}
return lSide;
}
+ protected static Parameter CreateBlockParameter (LocatedToken li)
+ {
+ return new ImplicitQueryParameter (li);
+ }
+
protected Invocation CreateQueryExpression (Expression lSide, ArrayList arguments)
{
return new QueryExpressionInvocation (
Parameters p = new Parameters (parameters);
LambdaExpression selector = new LambdaExpression (
- null, null, (TypeContainer) ec.DeclContainer, p, ec.CurrentBlock, loc);
+ null, null, (TypeContainer)ec.TypeContainer, p, ec.CurrentBlock, loc);
selector.Block = new SelectorBlock (ec.CurrentBlock, p, ti, loc);
selector.Block.AddStatement (new Return (expr, loc));
- selector.CreateAnonymousHelpers ();
- selector.RootScope.DefineType ();
+ if (!ec.IsInProbingMode) {
+ selector.CreateAnonymousHelpers ();
+ // TODO: I am not sure where this should be done to work
+ // correctly with anonymous containerss and was called only once
+ // FIXME: selector.RootScope == null for nested anonymous
+ // methods only ?
+ if (selector.RootScope != null)
+ selector.RootScope.DefineType ();
+ }
+
return new Argument (selector);
}
//
public abstract class ARangeVariableQueryClause : AQueryClause
{
- public readonly Block block;
+ LocatedToken variable;
protected Expression element_selector;
- protected ARangeVariableQueryClause (Block block, Expression expr, Location loc)
+ protected ARangeVariableQueryClause (LocatedToken variable, Expression expr, Location loc)
: base (expr, loc)
{
- this.block = block;
+ this.variable = variable;
}
protected virtual void AddSelectorArguments (EmitContext ec, ArrayList args, Parameter parentParameter,
//
public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parentParameter, TransparentIdentifiersScope ti)
{
- ICollection values = block.Variables.Values;
- if (values.Count != 1)
- throw new NotImplementedException ("Count != 1");
-
- IEnumerator enumerator = values.GetEnumerator ();
- enumerator.MoveNext ();
- LocalInfo li = (LocalInfo) enumerator.Current;
-
- Parameter parameter = new ImplicitQueryParameter (li);
- if (parentParameter == null)
- return next.BuildQueryClause (ec, expr, parameter, ti);
+ Parameter parameter = CreateBlockParameter (variable);
if (next != null) {
//
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.DeclContainer, loc);
+ element_selector = new AnonymousTypeDeclaration (transp_args, (TypeContainer) ec.TypeContainer, loc);
}
ArrayList args = new ArrayList ();
return lSide;
}
-
+
+ protected override void CloneTo (CloneContext clonectx, Expression target)
+ {
+ 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
//
public class Cast : QueryStartClause
{
+ // We don't have to clone cast type
readonly Expression type_expr;
public Cast (Expression type, Expression expr)
this.type_expr = type;
}
- protected override void CloneTo (CloneContext clonectx, Expression target)
- {
- // We don't have to clone cast type
- Cast t = (Cast) target;
- t.expr = expr.Clone (clonectx);
- }
-
public override Expression BuildQueryClause (EmitContext ec, Expression lSide, Parameter parameter, TransparentIdentifiersScope ti)
{
lSide = CreateQueryExpression (expr, new TypeArguments (loc, type_expr), null);
public class GroupBy : AQueryClause
{
- readonly Expression element_selector;
+ Expression element_selector;
public GroupBy (Expression elementSelector, Expression keySelector, Location loc)
: base (keySelector, loc)
return lSide;
}
+
+ protected override void CloneTo (CloneContext clonectx, Expression target)
+ {
+ GroupBy t = (GroupBy) target;
+ t.element_selector = element_selector.Clone (clonectx);
+ base.CloneTo (clonectx, t);
+ }
protected override string MethodName {
get { return "GroupBy"; }
Expression projection;
Expression inner_selector, outer_selector;
- public Join (Block block, Expression inner, Expression outerSelector, Expression innerSelector, Location loc)
- : base (block, inner, loc)
+ public Join (LocatedToken variable, Expression inner, Expression outerSelector, Expression innerSelector, Location loc)
+ : base (variable, inner, loc)
{
this.outer_selector = outerSelector;
this.inner_selector = innerSelector;
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.DeclContainer, loc);
+ projection = new AnonymousTypeDeclaration (join_args, (TypeContainer) ec.TypeContainer, loc);
}
args.Add (CreateSelectorArgument (ec, projection,
new Parameter [] { parentParameter, parameter }, ti));
}
+
+ 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);
+ base.CloneTo (clonectx, t);
+ }
protected virtual Parameter CreateResultSelectorParameter (Parameter parameter)
{
public class GroupJoin : Join
{
- string into_variable;
+ readonly LocatedToken into_variable;
- public GroupJoin (Block block, Expression inner, Expression outerSelector, Expression innerSelector,
- string into, Location loc)
- : base (block, inner, outerSelector, innerSelector, loc)
+ public GroupJoin (LocatedToken variable, Expression inner, Expression outerSelector, Expression innerSelector,
+ LocatedToken into, Location loc)
+ : base (variable, inner, outerSelector, innerSelector, loc)
{
this.into_variable = into;
}
// into variable is used as result selector and it's passed as
// transparent identifiers to the next clause
//
- return new ImplicitLambdaParameter (into_variable, loc);
+ return CreateBlockParameter (into_variable);
}
protected override string MethodName {
return e;
}
+
+ protected override void Error_InvalidInitializer (Expression initializer)
+ {
+ Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'",
+ Name, initializer.GetSignatureForError ());
+ }
}
- public Let (Block block, Expression expr, Location loc)
- : base (block, expr, loc)
+ public Let (LocatedToken variable, Expression expr, Location loc)
+ : base (variable, expr, loc)
{
}
public class SelectMany : ARangeVariableQueryClause
{
- public SelectMany (Block block, Expression expr)
- : base (block, expr, expr.Location)
+ public SelectMany (LocatedToken variable, Expression expr)
+ : base (variable, expr, expr.Location)
{
}
}
}
- readonly LocalInfo variable;
-
- public ImplicitQueryParameter (LocalInfo variable)
- : base (variable.Name, variable.Location)
- {
- this.variable = variable;
- }
-
- public override bool Resolve (IResolveContext ec)
+ public ImplicitQueryParameter (LocatedToken variable)
+ : base (variable.Value, variable.Location)
{
- if (!base.Resolve (ec))
- return false;
-
- variable.VariableType = parameter_type;
- return true;
}
}
public override Expression GetTransparentIdentifier (string name)
{
- if (transparent_identifiers == null)
- return null;
+ Expression expr = null;
+ if (transparent_identifiers != null)
+ expr = transparent_identifiers.GetIdentifier (name);
- return transparent_identifiers.GetIdentifier (name);
+ if (expr != null || Container == null)
+ return expr;
+
+ return Container.GetTransparentIdentifier (name);
+ }
+ }
+
+ //
+ // This block is actually never used, it is used by parser only
+ //
+ public class QueryBlock : Block
+ {
+ Hashtable range_variables = new Hashtable ();
+
+ public QueryBlock (Block parent, Location start)
+ : base (parent, start, Location.Null)
+ {
+ }
+
+ protected override void AddVariable (LocalInfo li)
+ {
+ string name = li.Name;
+ if (range_variables.Contains (name)) {
+ Location conflict = (Location)range_variables [name];
+ Report.SymbolRelatedToPreviousError (conflict, name);
+ Error_AlreadyDeclared (li.Location, name);
+ return;
+ }
+
+ range_variables.Add (name, li.Location);
+ }
+
+ 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_AlreadyDeclared (Location loc, string var)
+ {
+ Report.Error (1930, loc, "A range variable `{0}' has already been declared in this scope",
+ var);
+ }
+
+ protected override void Error_AlreadyDeclaredTypeParameter (Location loc, string name)
+ {
+ Report.Error (1948, loc, "A range variable `{0}' conflicts with a method type parameter",
+ name);
}
}
}