2 // lambda.cs: support for lambda expressions
4 // Authors: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2007 Novell, Inc
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
16 namespace Mono.CSharp {
17 public class LambdaExpression : AnonymousMethodExpression {
18 bool explicit_parameters;
21 // The parameters can either be:
22 // A list of Parameters (explicitly typed parameters)
23 // An ImplicitLambdaParameter
25 public LambdaExpression (AnonymousMethodExpression parent,
26 GenericMethod generic, TypeContainer host,
27 Parameters parameters, Block container,
29 : base (parent, generic, host, parameters, container, loc)
31 if (parameters.FixedParameters.Length > 0)
32 explicit_parameters = parameters.FixedParameters [0].TypeName != null;
35 public override bool HasExplicitParameters {
37 return explicit_parameters;
41 protected override Parameters CreateParameters (EmitContext ec, Type delegateType, ParameterData delegateParameters)
43 Parameters p = base.CreateParameters (ec, delegateType, delegateParameters);
44 if (explicit_parameters)
48 // If L has an implicitly typed parameter list
50 for (int i = 0; i < delegateParameters.Count; i++) {
51 // D has no ref or out parameters
52 //if ((invoke_pd.ParameterModifier (i) & Parameter.Modifier.ISBYREF) != 0)
56 // Makes implicit parameters explicit
57 // Set each parameter of L is given the type of the corresponding parameter in D
59 p[i].ParameterType = delegateParameters.Types[i];
64 public override Expression DoResolve (EmitContext ec)
67 // Only explicit parameters can be resolved at this point
69 if (explicit_parameters) {
70 if (!Parameters.Resolve (ec))
74 eclass = ExprClass.Value;
75 type = TypeManager.anonymous_method_type;
80 // Returns true if the body of lambda expression can be implicitly
81 // converted to the delegate of type `delegate_type'
83 public override bool ImplicitStandardConversionExists (Type delegate_type)
85 EmitContext ec = EmitContext.TempEc;
87 using (ec.Set (EmitContext.Flags.ProbingMode)) {
88 bool r = Compatible (ec, delegate_type) != null;
98 // Resolves a body of lambda expression.
100 protected override Expression ResolveMethod (EmitContext ec, Parameters parameters, Type returnType, Type delegateType)
102 ToplevelBlock b = ec.IsInProbingMode ? (ToplevelBlock) Block.PerformClone () : Block;
104 anonymous = new LambdaMethod (
105 Parent != null ? Parent.AnonymousMethod : null, RootScope, Host,
106 GenericMethod, Parameters, Container, b, returnType,
110 if (ec.IsInProbingMode)
111 r = anonymous.ResolveNoDefine (ec);
113 r = anonymous.Resolve (ec);
115 // Resolution failed.
119 return anonymous.AnonymousDelegate;
122 public override string GetSignatureForError ()
124 return "lambda expression";
128 // TryBuild: tries to compile this LambdaExpression with the given
129 // types as the lambda expression parameter types.
131 // If the lambda expression successfully builds with those types, the
132 // return value will be the inferred type for the lambda expression,
133 // otherwise the result will be null.
135 public Type TryBuild (EmitContext ec, Type [] types)
137 for (int i = 0; i < types.Length; i++)
138 Parameters [i].TypeName = new TypeExpression (types [i], Parameters [i].Location);
140 // TODO: temporary hack
141 ec.InferReturnType = true;
144 using (ec.Set (EmitContext.Flags.ProbingMode)) {
145 e = ResolveMethod (ec, Parameters, typeof (LambdaExpression), null);
156 // This is a return statement that is prepended lambda expression bodies that happen
157 // to be expressions. Depending on the return type of the delegate this will behave
158 // as either { expr (); return (); } or { return expr (); }
160 public class ContextualReturn : Return
162 public ContextualReturn (Expression expr)
163 : base (expr, expr.Location)