Beispiel #1
0
        protected internal override Func <object[], object> ToDelegate(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed)
        {
            if (resolver.GetActualArguments().CollapsedCount > 0)
            {
                return(null);
            }

            var indexes = new List <Func <object[], object> >(_expandedCount);

            for (int i = _start; i < _start + _expandedCount; i++)
            {
                if (!hasBeenUsed[i])
                {
                    indexes.Add(resolver.GetConvertor(i + 1, args.GetObject(i), ParameterInfo, _elementType));
                    hasBeenUsed[i] = true;
                }
            }

            if (_elementType == typeof(object))
            {
                return(new ParamArrayDelegate <object>(indexes.ToArray(), _start).MakeParamsArray);
            }

            Type genType = typeof(ParamArrayDelegate <>).MakeGenericType(_elementType);

            return((Func <object[], object>)Delegate.CreateDelegate(
                       typeof(Func <object[], object>),
                       Activator.CreateInstance(genType, indexes.ToArray(), _start),
                       genType.GetMethod("MakeParamsArray")));
        }
        internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed)
        {
            var actualArgs     = resolver.GetActualArguments();
            int splatIndex     = actualArgs.SplatIndex;
            int collapsedCount = actualArgs.CollapsedCount;
            int firstSplatted  = actualArgs.FirstSplattedArg;

            var result        = new Expression[2 + _expandedCount + (collapsedCount > 0 ? 2 : 0)];
            var arrayVariable = resolver.GetTemporary(_elementType.MakeArrayType(), "a");
            int e             = 0;

            result[e++] = Ast.Assign(arrayVariable, Ast.NewArrayBounds(_elementType, Ast.Constant(_expandedCount + collapsedCount)));

            int itemIndex = 0;
            int i         = _start;

            while (true)
            {
                // inject loop copying collapsed items:
                if (i == splatIndex)
                {
                    var indexVariable = resolver.GetTemporary(typeof(int), "t");

                    // for (int t = 0; t <= {collapsedCount}; t++) {
                    //   a[{itemIndex} + t] = CONVERT<ElementType>(list.get_Item({splatIndex - firstSplatted} + t))
                    // }
                    result[e++] = Ast.Assign(indexVariable, AstUtils.Constant(0));
                    result[e++] = AstUtils.Loop(
                        Ast.LessThan(indexVariable, Ast.Constant(collapsedCount)),
                        // TODO: not implemented in the old interpreter
                        // Ast.PostIncrementAssign(indexVariable),
                        Ast.Assign(indexVariable, Ast.Add(indexVariable, AstUtils.Constant(1))),
                        Ast.Assign(
                            Ast.ArrayAccess(arrayVariable, Ast.Add(AstUtils.Constant(itemIndex), indexVariable)),
                            resolver.Convert(
                                new DynamicMetaObject(
                                    resolver.GetSplattedItemExpression(Ast.Add(AstUtils.Constant(splatIndex - firstSplatted), indexVariable)),
                                    BindingRestrictions.Empty
                                    ),
                                null,
                                ParameterInfo,
                                _elementType
                                )
                            ),
                        null
                        );

                    itemIndex += collapsedCount;
                }

                if (i >= _start + _expandedCount)
                {
                    break;
                }

                Debug.Assert(!hasBeenUsed[i]);
                hasBeenUsed[i] = true;

                result[e++] = Ast.Assign(
                    Ast.ArrayAccess(arrayVariable, AstUtils.Constant(itemIndex++)),
                    resolver.Convert(args.GetObject(i), args.GetType(i), ParameterInfo, _elementType)
                    );

                i++;
            }

            result[e++] = arrayVariable;

            Debug.Assert(e == result.Length);
            return(Ast.Block(result));
        }