GetSplattedMetaArgument() публичный Метод

public GetSplattedMetaArgument ( ) : DynamicMetaObject
Результат DynamicMetaObject
Пример #1
0
        public void AddSplatted(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            var arg = args.GetSplattedMetaArgument();

            int listLength;
            ParameterExpression listVariable;

            metaBuilder.AddSplattedArgumentTest((IList)arg.Value, arg.Expression, out listLength, out listVariable);
            if (listLength > 0)
            {
                for (int i = 0; i < listLength; i++)
                {
                    Add(
                        Ast.Call(
                            listVariable,
                            typeof(IList).GetMethod("get_Item"),
                            AstUtils.Constant(i)
                            )
                        );
                }
            }
        }
        private static ActualArguments /*!*/ CreateActualArguments(List <DynamicMetaObject> /*!*/ normalized, MetaObjectBuilder /*!*/ metaBuilder,
                                                                   CallArguments /*!*/ args, int hidden, int preSplatLimit, int postSplatLimit, out int lastSplattedArg, out IList list, out ParameterExpression listVariable)
        {
            int firstSplattedArg, splatIndex, collapsedArgCount;

            // simple arguments:
            for (int i = 0; i < args.SimpleArgumentCount; i++)
            {
                normalized.Add(args.GetSimpleMetaArgument(i));
            }

            // splat argument:
            list         = null;
            listVariable = null;
            if (args.Signature.HasSplattedArgument)
            {
                firstSplattedArg = normalized.Count;

                int listLength;
                var splatted = args.GetSplattedMetaArgument();
                list = (IList)splatted.Value;
                metaBuilder.AddSplattedArgumentTest(list, splatted.Expression, out listLength, out listVariable);

                int i = 0;
                while (i < Math.Min(listLength, preSplatLimit - firstSplattedArg))
                {
                    normalized.Add(MakeSplattedItem(list, listVariable, i));
                    i++;
                }

                // skip items that are not needed for overload resolution
                splatIndex = normalized.Count;

                i = Math.Max(i, listLength - (postSplatLimit - (args.Signature.HasRhsArgument ? 1 : 0)));
                while (i < listLength)
                {
                    normalized.Add(MakeSplattedItem(list, listVariable, i));
                    i++;
                }

                collapsedArgCount = listLength - (normalized.Count - firstSplattedArg);
                lastSplattedArg   = normalized.Count - 1;
            }
            else
            {
                splatIndex        = firstSplattedArg = lastSplattedArg = -1;
                collapsedArgCount = 0;
            }

            Debug.Assert(collapsedArgCount >= 0);

            // rhs argument:
            if (args.Signature.HasRhsArgument)
            {
                normalized.Add(args.GetRhsMetaArgument());
            }

            return(new ActualArguments(
                       normalized.ToArray(),
                       DynamicMetaObject.EmptyMetaObjects,
                       ArrayUtils.EmptyStrings,
                       hidden,
                       collapsedArgCount,
                       firstSplattedArg,
                       splatIndex
                       ));
        }
Пример #3
0
        public void AddSplatted(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) {
            var arg = args.GetSplattedMetaArgument();

            int listLength;
            ParameterExpression listVariable;
            metaBuilder.AddSplattedArgumentTest((IList)arg.Value, arg.Expression, out listLength, out listVariable);
            if (listLength > 0) {
                for (int i = 0; i < listLength; i++) {
                    Add(
                        Ast.Call(
                            listVariable,
                            typeof(IList).GetMethod("get_Item"),
                            AstUtils.Constant(i)
                        )
                    );
                }
            }
        }
