PageRenderTime 83ms CodeModel.GetById 40ms app.highlight 8ms RepoModel.GetById 33ms app.codeStats 0ms

/Microsoft.Scripting/Actions/Calls/ParamsDictArgBuilder.cs

https://bitbucket.org/stefanrusek/xronos
C# | 130 lines | 97 code | 15 blank | 18 comment | 6 complexity | c22d7a0ff8d2dcd07a588a6132c6152a MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Microsoft Public License. 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  Microsoft Public License, 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 Microsoft Public License.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15
 16#if CODEPLEX_40
 17using System;
 18#else
 19using System; using Microsoft;
 20#endif
 21using System.Collections.Generic;
 22#if CODEPLEX_40
 23using System.Dynamic;
 24using System.Linq.Expressions;
 25#else
 26using Microsoft.Scripting;
 27using Microsoft.Linq.Expressions;
 28#endif
 29using System.Reflection;
 30using Microsoft.Scripting.Runtime;
 31using AstUtils = Microsoft.Scripting.Ast.Utils;
 32
 33namespace Microsoft.Scripting.Actions.Calls {
 34#if CODEPLEX_40
 35    using Ast = System.Linq.Expressions.Expression;
 36#else
 37    using Ast = Microsoft.Linq.Expressions.Expression;
 38#endif
 39    using Microsoft.Scripting.Utils;
 40
 41    /// <summary>
 42    /// Builds the parameter for a params dictionary argument - this collects all the extra name/value
 43    /// pairs provided to the function into a SymbolDictionary which is passed to the function.
 44    /// </summary>
 45    internal sealed class ParamsDictArgBuilder : ArgBuilder {
 46        private readonly string[] _names;
 47        private readonly int[] _nameIndexes;
 48        private readonly int _argIndex;
 49
 50        public ParamsDictArgBuilder(ParameterInfo info, int argIndex, string[] names, int[] nameIndexes) 
 51            : base(info) {
 52            Assert.NotNull(names, nameIndexes);
 53
 54            _argIndex = argIndex;
 55            _names = names;
 56            _nameIndexes = nameIndexes;
 57        }
 58
 59        public override int Priority {
 60            get { return 3; }
 61        }
 62
 63        internal protected override Expression ToExpression(ParameterBinder parameterBinder, IList<Expression> parameters, bool[] hasBeenUsed) {
 64            Expression res = Ast.Call(
 65                typeof(BinderOps).GetMethod("MakeSymbolDictionary"),
 66                Ast.NewArrayInit(typeof(string), ConstantNames()),
 67                AstUtils.NewArrayHelper(typeof(object), GetParameters(parameters, hasBeenUsed))
 68            );
 69
 70            return res;
 71        }
 72
 73        public override Type Type {
 74            get {
 75                return typeof(IAttributesCollection);
 76            }
 77        }
 78
 79        private List<Expression> GetParameters(IList<Expression> parameters, bool[] hasBeenUsed) {
 80            List<Expression> res = new List<Expression>(_nameIndexes.Length);
 81            for (int i = 0; i < _nameIndexes.Length; i++) {
 82                int parameterIndex = _nameIndexes[i] + _argIndex;
 83                if (!hasBeenUsed[parameterIndex]) {
 84                    res.Add(parameters[parameterIndex]);
 85                    hasBeenUsed[parameterIndex] = true;
 86                }
 87            }
 88            return res;
 89        }
 90
 91        private int[] GetParameters(bool[] hasBeenUsed) {
 92            var res = new List<int>(_nameIndexes.Length);
 93            for (int i = 0; i < _nameIndexes.Length; i++) {
 94                int parameterIndex = _nameIndexes[i] + _argIndex;
 95                if (!hasBeenUsed[parameterIndex]) {
 96                    res.Add(parameterIndex);
 97                    hasBeenUsed[parameterIndex] = true;
 98                }
 99            }
100            return res.ToArray();
101        }
102
103        private Expression[] ConstantNames() {
104            Expression[] res = new Expression[_names.Length];
105            for (int i = 0; i < _names.Length; i++) {
106                res[i] = AstUtils.Constant(_names[i]);
107            }
108            return res;
109        }
110
111        internal override bool CanGenerateDelegate {
112            get {
113                return true;
114            }
115        }
116
117        protected internal override Func<object[], object> ToDelegate(ParameterBinder parameterBinder, IList<DynamicMetaObject> knownTypes, bool[] hasBeenUsed) {
118            string[] names = _names;
119            int[] indexes = GetParameters(hasBeenUsed);
120
121            return (args) => {
122                object[] values = new object[indexes.Length];
123                for (int i = 0; i < indexes.Length; i++) {
124                    values[i] = args[indexes[i] + 1];
125                }
126                return BinderOps.MakeSymbolDictionary(names, values);
127            };
128        }
129    }
130}