1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 | /* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
#if CODEPLEX_40
using System;
#else
using System; using Microsoft;
#endif
using System.Collections.Generic;
#if CODEPLEX_40
using System.Dynamic;
using System.Linq.Expressions;
#else
using Microsoft.Scripting;
using Microsoft.Linq.Expressions;
#endif
using System.Reflection;
using Microsoft.Scripting.Utils;
namespace Microsoft.Scripting.Actions.Calls {
#if CODEPLEX_40
using Ast = System.Linq.Expressions.Expression;
#else
using Ast = Microsoft.Linq.Expressions.Expression;
#endif
internal sealed class ParamsArgBuilder : ArgBuilder {
private readonly int _start;
private readonly int _count;
private readonly Type _elementType;
public ParamsArgBuilder(ParameterInfo info, Type elementType, int start, int count)
: base(info) {
ContractUtils.RequiresNotNull(elementType, "elementType");
ContractUtils.Requires(start >= 0, "start");
ContractUtils.Requires(count >= 0, "count");
_start = start;
_count = count;
_elementType = elementType;
}
public override int Priority {
get { return 4; }
}
internal protected override Expression ToExpression(ParameterBinder parameterBinder, IList<Expression> parameters, bool[] hasBeenUsed) {
List<Expression> elems = new List<Expression>(_count);
for (int i = _start; i < _start + _count; i++) {
if (!hasBeenUsed[i]) {
elems.Add(parameterBinder.ConvertExpression(parameters[i], ParameterInfo, _elementType));
hasBeenUsed[i] = true;
}
}
return Ast.NewArrayInit(_elementType, elems);
}
protected internal override Func<object[], object> ToDelegate(ParameterBinder parameterBinder, IList<DynamicMetaObject> knownTypes, bool[] hasBeenUsed) {
List<Func<object[], object>> indexes = new List<Func<object[], object>>(_count);
for (int i = _start; i < _start + _count; i++) {
if (!hasBeenUsed[i]) {
indexes.Add(parameterBinder.ConvertObject(i + 1, knownTypes[i], ParameterInfo, _elementType));
hasBeenUsed[i] = true;
}
}
if (_elementType == typeof(object)) {
return new ParamArrayDelegate<object>(indexes.ToArray(), _start).MakeParamsArray;
}
Type genType = typeof(ParamArrayDelegate<>).MakeGenericType(_elementType);
return (Func<object[], object>)Delegate.CreateDelegate(
typeof(Func<object[], object>),
Activator.CreateInstance(genType, indexes.ToArray(), _start),
genType.GetMethod("MakeParamsArray"));
}
class ParamArrayDelegate<T> {
private readonly Func<object[], object>[] _indexes;
private readonly int _start;
public ParamArrayDelegate(Func<object[], object>[] indexes, int start) {
_indexes = indexes;
_start = start;
}
public T[] MakeParamsArray(object[] args) {
T[] res = new T[_indexes.Length];
for (int i = 0; i < _indexes.Length; i++) {
if (_indexes[i] == null) {
res[i] = (T)args[_start + i + 1];
} else {
res[i] = (T)_indexes[i](args);
}
}
return res;
}
}
internal override bool CanGenerateDelegate {
get {
return true;
}
}
public override Type Type {
get {
return _elementType.MakeArrayType();
}
}
}
}
|