Пример #4
0
        private static ActualArguments/*!*/ CreateActualArguments(List<DynamicMetaObject>/*!*/ normalized, MetaObjectBuilder/*!*/ metaBuilder,
            CallArguments/*!*/ args, int hidden, int preSplatLimit, int postSplatLimit, out int lastSplattedArg, out IList list, out ParameterExpression listVariable) {

            int firstSplattedArg, splatIndex, collapsedArgCount;

            // simple arguments:
            for (int i = 0; i < args.SimpleArgumentCount; i++) {
                normalized.Add(args.GetSimpleMetaArgument(i));
            }

            // splat argument:
            list = null;
            listVariable = null;
            if (args.Signature.HasSplattedArgument) {
                firstSplattedArg = normalized.Count;

                int listLength;
                var splatted = args.GetSplattedMetaArgument();
                list = (IList)splatted.Value;
                metaBuilder.AddSplattedArgumentTest(list, splatted.Expression, out listLength, out listVariable);

                int i = 0;
                while (i < Math.Min(listLength, preSplatLimit - firstSplattedArg)) {
                    normalized.Add(MakeSplattedItem(list, listVariable, i));
                    i++;
                }

                // skip items that are not needed for overload resolution
                splatIndex = normalized.Count;

                i = Math.Max(i, listLength - (postSplatLimit - (args.Signature.HasRhsArgument ? 1 : 0)));
                while (i < listLength) {
                    normalized.Add(MakeSplattedItem(list, listVariable, i));
                    i++;
                }

                collapsedArgCount = listLength - (normalized.Count - firstSplattedArg);
                lastSplattedArg = normalized.Count - 1;
            } else {
                splatIndex = firstSplattedArg = lastSplattedArg = -1;
                collapsedArgCount = 0;
            }

            Debug.Assert(collapsedArgCount >= 0);

            // rhs argument:
            if (args.Signature.HasRhsArgument) {
                normalized.Add(args.GetRhsMetaArgument());
            }

            return new ActualArguments(
                normalized.ToArray(),
                DynamicMetaObject.EmptyMetaObjects,
                ArrayUtils.EmptyStrings,
                hidden,
                collapsedArgCount,
                firstSplattedArg,
                splatIndex
            );
        }
Пример #5
0
        // Normalizes arguments: inserts self, expands splats, and inserts rhs arg. 
        // Adds any restrictions/conditions applied to the arguments to the given meta-builder.
        internal static DynamicMetaObject[]/*!*/ NormalizeArguments(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args,
            SelfCallConvention callConvention, bool calleeHasBlockParam, bool injectMissingBlockParam) {

            var result = new List<DynamicMetaObject>();

            // self (instance):
            if (callConvention == SelfCallConvention.SelfIsInstance) {
                result.Add(args.MetaTarget);
            }

            // block:
            if (calleeHasBlockParam) {
                if (args.Signature.HasBlock) {
                    if (args.GetMetaBlock() == null) {
                        // the user explicitly passed nil as a block arg:
                        result.Add(RubyBinder.NullMetaObject);
                    } else {
                        // pass BlockParam:
                        Debug.Assert(metaBuilder.BfcVariable != null);
                        result.Add(new DynamicMetaObject(metaBuilder.BfcVariable, BindingRestrictions.Empty));
                    }
                } else {
                    // no block passed into a method with a BlockParam:
                    result.Add(RubyBinder.NullMetaObject);
                }
            } else if (injectMissingBlockParam) {
                // no block passed into a method w/o a BlockParam (we still need to fill the missing block argument):
                result.Add(RubyBinder.NullMetaObject);
            }

            // self (parameter):
            if (callConvention == SelfCallConvention.SelfIsParameter) {
                result.Add(args.MetaTarget);
            }

            // simple arguments:
            for (int i = 0; i < args.SimpleArgumentCount; i++) {
                result.Add(args.GetSimpleMetaArgument(i));
            }

            // splat argument:
            int listLength;
            ParameterExpression listVariable;
            if (args.Signature.HasSplattedArgument) {
                var splatted = args.GetSplattedMetaArgument();

                if (metaBuilder.AddSplattedArgumentTest(splatted.Value, splatted.Expression, out listLength, out listVariable)) {

                    // AddTestForListArg only returns 'true' if the argument is a List<object>
                    var list = (List<object>)splatted.Value;

                    // get arguments, add tests
                    for (int j = 0; j < listLength; j++) {
                        result.Add(DynamicMetaObject.Create(
                            list[j], 
                            Ast.Call(listVariable, typeof(List<object>).GetMethod("get_Item"), AstUtils.Constant(j))
                        ));
                    }

                } else {
                    // argument is not an array => add the argument itself:
                    result.Add(splatted);
                }
            }

            // rhs argument:
            if (args.Signature.HasRhsArgument) {
                result.Add(args.GetRhsMetaArgument());
            }

            return result.ToArray();
        }
