xronos /Microsoft.Scripting/Actions/Calls/ParamsArgBuilder.cs

Language C# Lines 128
MD5 Hash 764964039b4a2709eec2e7ea3f8accc3 Estimated Cost $2,282 (why?)
Repository https://bitbucket.org/stefanrusek/xronos View Raw File
  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();
            }
        }
    }
}
Back to Top