2 // lambda.cs: support for lambda expressions
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Marek Safar (marek.safar@gmail.com)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2007 Novell, Inc
13 using System.Collections;
14 using System.Reflection;
15 using System.Reflection.Emit;
17 namespace Mono.CSharp {
18 public class LambdaExpression : AnonymousMethodExpression
20 readonly bool explicit_parameters;
23 // The parameters can either be:
24 // A list of Parameters (explicitly typed parameters)
25 // An ImplicitLambdaParameter
27 public LambdaExpression (AnonymousMethodExpression parent,
28 GenericMethod generic, TypeContainer host,
29 Parameters parameters, Block container,
31 : base (parent, generic, host, parameters, container, loc)
33 if (parameters.Count > 0)
34 explicit_parameters = !(parameters.FixedParameters [0] is ImplicitLambdaParameter);
37 public override bool HasExplicitParameters {
39 return explicit_parameters;
43 protected override Parameters ResolveParameters (EmitContext ec, TypeInferenceContext tic, Type delegateType)
45 if (!TypeManager.IsDelegateType (delegateType))
48 ParameterData d_params = TypeManager.GetDelegateParameters (delegateType);
50 if (explicit_parameters) {
51 if (!VerifyExplicitParameters (delegateType, d_params, ec.IsInProbingMode))
58 // If L has an implicitly typed parameter list we make implicit parameters explicit
59 // Set each parameter of L is given the type of the corresponding parameter in D
61 if (!VerifyParameterCompatibility (delegateType, d_params, ec.IsInProbingMode))
64 if (Parameters.Types == null)
65 Parameters.Types = new Type [Parameters.Count];
67 for (int i = 0; i < d_params.Count; i++) {
68 // D has no ref or out parameters
69 if ((d_params.ParameterModifier (i) & Parameter.Modifier.ISBYREF) != 0)
72 Type d_param = d_params.Types [i];
75 // Blablabla, because reflection does not work with dynamic types
76 if (d_param.IsGenericParameter)
77 d_param = delegateType.GetGenericArguments () [d_param.GenericParameterPosition];
79 // When inferred context exists all generics parameters have type replacements
81 d_param = tic.InflateGenericArgument (d_param);
84 Parameters.Types [i] = Parameters.FixedParameters[i].ParameterType = d_param;
89 public override Expression DoResolve (EmitContext ec)
92 // Only explicit parameters can be resolved at this point
94 if (explicit_parameters) {
95 if (!Parameters.Resolve (ec))
99 eclass = ExprClass.Value;
100 type = TypeManager.anonymous_method_type;
104 protected override AnonymousMethod CompatibleMethodFactory (Type returnType, Type delegateType, Parameters p, ToplevelBlock b)
106 return new LambdaMethod (RootScope, Host,
107 GenericMethod, p, Container, b, returnType,
111 public override string GetSignatureForError ()
113 return "lambda expression";
117 public class LambdaMethod : AnonymousMethod
119 public LambdaMethod (RootScopeInfo root_scope,
120 DeclSpace host, GenericMethod generic,
121 Parameters parameters, Block container,
122 ToplevelBlock block, Type return_type, Type delegate_type,
124 : base (root_scope, host, generic, parameters, container, block,
125 return_type, delegate_type, loc)
129 public override string ContainerType {
131 return "lambda expression";
137 // This is a return statement that is prepended lambda expression bodies that happen
138 // to be expressions. Depending on the return type of the delegate this will behave
139 // as either { expr (); return (); } or { return expr (); }
141 public class ContextualReturn : Return
143 public ContextualReturn (Expression expr)
144 : base (expr, expr.Location)