Пример #1
0
        protected override BitArray MapSpecialParameters(ParameterMapping/*!*/ mapping) {
            var infos = mapping.ParameterInfos;
            BitArray special = base.MapSpecialParameters(mapping);

            if (infos.Length > 0) {
                bool normalSeen = false;
                for (int i = 0; i < infos.Length; i++) {
                    bool isSpecial = false;
                    if (infos[i].ParameterType.IsSubclassOf(typeof(SiteLocalStorage))) {
                        mapping.AddBuilder(new SiteLocalStorageBuilder(infos[i]));
                        isSpecial = true;
                    } else if (infos[i].ParameterType == typeof(CodeContext) && !normalSeen) {
                        mapping.AddBuilder(new ContextArgBuilder(infos[i]));
                        isSpecial = true;
                    } else {
                        normalSeen = true;
                    }

                    if (isSpecial) {
                        (special = special ?? new BitArray(infos.Length))[i] = true;
                    }
                }
            }

            return special;
        }
Пример #2
0
        internal MethodCandidate CreateByRefReducedCandidate()
        {
            if (!_hasByRef)
            {
                return(null);
            }

            var reducedMapping = new ParameterMapping(_resolver, _overload, _argNames);

            reducedMapping.MapParameters(true);
            return(reducedMapping.CreateCandidate());
        }
Пример #3
0
        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 (!CompilerHelpers.IsStatic(mapping.Method)) {
                var type = mapping.Method.DeclaringType;
                mapping.AddParameter(new ParameterWrapper(null, type, null, true, false, false, _callType == CallTypes.ImplicitInstance));
                mapping.AddInstanceBuilder(new SimpleArgBuilder(type, mapping.ArgIndex, false, false));
            }

            return null;
        }
Пример #4
0
        internal MethodCandidate CreateByRefReducedCandidate() {
            if (!_hasByRefOrOut) {
                return null;
            }

            var reducedMapping = new ParameterMapping(_resolver, _method, _parameterInfos, _argNames);
            reducedMapping.MapParameters(true);
            return reducedMapping.CreateCandidate();
        }
Пример #5
0
        protected override BitArray MapSpecialParameters(ParameterMapping/*!*/ mapping) {
            var infos = mapping.ParameterInfos;
            var method = mapping.Method;
            var special = new BitArray(infos.Length);

            // Method signatures                                                                                  SelfCallConvention
            // RubyMethod/RubyCtor:   [(CallSiteStorage)*, (RubyContext|RubyScope)?, (BlockParam)?, self, args]  SelfIsParameter
            // static:                [(CallSiteStorage)*, (RubyContext|RubyScope)?, (BlockParam)?, args]        NoSelf
            // instance/extension/op: [self, (CallSiteStorage)*, (RubyContext|RubyScope)?, (BlockParam)?, args]  SelfIsInstace

            var i = 0;

            if (_callConvention == SelfCallConvention.SelfIsInstance) {
                if (CompilerHelpers.IsStatic(method)) {
                    Debug.Assert(RubyUtils.IsOperator(method) || CompilerHelpers.IsExtension(method));

                    // receiver maps to the first parameter:
                    mapping.AddParameter(new ParameterWrapper(infos[i], infos[i].ParameterType, null, true, false, false, true));
                    mapping.AddBuilder(new SimpleArgBuilder(infos[i], mapping.ArgIndex));
                    special[i++] = true;
                } else {
                    // receiver maps to the instance (no parameter info represents it):
                    mapping.AddParameter(new ParameterWrapper(null, method.DeclaringType, null, true, false, false, true));
                    mapping.AddInstanceBuilder(new InstanceBuilder(mapping.ArgIndex));
                }
            } else if (_callConvention == SelfCallConvention.NoSelf) {
                // instance methods on Object can be called with arbitrary receiver object including classes (static call):
                if (!method.IsStatic && method.DeclaringType == typeof(Object)) {
                    // insert an InstanceBuilder that doesn't consume any arguments, only inserts the target expression as instance:
                    mapping.AddInstanceBuilder(new ImplicitInstanceBuilder());
                }
            }

            while (i < infos.Length && infos[i].ParameterType.IsSubclassOf(typeof(RubyCallSiteStorage))) {
                mapping.AddBuilder(new RubyCallSiteStorageBuilder(infos[i]));
                special[i++] = true;
            }

            if (i < infos.Length) {
                var info = infos[i];

                if (info.ParameterType == typeof(RubyScope)) {
                    mapping.AddBuilder(new RubyScopeArgBuilder(info));
                    special[i++] = true;
                } else if (info.ParameterType == typeof(RubyContext)) {
                    mapping.AddBuilder(new RubyContextArgBuilder(info));
                    special[i++] = true;
                } else if (method.IsConstructor && info.ParameterType == typeof(RubyClass)) {
                    mapping.AddBuilder(new RubyClassCtorArgBuilder(info));
                    special[i++] = true;
                }
            }

            // If the method overload doesn't have a BlockParam parameter, we inject MissingBlockParam parameter and arg builder.
            // The parameter is treated as a regular explicit mandatory parameter.
            //
            // The argument builder provides no value for the actual argument expression, which makes the default binder to skip it
            // when emitting a tree for the actual method call (this is necessary since the method doesn't in fact have the parameter).
            // 
            // By injecting the missing block parameter we achieve that all overloads have either BlockParam, [NotNull]BlockParam or 
            // MissingBlockParam parameter. MissingBlockParam and BlockParam are convertible to each other. Default binder prefers 
            // those overloads where no conversion needs to happen, which ensures the desired semantics:
            //
            //                                        conversions with desired priority (the less number the higher priority)
            // Parameters:                call w/o block      call with non-null block       call with null block
            // (implicit, MBP, ... )      MBP -> MBP (1)            BP -> MBP (3)               BP -> MBP (2)
            // (implicit, BP,  ... )      MBP -> BP  (2)            BP -> BP  (2)               BP -> BP  (1)
            // (implicit, BP!, ... )          N/A                   BP -> BP! (1)                  N/A    
            //
            if (i < infos.Length && infos[i].ParameterType == typeof(BlockParam)) {
                var info = infos[i];
                mapping.AddBuilder(new SimpleArgBuilder(info, mapping.ArgIndex));
                mapping.AddParameter(new ParameterWrapper(info, info.ParameterType, null, CompilerHelpers.ProhibitsNull(info), false, false, true));
                special[i++] = true;
            } else if (i >= infos.Length || infos[i].ParameterType != typeof(BlockParam)) {
                mapping.AddBuilder(new MissingBlockArgBuilder(mapping.ArgIndex));
                mapping.AddParameter(new ParameterWrapper(null, typeof(MissingBlockParam), null, false, false, false, true));
            }

            if (_callConvention == SelfCallConvention.SelfIsParameter) {
                // Ruby library methods only:
                Debug.Assert(CompilerHelpers.IsStatic(method));
                Debug.Assert(i < infos.Length);
                var info = infos[i];

                // receiver maps to the first visible parameter:
                mapping.AddParameter(new ParameterWrapper(info, info.ParameterType, null, CompilerHelpers.ProhibitsNull(info), false, false, true));
                mapping.AddBuilder(new SimpleArgBuilder(info, mapping.ArgIndex));
                special[i++] = true;
            }

            return special;
        }
