2
// lambda.cs: support for lambda expressions
4
// Authors: Miguel de Icaza (miguel@gnu.org)
5
// Marek Safar (marek.safar@gmail.com)
7
// Dual licensed under the terms of the MIT X11 or GNU GPL
9
// Copyright 2007-2008 Novell, Inc
13
using IKVM.Reflection.Emit;
15
using System.Reflection.Emit;
18
namespace Mono.CSharp {
19
public class LambdaExpression : AnonymousMethodExpression
22
// The parameters can either be:
23
// A list of Parameters (explicitly typed parameters)
24
// An ImplicitLambdaParameter
26
public LambdaExpression (Location loc)
31
protected override Expression CreateExpressionTree (ResolveContext ec, TypeSpec delegate_type)
33
if (ec.IsInProbingMode)
36
BlockContext bc = new BlockContext (ec.MemberContext, ec.ConstructorBlock, ec.BuiltinTypes.Void) {
37
CurrentAnonymousMethod = ec.CurrentAnonymousMethod
40
Expression args = Parameters.CreateExpressionTree (bc, loc);
41
Expression expr = Block.CreateExpressionTree (ec);
45
Arguments arguments = new Arguments (2);
46
arguments.Add (new Argument (expr));
47
arguments.Add (new Argument (args));
48
return CreateExpressionFactoryCall (ec, "Lambda",
49
new TypeArguments (new TypeExpression (delegate_type, loc)),
53
public override bool HasExplicitParameters {
55
return Parameters.Count > 0 && !(Parameters.FixedParameters [0] is ImplicitLambdaParameter);
59
protected override ParametersCompiled ResolveParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegateType)
61
if (!delegateType.IsDelegate)
64
AParametersCollection d_params = Delegate.GetParameters (delegateType);
66
if (HasExplicitParameters) {
67
if (!VerifyExplicitParameters (ec, delegateType, d_params))
74
// If L has an implicitly typed parameter list we make implicit parameters explicit
75
// Set each parameter of L is given the type of the corresponding parameter in D
77
if (!VerifyParameterCompatibility (ec, delegateType, d_params, ec.IsInProbingMode))
80
TypeSpec [] ptypes = new TypeSpec [Parameters.Count];
81
for (int i = 0; i < d_params.Count; i++) {
82
// D has no ref or out parameters
83
if ((d_params.FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) != 0)
86
TypeSpec d_param = d_params.Types [i];
89
// When type inference context exists try to apply inferred type arguments
92
d_param = tic.InflateGenericArgument (ec, d_param);
96
ImplicitLambdaParameter ilp = (ImplicitLambdaParameter) Parameters.FixedParameters [i];
97
ilp.SetParameterType (d_param);
98
ilp.Resolve (null, i);
101
Parameters.Types = ptypes;
105
protected override AnonymousMethodBody CompatibleMethodFactory (TypeSpec returnType, TypeSpec delegateType, ParametersCompiled p, ParametersBlock b)
107
return new LambdaMethod (p, b, returnType, delegateType, loc);
110
protected override bool DoResolveParameters (ResolveContext rc)
113
// Only explicit parameters can be resolved at this point
115
if (HasExplicitParameters) {
116
return Parameters.Resolve (rc);
122
public override string GetSignatureForError ()
124
return "lambda expression";
127
public override object Accept (StructuralVisitor visitor)
129
return visitor.Visit (this);
133
class LambdaMethod : AnonymousMethodBody
135
public LambdaMethod (ParametersCompiled parameters,
136
ParametersBlock block, TypeSpec return_type, TypeSpec delegate_type,
138
: base (parameters, block, return_type, delegate_type, loc)
144
public override string ContainerType {
146
return "lambda expression";
152
protected override void CloneTo (CloneContext clonectx, Expression target)
157
public override Expression CreateExpressionTree (ResolveContext ec)
159
BlockContext bc = new BlockContext (ec.MemberContext, Block, ReturnType);
160
Expression args = parameters.CreateExpressionTree (bc, loc);
161
Expression expr = Block.CreateExpressionTree (ec);
165
Arguments arguments = new Arguments (2);
166
arguments.Add (new Argument (expr));
167
arguments.Add (new Argument (args));
168
return CreateExpressionFactoryCall (ec, "Lambda",
169
new TypeArguments (new TypeExpression (type, loc)),
175
// This is a return statement that is prepended lambda expression bodies that happen
176
// to be expressions. Depending on the return type of the delegate this will behave
177
// as either { expr (); return (); } or { return expr (); }
179
public class ContextualReturn : Return
181
ExpressionStatement statement;
183
public ContextualReturn (Expression expr)
184
: base (expr, expr.Location)
188
public override Expression CreateExpressionTree (ResolveContext ec)
190
return Expr.CreateExpressionTree (ec);
193
public override void Emit (EmitContext ec)
195
if (statement != null) {
196
statement.EmitStatement (ec);
197
ec.Emit (OpCodes.Ret);
204
protected override bool DoResolve (BlockContext ec)
207
// When delegate returns void, only expression statements can be used
209
if (ec.ReturnType.Kind == MemberKind.Void) {
210
Expr = Expr.Resolve (ec);
214
statement = Expr as ExpressionStatement;
215
if (statement == null)
216
Expr.Error_InvalidExpressionStatement (ec);
221
return base.DoResolve (ec);