PageRenderTime 25ms CodeModel.GetById 2ms app.highlight 16ms RepoModel.GetById 2ms app.codeStats 0ms

/IronPython_2_0/Src/IronPython/Runtime/Types/BuiltinFunctionOverloadMapper.cs

#
C# | 145 lines | 94 code | 25 blank | 26 comment | 13 complexity | 9e24af93a7f82ea0bbff28a9a63c93b5 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
 16using System; using Microsoft;
 17using System.Collections.Generic;
 18using System.Reflection;
 19using Microsoft.Scripting.Runtime;
 20using IronPython.Runtime.Types;
 21using IronPython.Runtime.Operations;
 22
 23namespace IronPython.Runtime.Types {
 24
 25    // Used to map signatures to specific targets on the embedded reflected method.
 26    public class BuiltinFunctionOverloadMapper : ICodeFormattable {
 27        private BuiltinFunction _function;
 28        private object _instance;
 29
 30        public BuiltinFunctionOverloadMapper(BuiltinFunction builtinFunction, object instance) {
 31            this._function = builtinFunction;
 32            this._instance = instance;
 33        }
 34
 35        public object this[params Type[] types] {
 36            get {
 37                return GetOverload(types, Targets);
 38            }
 39        }
 40
 41        protected object GetOverload(Type[] sig, IList<MethodBase> targets) {
 42            // We can still end up with more than one target since generic and non-generic
 43            // methods can share the same name and signature. So we'll build up a new
 44            // reflected method with all the candidate targets. A caller can then index this
 45            // reflected method if necessary in order to provide generic type arguments and
 46            // fully disambiguate the target.
 47
 48            // Search for targets with the right number of arguments.
 49            MethodBase[] newTargets = FindMatchingTargets(sig, targets);
 50
 51            if (targets == null)
 52                throw RuntimeHelpers.SimpleTypeError(String.Format("No match found for the method signature {0}", sig));    // TODO: Sig to usable display
 53
 54            BuiltinFunction bf = new BuiltinFunction(_function.Name, newTargets, Function.DeclaringType, _function.FunctionType);
 55
 56            if (_instance != null) {
 57                return bf.BindToInstance(_instance);
 58            } else {
 59                return GetTargetFunction(bf);
 60            }
 61        }
 62
 63        private MethodBase[] FindMatchingTargets(Type[] sig, IList<MethodBase> targets) {
 64            int args = sig.Length;
 65
 66            List<MethodBase> res = new List<MethodBase>();
 67            foreach (MethodBase mb in targets) {
 68                ParameterInfo[] pis = mb.GetParameters();
 69                if (pis.Length != args)
 70                    continue;
 71
 72                // Check each parameter type for an exact match.
 73                bool match = true;
 74                for (int i = 0; i < args; i++)
 75                    if (pis[i].ParameterType != sig[i]) {
 76                        match = false;
 77                        break;
 78                    }
 79                if (!match)
 80                    continue;
 81
 82                // Okay, we have a match, add it to the list.
 83                res.Add(mb);
 84            }
 85            return res.ToArray();
 86        }
 87
 88        public BuiltinFunction Function {
 89            get {
 90                return _function;
 91            }
 92        }
 93
 94        public virtual IList<MethodBase> Targets {
 95            get {
 96                return _function.Targets;
 97            }
 98        }
 99
100        protected virtual object GetTargetFunction(BuiltinFunction bf) {
101            return bf;
102        }
103
104        internal virtual object GetKeywordArgumentOverload(Type[] key) {
105            return GetOverload(key, Function.Targets);
106        }
107
108        public virtual string/*!*/ __repr__(CodeContext/*!*/ context) {
109            PythonDictionary overloadList = new PythonDictionary();
110
111            foreach (MethodBase mb in Targets) {
112                string key = DocBuilder.CreateAutoDoc(mb);
113                overloadList[key] = Function;
114            }
115            return overloadList.__repr__(context);
116        }
117    }
118
119    public class ConstructorOverloadMapper : BuiltinFunctionOverloadMapper {
120        public ConstructorOverloadMapper(ConstructorFunction builtinFunction, object instance)
121            : base(builtinFunction, instance) {
122        }
123
124        public override IList<MethodBase> Targets {
125            get {
126                return ((ConstructorFunction)Function).ConstructorTargets;
127            }
128        }
129
130        internal override object GetKeywordArgumentOverload(Type[] key) {
131            return base.GetOverload(key, Function.Targets);
132        }
133
134        protected override object GetTargetFunction(BuiltinFunction bf) {
135            // return a function that's bound to the overloads, we'll
136            // the user then calls this w/ the dynamic type, and the bound
137            // function drops the class & calls the overload.
138            if (bf.Targets[0].DeclaringType != typeof(InstanceOps)) {
139                return new ConstructorFunction(InstanceOps.OverloadedNew, bf.Targets).BindToInstance(bf);
140            }
141
142            return base.GetTargetFunction(bf);
143        }
144    }
145}