Пример #6
0
 private void AddSimpleHiddenMapping(ParameterMapping mapping, ParameterInfo info, bool prohibitNull) {
     mapping.AddBuilder(new SimpleArgBuilder(info, info.ParameterType, mapping.ArgIndex, false, false));
     mapping.AddParameter(new ParameterWrapper(info, info.ParameterType, null, 
         ParameterBindingFlags.IsHidden | (prohibitNull ? ParameterBindingFlags.ProhibitNull : 0)
     ));
 }
Пример #7
0
        private void AddBasicMethodTargets(MethodBase method) {
            Assert.NotNull(method);

            var mapping = new ParameterMapping(this, method, null, _argNames);

            mapping.MapParameters(false);

            foreach (var defaultCandidate in mapping.CreateDefaultCandidates()) {
                AddSimpleTarget(defaultCandidate);
            }

            var byRefReducedCandidate = mapping.CreateByRefReducedCandidate();
            if (byRefReducedCandidate != null) {
                AddSimpleTarget(byRefReducedCandidate);
            }

            AddSimpleTarget(mapping.CreateCandidate());
        }
Пример #8
0
        internal protected virtual BitArray MapSpecialParameters(ParameterMapping mapping) {
            if (!CompilerHelpers.IsStatic(mapping.Method)) {
                var type = mapping.Method.DeclaringType;
                mapping.AddParameter(new ParameterWrapper(null, type, null, true, false, false, false));
                mapping.AddInstanceBuilder(new InstanceBuilder(mapping.ArgIndex));
            }

            return null;
        }
Пример #9
0
        private void AddBasicMethodTargets(OverloadInfo method) {
            Assert.NotNull(method);

            var mapping = new ParameterMapping(this, method, _argNames);

            mapping.MapParameters(false);

            foreach (var defaultCandidate in mapping.CreateDefaultCandidates()) {
                AddSimpleTarget(defaultCandidate);
            }

            // TODO: We reduce out/ref parameters only for the main overload.
            // We should rather treat all out params as optional (either a StrongBox is provided or not).
            var byRefReducedCandidate = mapping.CreateByRefReducedCandidate();
            if (byRefReducedCandidate != null) {
                AddSimpleTarget(byRefReducedCandidate);
            }

            AddSimpleTarget(mapping.CreateCandidate());
        }
Пример #10
0
        internal protected virtual BitArray MapSpecialParameters(ParameterMapping mapping) {
            if (!mapping.Overload.IsStatic) {
                var type = mapping.Overload.DeclaringType;
                mapping.AddParameter(new ParameterWrapper(null, type, null, ParameterBindingFlags.ProhibitNull));
                mapping.AddInstanceBuilder(new InstanceBuilder(mapping.ArgIndex));
            }

            return null;
        }
Пример #11
0
        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;
        }