Пример #6
0
        public void AddSplatted(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) {
            var arg = args.GetSplattedMetaArgument();

            int listLength;
            ParameterExpression listVariable;
            if (metaBuilder.AddSplattedArgumentTest(arg.Value, arg.Expression, out listLength, out listVariable)) {
                if (listLength > 0) {
                    for (int i = 0; i < listLength; i++) {
                        Add(
                            Ast.Call(
                                listVariable,
                                typeof(List<object>).GetMethod("get_Item"),
                                AstUtils.Constant(i)
                            )
                        );
                    }
                }
            } else {
                // argument is not an array => add the argument itself:
                Add(arg.Expression);
            }
        }
Пример #7
0
        public void AddCallArguments(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            _callArguments = args;

            // calculate actual argument count:
            _actualArgumentCount = args.SimpleArgumentCount;
            if (args.Signature.HasSplattedArgument)
            {
                var splattedArg = args.GetSplattedMetaArgument();
                metaBuilder.AddSplattedArgumentTest((IList)splattedArg.Value, splattedArg.Expression, out _listLength, out _listVariable);
                _actualArgumentCount += _listLength;
            }
            if (args.Signature.HasRhsArgument)
            {
                _actualArgumentCount++;
            }

            // check:
            if (HasTooFewArguments)
            {
                metaBuilder.SetWrongNumberOfArgumentsError(_actualArgumentCount, _mandatoryParamCount);
                return;
            }

            if (HasTooManyArguments)
            {
                metaBuilder.SetWrongNumberOfArgumentsError(_actualArgumentCount, _mandatoryParamCount);
                return;
            }

            bool isSplatted;

            // leading mandatory:
            for (int i = 0; i < _leadingMandatoryParamCount; i++)
            {
                _arguments[LeadingMandatoryIndex + i] = GetArgument(i, out isSplatted);
            }

            // trailing mandatory:
            for (int i = 0; i < TrailingMandatoryCount; i++)
            {
                _arguments[TrailingMandatoryIndex + i] = GetArgument(_actualArgumentCount - TrailingMandatoryCount + i, out isSplatted);
            }

            int start = _leadingMandatoryParamCount;
            int end   = _actualArgumentCount - TrailingMandatoryCount;

            // optional:
            for (int i = 0; i < _optionalParamCount; i++)
            {
                _arguments[OptionalParameterIndex + i] = (start < end) ? GetArgument(start++, out isSplatted) : Ast.Field(null, Fields.DefaultArgument);
            }

            // unsplat:
            if (_hasUnsplatParameter)
            {
                Expression array;
                if (args.Signature.HasSplattedArgument)
                {
                    // simple:
                    var argsToUnsplat = new List <Expression>();
                    while (start < end)
                    {
                        var arg = GetArgument(start, out isSplatted);
                        if (isSplatted)
                        {
                            break;
                        }
                        argsToUnsplat.Add(AstUtils.Box(arg));
                        start++;
                    }
                    array = Methods.MakeArrayOpCall(argsToUnsplat);

                    int rangeStart  = start - args.SimpleArgumentCount;
                    int rangeLength = Math.Min(end - start, _listLength - rangeStart);

                    // splatted:
                    if (rangeLength > 0)
                    {
                        array  = Methods.AddSubRange.OpCall(array, _listVariable, Ast.Constant(rangeStart), Ast.Constant(rangeLength));
                        start += rangeLength;
                    }

                    // rhs:
                    while (start < end)
                    {
                        array = Methods.AddItem.OpCall(array, AstUtils.Box(GetArgument(start, out isSplatted)));
                        start++;
                    }
                }
                else
                {
                    var argsToUnsplat = new List <Expression>(end - start);
                    while (start < end)
                    {
                        argsToUnsplat.Add(AstUtils.Box(GetArgument(start++, out isSplatted)));
                    }
                    array = Methods.MakeArrayOpCall(argsToUnsplat);
                }

                _arguments[UnsplatParameterIndex] = array;
            }

            _callArguments = null;
            _listVariable  = null;
            Debug.Assert(CollectionUtils.TrueForAll(_arguments, (e) => e != null));
        }
