DefaultOverloadResolver.cs :  » Script » IronRuby » Microsoft » Scripting » Actions » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Script » IronRuby 
IronRuby » Microsoft » Scripting » Actions » DefaultOverloadResolver.cs
/* ****************************************************************************
 *
 * 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 !CLR2
using System.Linq.Expressions;
#else
using Microsoft.Scripting.Ast;
#endif

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Dynamic;
using Microsoft.Scripting.Actions.Calls;
using Microsoft.Scripting.Generation;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
using AstUtilsMicrosoft.Scripting.Ast.Utils;

namespace Microsoft.Scripting.Actions{
    using Ast = Expression;

    internal sealed class DefaultOverloadResolverFactory : OverloadResolverFactory {
        private readonly DefaultBinder _binder;

        public DefaultOverloadResolverFactory(DefaultBinder binder) {
            Assert.NotNull(binder);
            _binder = binder;
        }

        public override DefaultOverloadResolver CreateOverloadResolver(IList<DynamicMetaObject> args, CallSignature signature, CallTypes callType) {
            return new DefaultOverloadResolver(_binder, args, signature, callType);
        }
    }

    public class DefaultOverloadResolver : OverloadResolver {
        // the first argument is "self" if CallType is ImplicitInstance
        // (TODO: it might be better to change the signature)
        private readonly IList<DynamicMetaObject> _args;
        private readonly CallSignature _signature;
        private readonly CallTypes _callType;
        private DynamicMetaObject _invalidSplattee;
        private static readonly DefaultOverloadResolverFactory _factory = new DefaultOverloadResolverFactory(DefaultBinder.Instance);

        // instance method call:
        public DefaultOverloadResolver(ActionBinder binder, DynamicMetaObject instance, IList<DynamicMetaObject> args, CallSignature signature)
            : this(binder, ArrayUtils.Insert(instance, args), signature, CallTypes.ImplicitInstance) {
        }


        // method call:
        public DefaultOverloadResolver(ActionBinder binder, IList<DynamicMetaObject> args, CallSignature signature)
            : this(binder, args, signature, CallTypes.None) {
        }

        public DefaultOverloadResolver(ActionBinder binder, IList<DynamicMetaObject> args, CallSignature signature, CallTypes callType)
            : base(binder) {
            ContractUtils.RequiresNotNullItems(args, "args");

            Debug.Assert((callType == CallTypes.ImplicitInstance ? 1 : 0) + signature.ArgumentCount == args.Count);
            _args = args;
            _signature = signature;
            _callType = callType;
        }

        public static OverloadResolverFactory Factory {
            get {
                return _factory;
            }
        }

        public CallSignature Signature {
            get { return _signature; } 
        }

        public IList<DynamicMetaObject> Arguments {
            get { return _args; }
        }

        public CallTypes CallType {
            get { return _callType; }
        }

        protected internal override BitArray MapSpecialParameters(ParameterMapping mapping) {
            //  CallType        call-site   m static                  m instance         m operator/extension
            //  implicit inst.  T.m(a,b)    Ast.Call(null, [a, b])    Ast.Call(a, [b])   Ast.Call(null, [a, b])   
            //  none            a.m(b)      Ast.Call(null, [b])       Ast.Call(a, [b])   Ast.Call(null, [a, b])

            if (!mapping.Overload.IsStatic) {
                var type = mapping.Overload.DeclaringType;
                var flags = ParameterBindingFlags.ProhibitNull | (_callType == CallTypes.ImplicitInstance ? ParameterBindingFlags.IsHidden : 0);

                mapping.AddParameter(new ParameterWrapper(null, type, null, flags));
                mapping.AddInstanceBuilder(new InstanceBuilder(mapping.ArgIndex));
            }

            return null;
        }

        internal protected override Candidate CompareEquivalentCandidates(ApplicableCandidate one, ApplicableCandidate two) {
            var result = base.CompareEquivalentCandidates(one, two);
            if (result.Chosen()) {
                return result;
            }

            if (one.Method.Overload.IsStatic && !two.Method.Overload.IsStatic) {
                return _callType == CallTypes.ImplicitInstance ? Candidate.Two : Candidate.One;
            } else if (!one.Method.Overload.IsStatic && two.Method.Overload.IsStatic) {
                return _callType == CallTypes.ImplicitInstance ? Candidate.One : Candidate.Two;
            }

            return Candidate.Equivalent;
        }

        #region Actual Arguments

        private DynamicMetaObject GetArgument(int i) {
            return _args[(CallType == CallTypes.ImplicitInstance ? 1 : 0) + i];
        }

        protected override void GetNamedArguments(out IList<DynamicMetaObject> namedArgs, out IList<string> argNames) {
            if (_signature.HasNamedArgument() || _signature.HasDictionaryArgument()) {
                var objects = new List<DynamicMetaObject>();
                var names = new List<string>();

                for (int i = 0; i < _signature.ArgumentCount; i++) {
                    if (_signature.GetArgumentKind(i) == ArgumentType.Named) {
                        objects.Add(GetArgument(i));
                        names.Add(_signature.GetArgumentName(i));
                    }
                }

                if (_signature.HasDictionaryArgument()) {
                    if (objects == null) {
                        objects = new List<DynamicMetaObject>();
                        names = new List<string>();
                    }
                    SplatDictionaryArgument(names, objects);
                }

               
                names.TrimExcess();
                objects.TrimExcess();
                argNames = names;
                namedArgs = objects;
            } else { 
                argNames = ArrayUtils.EmptyStrings;
                namedArgs = DynamicMetaObject.EmptyMetaObjects;
            }
        }

        protected override ActualArguments CreateActualArguments(IList<DynamicMetaObject> namedArgs, IList<string> argNames, int preSplatLimit, int postSplatLimit) {
            var res = new List<DynamicMetaObject>();

            if (CallType == CallTypes.ImplicitInstance) {
                res.Add(_args[0]);
            }

            for (int i = 0; i < _signature.ArgumentCount; i++) {
                var arg = GetArgument(i);

                switch (_signature.GetArgumentKind(i)) {
                    case ArgumentType.Simple:
                    case ArgumentType.Instance:
                        res.Add(arg);
                        break;

                    case ArgumentType.List:
                        // TODO: lazy splat
                        IList<object> list = arg.Value as IList<object>;
                        if (list == null) {
                            _invalidSplattee = arg;
                            return null;
                        }

                        for (int j = 0; j < list.Count; j++) {
                            res.Add(
                                DynamicMetaObject.Create(
                                    list[j],
                                    Ast.Call(
                                        Ast.Convert(
                                            arg.Expression,
                                            typeof(IList<object>)
                                        ),
                                        typeof(IList<object>).GetMethod("get_Item"),
                                        AstUtils.Constant(j)
                                    )
                                )
                            );
                        }
                        break;

                    case ArgumentType.Named:
                    case ArgumentType.Dictionary:
                        // already processed
                        break;

                    default:
                        throw new NotImplementedException();
                }
            }

            res.TrimExcess();
            return new ActualArguments(res, namedArgs, argNames, _callType == CallTypes.ImplicitInstance ? 1 : 0,  0, -1, -1);
        }

        private void SplatDictionaryArgument(IList<string> splattedNames, IList<DynamicMetaObject> splattedArgs) {
            Assert.NotNull(splattedNames, splattedArgs);

            DynamicMetaObject dictMo = GetArgument(_signature.ArgumentCount - 1);
            IDictionary dict = (IDictionary)dictMo.Value;
            IDictionaryEnumerator dictEnum = dict.GetEnumerator();
            while (dictEnum.MoveNext()) {
                DictionaryEntry de = dictEnum.Entry;
                
                if (de.Key is string) {
                    splattedNames.Add((string)de.Key);
                    splattedArgs.Add(
                        DynamicMetaObject.Create(
                            de.Value,
                            Ast.Call(
                                AstUtils.Convert(dictMo.Expression, typeof(IDictionary)),
                                typeof(IDictionary).GetMethod("get_Item"),
                                AstUtils.Constant(de.Key as string)
                            )
                        )
                    );
                }
            }
        }

        protected override Expression GetSplattedExpression() {
            // lazy splatting not used:
            throw Assert.Unreachable;
        }

        protected override object GetSplattedItem(int index) {
            // lazy splatting not used:
            throw Assert.Unreachable;
        }


        #endregion

        public override ErrorInfo MakeInvalidParametersError(BindingTarget target) {
            if (target.Result == BindingResult.InvalidArguments && _invalidSplattee != null) {
                return MakeInvalidSplatteeError(target);
            }
            return base.MakeInvalidParametersError(target);
        }

        private ErrorInfo MakeInvalidSplatteeError(BindingTarget target) {
            return ErrorInfo.FromException(
                Ast.Call(typeof(BinderOps).GetMethod("InvalidSplatteeError"), 
                    AstUtils.Constant(target.Name),
                    AstUtils.Constant(Binder.GetTypeName(_invalidSplattee.GetLimitType()))
                )
            );
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.