[sgen] Throw OOM also from the managed allocator
[mono.git] / mcs / class / referencesource / System.Core / Microsoft / Scripting / Ast / LambdaExpression.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
6  * copy of the license can be found in the License.html file at the root of this distribution. If 
7  * you cannot locate the  Apache License, Version 2.0, please send an email to 
8  * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
9  * by the terms of the Apache License, Version 2.0.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15
16 using System;
17 using System.Collections.Generic;
18 using System.Collections.ObjectModel;
19 using System.Diagnostics;
20 using System.Dynamic.Utils;
21 using System.Reflection;
22 using System.Reflection.Emit;
23 using System.Threading;
24 using System.Runtime.CompilerServices;
25
26 #if SILVERLIGHT
27 using System.Core;
28 #endif
29
30 #if CLR2
31 namespace Microsoft.Scripting.Ast {
32 #else
33 namespace System.Linq.Expressions {
34 #endif
35     using Compiler;
36
37     /// <summary>
38     /// Creates a <see cref="LambdaExpression"/> node.
39     /// This captures a block of code that is similar to a .NET method body.
40     /// </summary>
41     /// <remarks>
42     /// Lambda expressions take input through parameters and are expected to be fully bound. 
43     /// </remarks>
44 #if !SILVERLIGHT
45     [DebuggerTypeProxy(typeof(Expression.LambdaExpressionProxy))]
46 #endif
47     public abstract class LambdaExpression : Expression {
48         private readonly string _name;
49         private readonly Expression _body;
50         private readonly ReadOnlyCollection<ParameterExpression> _parameters;
51         private readonly Type _delegateType;
52         private readonly bool _tailCall;
53
54         internal LambdaExpression(
55             Type delegateType,
56             string name,
57             Expression body,
58             bool tailCall,
59             ReadOnlyCollection<ParameterExpression> parameters
60         ) {
61
62             Debug.Assert(delegateType != null);
63
64             _name = name;
65             _body = body;
66             _parameters = parameters;
67             _delegateType = delegateType;
68             _tailCall = tailCall;
69         }
70
71         /// <summary>
72         /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
73         /// </summary>
74         /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
75         public sealed override Type Type {
76             get { return _delegateType; }
77         }
78
79         /// <summary>
80         /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
81         /// </summary>
82         /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
83         public sealed override ExpressionType NodeType {
84             get { return ExpressionType.Lambda; }
85         }
86
87         /// <summary>
88         /// Gets the parameters of the lambda expression. 
89         /// </summary>
90         public ReadOnlyCollection<ParameterExpression> Parameters {
91             get { return _parameters; }
92         }
93
94         /// <summary>
95         /// Gets the name of the lambda expression. 
96         /// </summary>
97         /// <remarks>Used for debugging purposes.</remarks>
98         public string Name {
99             get { return _name; }
100         }
101
102         /// <summary>
103         /// Gets the body of the lambda expression. 
104         /// </summary>
105         public Expression Body {
106             get { return _body; }
107         }
108
109         /// <summary>
110         /// Gets the return type of the lambda expression. 
111         /// </summary>
112         public Type ReturnType {
113             get { return Type.GetMethod("Invoke").ReturnType; }
114         }
115
116         /// <summary>
117         /// Gets the value that indicates if the lambda expression will be compiled with
118         /// tail call optimization. 
119         /// </summary>
120         public bool TailCall {
121             get { return _tailCall; }
122         }
123
124         /// <summary>
125         /// Produces a delegate that represents the lambda expression.
126         /// </summary>
127         /// <returns>A delegate containing the compiled version of the lambda.</returns>
128         public Delegate Compile() {
129             return LambdaCompiler.Compile(this, null);
130         }
131
132         /// <summary>
133         /// Produces a delegate that represents the lambda expression.
134         /// </summary>
135         /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
136         /// <returns>A delegate containing the compiled version of the lambda.</returns>
137         public Delegate Compile(DebugInfoGenerator debugInfoGenerator) {
138             ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator");
139             return LambdaCompiler.Compile(this, debugInfoGenerator);
140         }
141
142 #if NETSTANDARD
143         public Delegate Compile(bool preferInterpretation) {
144             // TODO: add logic for preferInterpretation
145             return Compile();
146         }
147 #endif
148
149         /// <summary>
150         /// Compiles the lambda into a method definition.
151         /// </summary>
152         /// <param name="method">A <see cref="MethodBuilder"/> which will be used to hold the lambda's IL.</param>
153         public void CompileToMethod(MethodBuilder method) {
154             CompileToMethodInternal(method, null);
155         }
156
157         /// <summary>
158         /// Compiles the lambda into a method definition and custom debug information.
159         /// </summary>
160         /// <param name="method">A <see cref="MethodBuilder"/> which will be used to hold the lambda's IL.</param>
161         /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
162         public void CompileToMethod(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) {
163             ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator");
164             CompileToMethodInternal(method, debugInfoGenerator);
165         }
166
167         private void CompileToMethodInternal(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) {
168             ContractUtils.RequiresNotNull(method, "method");
169             ContractUtils.Requires(method.IsStatic, "method");
170             var type = method.DeclaringType as TypeBuilder;
171             if (type == null) throw Error.MethodBuilderDoesNotHaveTypeBuilder();
172
173             LambdaCompiler.Compile(this, method, debugInfoGenerator);
174         }
175
176         internal abstract LambdaExpression Accept(StackSpiller spiller);
177     }
178
179     /// <summary>
180     /// Defines a <see cref="Expression{TDelegate}"/> node.
181     /// This captures a block of code that is similar to a .NET method body.
182     /// </summary>
183     /// <typeparam name="TDelegate">The type of the delegate.</typeparam>
184     /// <remarks>
185     /// Lambda expressions take input through parameters and are expected to be fully bound. 
186     /// </remarks>
187     public sealed class Expression<TDelegate> : LambdaExpression {
188         internal Expression(Expression body, string name, bool tailCall, ReadOnlyCollection<ParameterExpression> parameters)
189             : base(typeof(TDelegate), name, body, tailCall, parameters) {
190         }
191
192         /// <summary>
193         /// Produces a delegate that represents the lambda expression.
194         /// </summary>
195         /// <returns>A delegate containing the compiled version of the lambda.</returns>
196         public new TDelegate Compile() {
197             return (TDelegate)(object)LambdaCompiler.Compile(this, null);
198         }
199
200         /// <summary>
201         /// Produces a delegate that represents the lambda expression.
202         /// </summary>
203         /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
204         /// <returns>A delegate containing the compiled version of the lambda.</returns>
205         public new TDelegate Compile(DebugInfoGenerator debugInfoGenerator) {
206             ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator");
207             return (TDelegate)(object)LambdaCompiler.Compile(this, debugInfoGenerator);
208         }
209
210 #if NETSTANDARD
211         public new TDelegate Compile(bool preferInterpretation) {
212             // TODO: add logic for preferInterpretation
213             return Compile();
214         }
215 #endif
216
217         /// <summary>
218         /// Creates a new expression that is like this one, but using the
219         /// supplied children. If all of the children are the same, it will
220         /// return this expression.
221         /// </summary>
222         /// <param name="body">The <see cref="LambdaExpression.Body">Body</see> property of the result.</param>
223         /// <param name="parameters">The <see cref="LambdaExpression.Parameters">Parameters</see> property of the result.</param>
224         /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
225         public Expression<TDelegate> Update(Expression body, IEnumerable<ParameterExpression> parameters) {
226             if (body == Body && parameters == Parameters) {
227                 return this;
228             }
229             return Expression.Lambda<TDelegate>(body, Name, TailCall, parameters);
230         }
231
232         /// <summary>
233         /// Dispatches to the specific visit method for this node type.
234         /// </summary>
235         protected internal override Expression Accept(ExpressionVisitor visitor) {
236             return visitor.VisitLambda(this);
237         }
238
239         internal override LambdaExpression Accept(StackSpiller spiller) {
240             return spiller.Rewrite(this);
241         }
242
243         internal static LambdaExpression Create(Expression body, string name, bool tailCall, ReadOnlyCollection<ParameterExpression> parameters) {
244             return new Expression<TDelegate>(body, name, tailCall, parameters);
245         }
246     }
247
248
249     public partial class Expression {
250
251         /// <summary>
252         /// Creates an Expression{T} given the delegate type. Caches the
253         /// factory method to speed up repeated creations for the same T.
254         /// </summary>
255         internal static LambdaExpression CreateLambda(Type delegateType, Expression body, string name, bool tailCall, ReadOnlyCollection<ParameterExpression> parameters) {
256             // Get or create a delegate to the public Expression.Lambda<T>
257             // method and call that will be used for creating instances of this
258             // delegate type
259             LambdaFactory fastPath;
260             var factories = _LambdaFactories;
261             if (factories == null) {
262                 _LambdaFactories = factories = new CacheDict<Type, LambdaFactory>(50);
263             }
264
265             MethodInfo create = null;
266             if (!factories.TryGetValue(delegateType, out fastPath)) {
267                 create = typeof(Expression<>).MakeGenericType(delegateType).GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic);
268                 if (TypeUtils.CanCache(delegateType)) {
269                     factories[delegateType] = fastPath = (LambdaFactory)Delegate.CreateDelegate(typeof(LambdaFactory), create);
270                 }
271             }
272
273             if (fastPath != null) {
274                 return fastPath(body, name, tailCall, parameters);
275             }
276             
277             Debug.Assert(create != null);
278             return (LambdaExpression)create.Invoke(null, new object[] { body, name, tailCall, parameters });
279         }
280
281         /// <summary>
282         /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time. 
283         /// </summary>
284         /// <typeparam name="TDelegate">The delegate type. </typeparam>
285         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
286         /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
287         /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
288         public static Expression<TDelegate> Lambda<TDelegate>(Expression body, params ParameterExpression[] parameters) {
289             return Lambda<TDelegate>(body, false, (IEnumerable<ParameterExpression>)parameters);
290         }
291
292         /// <summary>
293         /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time. 
294         /// </summary>
295         /// <typeparam name="TDelegate">The delegate type. </typeparam>
296         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
297         /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
298         /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
299         /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
300         public static Expression<TDelegate> Lambda<TDelegate>(Expression body, bool tailCall, params ParameterExpression[] parameters) {
301             return Lambda<TDelegate>(body, tailCall, (IEnumerable<ParameterExpression>)parameters);
302         }
303
304         /// <summary>
305         /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time. 
306         /// </summary>
307         /// <typeparam name="TDelegate">The delegate type. </typeparam>
308         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
309         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
310         /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
311         public static Expression<TDelegate> Lambda<TDelegate>(Expression body, IEnumerable<ParameterExpression> parameters) {
312             return Lambda<TDelegate>(body, null, false, parameters);
313         }
314
315         /// <summary>
316         /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time. 
317         /// </summary>
318         /// <typeparam name="TDelegate">The delegate type. </typeparam>
319         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
320         /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
321         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
322         /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
323         public static Expression<TDelegate> Lambda<TDelegate>(Expression body, bool tailCall, IEnumerable<ParameterExpression> parameters) {
324             return Lambda<TDelegate>(body, null, tailCall, parameters);
325         }
326
327         /// <summary>
328         /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time. 
329         /// </summary>
330         /// <typeparam name="TDelegate">The delegate type. </typeparam>
331         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
332         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
333         /// <param name="name">The name of the lambda. Used for generating debugging info.</param>
334         /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
335         public static Expression<TDelegate> Lambda<TDelegate>(Expression body, String name, IEnumerable<ParameterExpression> parameters) {
336             return Lambda<TDelegate>(body, name, false, parameters);
337         }
338
339         /// <summary>
340         /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time. 
341         /// </summary>
342         /// <typeparam name="TDelegate">The delegate type. </typeparam>
343         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
344         /// <param name="name">The name of the lambda. Used for generating debugging info.</param>
345         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
346         /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
347         /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
348         public static Expression<TDelegate> Lambda<TDelegate>(Expression body, String name, bool tailCall, IEnumerable<ParameterExpression> parameters) {
349             var parameterList = parameters.ToReadOnly();
350             ValidateLambdaArgs(typeof(TDelegate), ref body, parameterList);
351             return new Expression<TDelegate>(body, name, tailCall, parameterList);
352         }
353
354
355         /// <summary>
356         /// Creates a LambdaExpression by first constructing a delegate type. 
357         /// </summary>
358         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
359         /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
360         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
361         public static LambdaExpression Lambda(Expression body, params ParameterExpression[] parameters) {
362             return Lambda(body, false, (IEnumerable<ParameterExpression>)parameters);
363         }
364
365         /// <summary>
366         /// Creates a LambdaExpression by first constructing a delegate type. 
367         /// </summary>
368         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
369         /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
370         /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
371         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
372         public static LambdaExpression Lambda(Expression body, bool tailCall, params ParameterExpression[] parameters) {
373             return Lambda(body, tailCall, (IEnumerable<ParameterExpression>)parameters);
374         }
375
376         /// <summary>
377         /// Creates a LambdaExpression by first constructing a delegate type. 
378         /// </summary>
379         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
380         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
381         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
382         public static LambdaExpression Lambda(Expression body, IEnumerable<ParameterExpression> parameters) {
383             return Lambda(body, null, false, parameters);
384         }
385
386         /// <summary>
387         /// Creates a LambdaExpression by first constructing a delegate type. 
388         /// </summary>
389         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
390         /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
391         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
392         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
393         public static LambdaExpression Lambda(Expression body, bool tailCall, IEnumerable<ParameterExpression> parameters) {
394             return Lambda(body, null, tailCall, parameters);
395         }
396
397         /// <summary>
398         /// Creates a LambdaExpression by first constructing a delegate type. 
399         /// </summary>
400         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
401         /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
402         /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
403         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
404         public static LambdaExpression Lambda(Type delegateType, Expression body, params ParameterExpression[] parameters) {
405             return Lambda(delegateType, body, null, false, parameters);
406         }
407
408         /// <summary>
409         /// Creates a LambdaExpression by first constructing a delegate type. 
410         /// </summary>
411         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
412         /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
413         /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
414         /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
415         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
416         public static LambdaExpression Lambda(Type delegateType, Expression body, bool tailCall, params ParameterExpression[] parameters) {
417             return Lambda(delegateType, body, null, tailCall, parameters);
418         }
419
420         /// <summary>
421         /// Creates a LambdaExpression by first constructing a delegate type. 
422         /// </summary>
423         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
424         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
425         /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
426         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
427         public static LambdaExpression Lambda(Type delegateType, Expression body, IEnumerable<ParameterExpression> parameters) {
428             return Lambda(delegateType, body, null, false, parameters);
429         }
430
431         /// <summary>
432         /// Creates a LambdaExpression by first constructing a delegate type. 
433         /// </summary>
434         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
435         /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
436         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
437         /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
438         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
439         public static LambdaExpression Lambda(Type delegateType, Expression body, bool tailCall, IEnumerable<ParameterExpression> parameters) {
440             return Lambda(delegateType, body, null, tailCall, parameters);
441         }
442
443         /// <summary>
444         /// Creates a LambdaExpression by first constructing a delegate type. 
445         /// </summary>
446         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
447         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
448         /// <param name="name">The name for the lambda. Used for emitting debug information.</param>
449         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
450         public static LambdaExpression Lambda(Expression body, string name, IEnumerable<ParameterExpression> parameters) {
451             return Lambda(body, name, false, parameters);
452         }
453
454         /// <summary>
455         /// Creates a LambdaExpression by first constructing a delegate type. 
456         /// </summary>
457         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
458         /// <param name="name">The name for the lambda. Used for emitting debug information.</param>
459         /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
460         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
461         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
462         public static LambdaExpression Lambda(Expression body, string name, bool tailCall, IEnumerable<ParameterExpression> parameters) {
463             ContractUtils.RequiresNotNull(body, "body");
464
465             var parameterList = parameters.ToReadOnly();
466
467             int paramCount = parameterList.Count;
468             Type[] typeArgs = new Type[paramCount + 1];
469             if (paramCount > 0) {
470                 var set = new Set<ParameterExpression>(parameterList.Count);
471                 for (int i = 0; i < paramCount; i++) {
472                     var param = parameterList[i];
473                     ContractUtils.RequiresNotNull(param, "parameter");
474                     typeArgs[i] = param.IsByRef ? param.Type.MakeByRefType() : param.Type;
475                     if (set.Contains(param)) {
476                         throw Error.DuplicateVariable(param);
477                     }
478                     set.Add(param);
479                 }
480             }
481             typeArgs[paramCount] = body.Type;
482
483             Type delegateType = DelegateHelpers.MakeDelegateType(typeArgs);
484
485             return CreateLambda(delegateType, body, name, tailCall, parameterList);
486         }
487
488         /// <summary>
489         /// Creates a LambdaExpression by first constructing a delegate type. 
490         /// </summary>
491         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
492         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
493         /// <param name="name">The name for the lambda. Used for emitting debug information.</param>
494         /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
495         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
496         public static LambdaExpression Lambda(Type delegateType, Expression body, string name, IEnumerable<ParameterExpression> parameters) {
497             var paramList = parameters.ToReadOnly();
498             ValidateLambdaArgs(delegateType, ref body, paramList);
499
500             return CreateLambda(delegateType, body, name, false, paramList);
501         }
502
503         /// <summary>
504         /// Creates a LambdaExpression by first constructing a delegate type. 
505         /// </summary>
506         /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
507         /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
508         /// <param name="name">The name for the lambda. Used for emitting debug information.</param>
509         /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
510         /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
511         /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
512         public static LambdaExpression Lambda(Type delegateType, Expression body, string name, bool tailCall, IEnumerable<ParameterExpression> parameters) {
513             var paramList = parameters.ToReadOnly();
514             ValidateLambdaArgs(delegateType, ref body, paramList);
515
516             return CreateLambda(delegateType, body, name, tailCall, paramList);
517         }
518
519         private static void ValidateLambdaArgs(Type delegateType, ref Expression body, ReadOnlyCollection<ParameterExpression> parameters) {
520             ContractUtils.RequiresNotNull(delegateType, "delegateType");
521             RequiresCanRead(body, "body");
522
523             if (!typeof(MulticastDelegate).IsAssignableFrom(delegateType) || delegateType == typeof(MulticastDelegate)) {
524                 throw Error.LambdaTypeMustBeDerivedFromSystemDelegate();
525             }
526
527             MethodInfo mi;
528             var ldc = _LambdaDelegateCache;
529             if (!ldc.TryGetValue(delegateType, out mi)) {
530                 mi = delegateType.GetMethod("Invoke");
531                 if (TypeUtils.CanCache(delegateType)) {
532                     ldc[delegateType] = mi;
533                 }
534             }
535
536             ParameterInfo[] pis = mi.GetParametersCached();
537
538             if (pis.Length > 0) {
539                 if (pis.Length != parameters.Count) {
540                     throw Error.IncorrectNumberOfLambdaDeclarationParameters();
541                 }
542                 var set = new Set<ParameterExpression>(pis.Length);
543                 for (int i = 0, n = pis.Length; i < n; i++) {
544                     ParameterExpression pex = parameters[i];
545                     ParameterInfo pi = pis[i];
546                     RequiresCanRead(pex, "parameters");
547                     Type pType = pi.ParameterType;
548                     if (pex.IsByRef) {
549                         if (!pType.IsByRef) {
550                             //We cannot pass a parameter of T& to a delegate that takes T or any non-ByRef type.
551                             throw Error.ParameterExpressionNotValidAsDelegate(pex.Type.MakeByRefType(), pType);
552                         }
553                         pType = pType.GetElementType();
554                     }
555                     if (!TypeUtils.AreReferenceAssignable(pex.Type, pType)) {
556                         throw Error.ParameterExpressionNotValidAsDelegate(pex.Type, pType);
557                     }
558                     if (set.Contains(pex)) {
559                         throw Error.DuplicateVariable(pex);
560                     }
561                     set.Add(pex);
562                 }
563             } else if (parameters.Count > 0) {
564                 throw Error.IncorrectNumberOfLambdaDeclarationParameters();
565             }
566             if (mi.ReturnType != typeof(void) && !TypeUtils.AreReferenceAssignable(mi.ReturnType, body.Type)) {
567                 if (!TryQuote(mi.ReturnType, ref body)) {
568                     throw Error.ExpressionTypeDoesNotMatchReturn(body.Type, mi.ReturnType);
569                 }
570             }
571         }
572
573         private static bool ValidateTryGetFuncActionArgs(Type[] typeArgs) {
574             if (typeArgs == null) {
575                 throw new ArgumentNullException("typeArgs");
576             }
577             for (int i = 0, n = typeArgs.Length; i < n; i++) {
578                 var a = typeArgs[i];
579                 if (a == null) {
580                     throw new ArgumentNullException("typeArgs");
581                 }
582                 if (a.IsByRef) {
583                     return false;
584                 }
585             }
586             return true;
587         }
588
589         /// <summary>
590         /// Creates a <see cref="Type"/> object that represents a generic System.Func delegate type that has specific type arguments.
591         /// The last type argument specifies the return type of the created delegate.
592         /// </summary>
593         /// <param name="typeArgs">An array of Type objects that specify the type arguments for the System.Func delegate type.</param>
594         /// <returns>The type of a System.Func delegate that has the specified type arguments.</returns>
595         public static Type GetFuncType(params Type[] typeArgs) {
596             if (!ValidateTryGetFuncActionArgs(typeArgs)) throw Error.TypeMustNotBeByRef();
597
598             Type result = DelegateHelpers.GetFuncType(typeArgs);
599             if (result == null) {
600                 throw Error.IncorrectNumberOfTypeArgsForFunc();
601             }
602             return result;
603         }
604
605         /// <summary>
606         /// Creates a <see cref="Type"/> object that represents a generic System.Func delegate type that has specific type arguments.
607         /// The last type argument specifies the return type of the created delegate.
608         /// </summary>
609         /// <param name="typeArgs">An array of Type objects that specify the type arguments for the System.Func delegate type.</param>
610         /// <param name="funcType">When this method returns, contains the generic System.Func delegate type that has specific type arguments. Contains null if there is no generic System.Func delegate that matches the <paramref name="typeArgs"/>.This parameter is passed uninitialized.</param>
611         /// <returns>true if generic System.Func delegate type was created for specific <paramref name="typeArgs"/>; false otherwise.</returns>
612         public static bool TryGetFuncType(Type[] typeArgs, out Type funcType) {
613             if (ValidateTryGetFuncActionArgs(typeArgs)) {
614                 return (funcType = DelegateHelpers.GetFuncType(typeArgs)) != null;
615             }
616             funcType = null;
617             return false;
618         }
619
620         /// <summary>
621         /// Creates a <see cref="Type"/> object that represents a generic System.Action delegate type that has specific type arguments. 
622         /// </summary>
623         /// <param name="typeArgs">An array of Type objects that specify the type arguments for the System.Action delegate type.</param>
624         /// <returns>The type of a System.Action delegate that has the specified type arguments.</returns>
625         public static Type GetActionType(params Type[] typeArgs) {
626             if (!ValidateTryGetFuncActionArgs(typeArgs)) throw Error.TypeMustNotBeByRef();
627
628             Type result = DelegateHelpers.GetActionType(typeArgs);
629             if (result == null) {
630                 throw Error.IncorrectNumberOfTypeArgsForAction();
631             }
632             return result;
633         }
634
635         /// <summary>
636         /// Creates a <see cref="Type"/> object that represents a generic System.Action delegate type that has specific type arguments.
637         /// </summary>
638         /// <param name="typeArgs">An array of Type objects that specify the type arguments for the System.Action delegate type.</param>
639         /// <param name="actionType">When this method returns, contains the generic System.Action delegate type that has specific type arguments. Contains null if there is no generic System.Action delegate that matches the <paramref name="typeArgs"/>.This parameter is passed uninitialized.</param>
640         /// <returns>true if generic System.Action delegate type was created for specific <paramref name="typeArgs"/>; false otherwise.</returns>
641         public static bool TryGetActionType(Type[] typeArgs, out Type actionType) {
642             if (ValidateTryGetFuncActionArgs(typeArgs)) {
643                 return (actionType = DelegateHelpers.GetActionType(typeArgs)) != null;
644             }
645             actionType = null;
646             return false;
647         }
648
649         /// <summary>
650         /// Gets a <see cref="Type"/> object that represents a generic System.Func or System.Action delegate type that has specific type arguments.
651         /// The last type argument determines the return type of the delegate. If no Func or Action is large enough, it will generate a custom
652         /// delegate type.
653         /// </summary>
654         /// <param name="typeArgs">The type arguments of the delegate.</param>
655         /// <returns>The delegate type.</returns>
656         /// <remarks>
657         /// As with Func, the last argument is the return type. It can be set
658         /// to System.Void to produce an Action.</remarks>
659         public static Type GetDelegateType(params Type[] typeArgs) {
660             ContractUtils.RequiresNotEmpty(typeArgs, "typeArgs");
661             ContractUtils.RequiresNotNullItems(typeArgs, "typeArgs");
662             return DelegateHelpers.MakeDelegateType(typeArgs);
663         }
664     }
665 }