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 System
.Reflection
;
14 using System
.Reflection
.Emit
;
16 namespace Mono
.CSharp
{
17 public class LambdaExpression
: AnonymousMethodExpression
20 // The parameters can either be:
21 // A list of Parameters (explicitly typed parameters)
22 // An ImplicitLambdaParameter
24 public LambdaExpression (Location loc
)
29 protected override Expression
CreateExpressionTree (ResolveContext ec
, Type delegate_type
)
31 if (ec
.IsInProbingMode
)
34 BlockContext bc
= new BlockContext (ec
.MemberContext
, ec
.CurrentBlock
.Explicit
, TypeManager
.void_type
) {
35 CurrentAnonymousMethod
= ec
.CurrentAnonymousMethod
38 Expression args
= Parameters
.CreateExpressionTree (bc
, loc
);
39 Expression expr
= Block
.CreateExpressionTree (ec
);
43 Arguments arguments
= new Arguments (2);
44 arguments
.Add (new Argument (expr
));
45 arguments
.Add (new Argument (args
));
46 return CreateExpressionFactoryCall (ec
, "Lambda",
47 new TypeArguments (new TypeExpression (delegate_type
, loc
)),
51 public override bool HasExplicitParameters
{
53 return Parameters
.Count
> 0 && !(Parameters
.FixedParameters
[0] is ImplicitLambdaParameter
);
57 protected override ParametersCompiled
ResolveParameters (ResolveContext ec
, TypeInferenceContext tic
, Type delegateType
)
59 if (!TypeManager
.IsDelegateType (delegateType
))
62 AParametersCollection d_params
= TypeManager
.GetDelegateParameters (ec
, delegateType
);
64 if (HasExplicitParameters
) {
65 if (!VerifyExplicitParameters (ec
, delegateType
, d_params
))
72 // If L has an implicitly typed parameter list we make implicit parameters explicit
73 // Set each parameter of L is given the type of the corresponding parameter in D
75 if (!VerifyParameterCompatibility (ec
, delegateType
, d_params
, ec
.IsInProbingMode
))
78 Type
[] ptypes
= new Type
[Parameters
.Count
];
79 for (int i
= 0; i
< d_params
.Count
; i
++) {
80 // D has no ref or out parameters
81 if ((d_params
.FixedParameters
[i
].ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
84 Type d_param
= d_params
.Types
[i
];
87 // Blablabla, because reflection does not work with dynamic types
88 if (d_param
.IsGenericParameter
)
89 d_param
= delegateType
.GetGenericArguments () [d_param
.GenericParameterPosition
];
92 // When type inference context exists try to apply inferred type arguments
95 d_param
= tic
.InflateGenericArgument (d_param
);
99 ((ImplicitLambdaParameter
) Parameters
.FixedParameters
[i
]).Type
= d_param
;
102 Parameters
.Types
= ptypes
;
106 protected override Expression
DoResolve (ResolveContext ec
)
109 // Only explicit parameters can be resolved at this point
111 if (HasExplicitParameters
) {
112 if (!Parameters
.Resolve (ec
))
116 eclass
= ExprClass
.Value
;
117 type
= InternalType
.AnonymousMethod
;
121 protected override AnonymousMethodBody
CompatibleMethodFactory (Type returnType
, Type delegateType
, ParametersCompiled p
, ToplevelBlock b
)
123 return new LambdaMethod (p
, b
, returnType
, delegateType
, loc
);
126 public override string GetSignatureForError ()
128 return "lambda expression";
132 public class LambdaMethod
: AnonymousMethodBody
134 public LambdaMethod (ParametersCompiled parameters
,
135 ToplevelBlock block
, Type return_type
, Type delegate_type
,
137 : base (parameters
, block
, return_type
, delegate_type
, loc
)
141 protected override void CloneTo (CloneContext clonectx
, Expression target
)
146 public override string ContainerType
{
148 return "lambda expression";
152 public override Expression
CreateExpressionTree (ResolveContext ec
)
154 BlockContext bc
= new BlockContext (ec
.MemberContext
, Block
, ReturnType
);
155 Expression args
= parameters
.CreateExpressionTree (bc
, loc
);
156 Expression expr
= Block
.CreateExpressionTree (ec
);
160 Arguments arguments
= new Arguments (2);
161 arguments
.Add (new Argument (expr
));
162 arguments
.Add (new Argument (args
));
163 return CreateExpressionFactoryCall (ec
, "Lambda",
164 new TypeArguments (new TypeExpression (type
, loc
)),
170 // This is a return statement that is prepended lambda expression bodies that happen
171 // to be expressions. Depending on the return type of the delegate this will behave
172 // as either { expr (); return (); } or { return expr (); }
174 public class ContextualReturn
: Return
176 ExpressionStatement statement
;
178 public ContextualReturn (Expression expr
)
179 : base (expr
, expr
.Location
)
183 public override Expression
CreateExpressionTree (ResolveContext ec
)
185 return Expr
.CreateExpressionTree (ec
);
188 public override void Emit (EmitContext ec
)
190 if (statement
!= null) {
191 statement
.EmitStatement (ec
);
192 ec
.ig
.Emit (OpCodes
.Ret
);
199 protected override bool DoResolve (BlockContext ec
)
202 // When delegate returns void, only expression statements can be used
204 if (ec
.ReturnType
== TypeManager
.void_type
) {
205 Expr
= Expr
.Resolve (ec
);
209 statement
= Expr
as ExpressionStatement
;
210 if (statement
== null)
211 Expr
.Error_InvalidExpressionStatement (ec
);
216 return base.DoResolve (ec
);