Пример #8
0
        public void AddCallArguments(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) {
            _callArguments = args;

            // calculate actual argument count:
            _actualArgumentCount = args.SimpleArgumentCount;
            if (args.Signature.HasSplattedArgument) {
                var splattedArg = args.GetSplattedMetaArgument();
                metaBuilder.AddSplattedArgumentTest((IList)splattedArg.Value, splattedArg.Expression, out _listLength, out _listVariable);
                _actualArgumentCount += _listLength;
            }
            if (args.Signature.HasRhsArgument) {
                _actualArgumentCount++;
            }

            // check:
            if (HasTooFewArguments) {
                metaBuilder.SetWrongNumberOfArgumentsError(_actualArgumentCount, _mandatoryParamCount);
                return;
            }

            if (HasTooManyArguments) {
                metaBuilder.SetWrongNumberOfArgumentsError(_actualArgumentCount, _mandatoryParamCount);
                return;
            }

            bool isSplatted;

            // leading mandatory:
            for (int i = 0; i < _leadingMandatoryParamCount; i++) {
                _arguments[LeadingMandatoryIndex + i] = GetArgument(i, out isSplatted);
            }

            // trailing mandatory:
            for (int i = 0; i < TrailingMandatoryCount; i++) {
                _arguments[TrailingMandatoryIndex + i] = GetArgument(_actualArgumentCount - TrailingMandatoryCount + i, out isSplatted);
            }

            int start = _leadingMandatoryParamCount;
            int end = _actualArgumentCount - TrailingMandatoryCount;

            // optional:
            for (int i = 0; i < _optionalParamCount; i++) {
                _arguments[OptionalParameterIndex + i] = (start < end) ? GetArgument(start++, out isSplatted) : Ast.Field(null, Fields.DefaultArgument);
            }

            // unsplat:
            if (_hasUnsplatParameter) {
                Expression array;
                if (args.Signature.HasSplattedArgument) {
                    // simple:
                    var argsToUnsplat = new List<Expression>();
                    while (start < end) {
                        var arg = GetArgument(start, out isSplatted);
                        if (isSplatted) {
                            break;
                        }
                        argsToUnsplat.Add(AstUtils.Box(arg));
                        start++;
                    }
                    array = Methods.MakeArrayOpCall(argsToUnsplat);
                    
                    int rangeStart = start - args.SimpleArgumentCount;
                    int rangeLength = Math.Min(end - start, _listLength - rangeStart);

                    // splatted:
                    if (rangeLength > 0) {
                        array = Methods.AddSubRange.OpCall(array, _listVariable, Ast.Constant(rangeStart), Ast.Constant(rangeLength));
                        start += rangeLength;
                    }

                    // rhs:
                    while (start < end) {
                        array = Methods.AddItem.OpCall(array, AstUtils.Box(GetArgument(start, out isSplatted)));
                        start++;
                    }
                } else {
                    var argsToUnsplat = new List<Expression>(end - start);
                    while (start < end) {
                        argsToUnsplat.Add(AstUtils.Box(GetArgument(start++, out isSplatted)));
                    }
                    array = Methods.MakeArrayOpCall(argsToUnsplat);
                }

                _arguments[UnsplatParameterIndex] = array;
            }

            _callArguments = null;
            _listVariable = null;
            Debug.Assert(CollectionUtils.TrueForAll(_arguments, (e) => e != null));
        }