Beispiel #1
0
        private MSA.Expression /*!*/ MakeParametersInitialization(AstGenerator /*!*/ gen, AstParameters /*!*/ parameters)
        {
            var result = new AstExpressions(
                _parameters.LeftValues.Count +
                (_parameters.UnsplattedValue != null ? 1 : 0) +
                1
                );

            bool paramsInArray = HasFormalParametersInArray;

            for (int i = 0; i < _parameters.LeftValues.Count; i++)
            {
                var parameter = paramsInArray ? (MSA.Expression)
                                Ast.ArrayAccess(parameters[HiddenParameterCount], AstUtils.Constant(i)) :
                                parameters[HiddenParameterCount + i];

                result.Add(_parameters.LeftValues[i].TransformWrite(gen, parameter));
            }

            if (_parameters.UnsplattedValue != null)
            {
                // the last parameter is unsplat:
                var parameter = parameters[parameters.Count - 1];
                result.Add(_parameters.UnsplattedValue.TransformWrite(gen, parameter));
            }

            result.Add(AstUtils.Empty());
            return(Ast.Block(result));
        }
Beispiel #2
0
        private DynamicMetaObject MakeArrayIndexRule(OverloadResolverFactory factory, IndexType oper, DynamicMetaObject[] args)
        {
            if (CanConvertFrom(GetArgType(args, 1), typeof(int), false, NarrowingLevel.All))
            {
                BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args));

                if (oper == IndexType.Get)
                {
                    return(new DynamicMetaObject(
                               Ast.ArrayAccess(
                                   args[0].Expression,
                                   ConvertIfNeeded(factory, args[1].Expression, typeof(int))
                                   ),
                               restrictions
                               ));
                }
                else
                {
                    return(new DynamicMetaObject(
                               Ast.Assign(
                                   Ast.ArrayAccess(
                                       args[0].Expression,
                                       ConvertIfNeeded(factory, args[1].Expression, typeof(int))
                                       ),
                                   ConvertIfNeeded(factory, args[2].Expression, args[0].GetLimitType().GetElementType())
                                   ),
                               restrictions.Merge(args[1].Restrictions)
                               ));
                }
            }

            return(null);
        }
Beispiel #3
0
        private MSA.Expression /*!*/ MakeParametersInitialization(AstGenerator /*!*/ gen, MSA.Expression[] /*!*/ parameters)
        {
            Assert.NotNull(gen);
            Assert.NotNullItems(parameters);

            var result = AstFactory.CreateExpressionArray(
                _parameters.LeftValues.Count +
                (_parameters.UnsplattedValue != null ? 1 : 0) +
                1
                );

            int resultIndex = 0;

            bool paramsInArray = HasFormalParametersInArray;

            for (int i = 0; i < _parameters.LeftValues.Count; i++)
            {
                var parameter = paramsInArray ?
                                Ast.ArrayAccess(parameters[HiddenParameterCount], Ast.Constant(i)) :
                                parameters[HiddenParameterCount + i];

                result[resultIndex++] = _parameters.LeftValues[i].TransformWrite(gen, parameter);
            }

            if (_parameters.UnsplattedValue != null)
            {
                // the last parameter is unsplat:
                var parameter = parameters[parameters.Length - 1];
                result[resultIndex++] = _parameters.UnsplattedValue.TransformWrite(gen, parameter);
            }

            result[resultIndex++] = Ast.Empty();
            Debug.Assert(resultIndex == result.Length);
            return(AstFactory.Block(result));
        }
Beispiel #4
0
        private MetaObject MakeArrayIndexRule(string oper, MetaObject[] args)
        {
            if (CanConvertFrom(GetArgType(args, 1), typeof(int), false, NarrowingLevel.All))
            {
                Restrictions restrictions = Restrictions.GetTypeRestriction(args[0].Expression, args[0].LimitType).Merge(Restrictions.Combine(args));

                if (oper == StandardOperators.GetItem)
                {
                    return(new MetaObject(
                               Ast.ArrayAccess(
                                   args[0].Expression,
                                   ConvertIfNeeded(args[1].Expression, typeof(int))
                                   ),
                               restrictions
                               ));
                }
                else
                {
                    return(new MetaObject(
                               Ast.Assign(
                                   Ast.ArrayAccess(
                                       args[0].Expression,
                                       ConvertIfNeeded(args[1].Expression, typeof(int))
                                       ),
                                   ConvertIfNeeded(args[2].Expression, args[0].LimitType.GetElementType())
                                   ),
                               restrictions.Merge(args[1].Restrictions)
                               ));
                }
            }

            return(null);
        }
Beispiel #5
0
        // Function Body Code Generation
        //
        // object Func(object self, object[] args) {
        //     object p1 = ...;
        //     object p2 = ...;
        //     ...
        //     object pn = ...;
        //     (..Body..)
        // }
        //
        // <if has_default(p[i]) then>
        //     <p[i]> = <i> < args.Length ? (args[<i>] == void ? <default(p[i])> : args[<i>]) : <default(p[i])>;
        // <else if any_length_args(p[i]) then>
        //     <if has_name(p[i]) then>
        //         <p[i]> = new Array(args.Skip(<i>));
        //     <else>
        //         <p[i]> = new UnnamedSpreadArguments(args, <i>);
        //     <end if>
        // <else>
        //     <p[i]> = <i> < args.Length ? args[<i>] : void;
        // <end if>

        public System.Linq.Expressions.Expression <Func <object, object, object[], object> > TransformLambda()
        {
            List <Ast> body = new List <Ast>();

            for (int i = 0; i < Parameters.Count; i++)
            {
                var capCheck = Ast.LessThan(Ast.Constant(i), Ast.Property(_arguments, "Length"));
                Ast exp;
                if (Parameters[i].HasDefaultValue)
                {
                    exp = Ast.Condition(capCheck,
                                        Ast.Condition(Ast.TypeEqual(Ast.ArrayAccess(_arguments, Ast.Constant(i)), typeof(Builtins.Void)),
                                                      Ast.Constant(Parameters[i].DefaultValue, typeof(object)),
                                                      Ast.ArrayAccess(_arguments, Ast.Constant(i))
                                                      ),
                                        Ast.Constant(Parameters[i].DefaultValue, typeof(object))
                                        );
                }
                else if (Parameters[i].ExpandToArray)
                {
                    if (Parameters[i].ParameterVariable.Name != null)
                    {
                        exp = Ast.New((System.Reflection.ConstructorInfo)Utils.GetMember(() => new Builtins.Array(null)),
                                      Ast.Call(new Func <IEnumerable <object>, int, IEnumerable <object> >(Enumerable.Skip).Method, _arguments, Ast.Constant(i))
                                      );
                    }
                    else
                    {
                        exp = Ast.New((System.Reflection.ConstructorInfo)Utils.GetMember(() => new Runtime.UnnamedSpreadArguments(null, 0)),
                                      _arguments,
                                      Ast.Constant(i)
                                      );
                    }
                }
                else
                {
                    exp = Ast.Condition(capCheck,
                                        Ast.ArrayAccess(_arguments, Ast.Constant(i)),
                                        Ast.Constant(Builtins.Void.Value, typeof(object))
                                        );
                }
                body.Add(Ast.Assign(Parameters[i].ParameterVariable, exp));
            }
            foreach (var statement in Body)
            {
                body.Add(statement.Transform());
            }
            body.Add(Ast.Label(ReturnLabel, Ast.Constant(Builtins.Void.Value)));
            return(Ast.Lambda <Func <object, object, object[], object> >(Ast.Block(_variables.Values.Concat(Parameters.Select(x => x.ParameterVariable)), body), Name, new[] { _global, _context, _arguments }));
        }
Beispiel #6
0
 private MSA.Expression /*!*/ GetParameterAccess(AstParameters /*!*/ parameters, MSA.Expression paramsArray, int i)
 {
     return((paramsArray != null) ? (MSA.Expression)Ast.ArrayAccess(paramsArray, AstUtils.Constant(i)) : parameters[HiddenParameterCount + i]);
 }
        internal override MSAst.Expression TransformSet(SourceSpan span, MSAst.Expression right, PythonOperationKind op)
        {
            // if we just have a simple named multi-assignment  (e.g. a, b = 1,2)
            // then go ahead and step over the entire statement at once.  If we have a
            // more complex statement (e.g. a.b, c.d = 1, 2) then we'll step over the
            // sets individually as they could be property sets the user wants to step
            // into.  TODO: Enable stepping of the right hand side?
            bool emitIndividualSets = false;

            foreach (Expression e in _items)
            {
                if (IsComplexAssignment(e))
                {
                    emitIndividualSets = true;
                    break;
                }
            }

            SourceSpan rightSpan = SourceSpan.None;
            SourceSpan leftSpan  =
                (Span.Start.IsValid && span.IsValid) ?
                new SourceSpan(Span.Start, span.End) :
                SourceSpan.None;

            SourceSpan totalSpan = SourceSpan.None;

            if (emitIndividualSets)
            {
                rightSpan = span;
                leftSpan  = SourceSpan.None;
                totalSpan = (Span.Start.IsValid && span.IsValid) ?
                            new SourceSpan(Span.Start, span.End) :
                            SourceSpan.None;
            }

            // 1. Evaluate the expression and assign the value to the temp.
            MSAst.ParameterExpression right_temp = Ast.Variable(typeof(object), "unpacking");

            // 2. Add the assignment "right_temp = right" into the suite/block
            MSAst.Expression assignStmt1 = MakeAssignment(right_temp, right);

            // 3. Call GetEnumeratorValues on the right side (stored in temp)
            MSAst.Expression enumeratorValues = Expression.Convert(LightExceptions.CheckAndThrow(
                                                                       Expression.Call(
                                                                           emitIndividualSets ?
                                                                           AstMethods.GetEnumeratorValues :
                                                                           AstMethods.GetEnumeratorValuesNoComplexSets, // method
                                                                           // arguments
                                                                           Parent.LocalContext,
                                                                           right_temp,
                                                                           AstUtils.Constant(_items.Length)
                                                                           )
                                                                       ), typeof(object[]));

            // 4. Create temporary variable for the array
            MSAst.ParameterExpression array_temp = Ast.Variable(typeof(object[]), "array");

            // 5. Assign the value of the method call (mce) into the array temp
            // And add the assignment "array_temp = Ops.GetEnumeratorValues(...)" into the block
            MSAst.Expression assignStmt2 = MakeAssignment(
                array_temp,
                enumeratorValues,
                rightSpan
                );

            ReadOnlyCollectionBuilder <MSAst.Expression> sets = new ReadOnlyCollectionBuilder <MSAst.Expression>(_items.Length + 1);

            for (int i = 0; i < _items.Length; i++)
            {
                // target = array_temp[i]

                Expression target = _items[i];
                if (target == null)
                {
                    continue;
                }

                // 6. array_temp[i]
                MSAst.Expression element = Ast.ArrayAccess(
                    array_temp,                             // array expression
                    AstUtils.Constant(i)                    // index
                    );

                // 7. target = array_temp[i], and add the transformed assignment into the list of sets
                MSAst.Expression set = target.TransformSet(
                    emitIndividualSets ?                    // span
                    target.Span :
                    SourceSpan.None,
                    element,
                    PythonOperationKind.None
                    );
                sets.Add(set);
            }
            // 9. add the sets as their own block so they can be marked as a single span, if necessary.
            sets.Add(AstUtils.Empty());
            MSAst.Expression itemSet = GlobalParent.AddDebugInfo(Ast.Block(sets.ToReadOnlyCollection()), leftSpan);

            // 10. Return the suite statement (block)
            return(GlobalParent.AddDebugInfo(Ast.Block(new[] { array_temp, right_temp }, assignStmt1, assignStmt2, itemSet, AstUtils.Empty()), totalSpan));
        }
        private bool MakeDefaultMemberRule(Operators oper)
        {
            if (_types[0].IsArray)
            {
                if (Binder.CanConvertFrom(_types[1], typeof(int), false, NarrowingLevel.All))
                {
                    if (oper == Operators.GetItem)
                    {
                        _rule.Target = _rule.MakeReturn(Binder,
                                                        Ast.ArrayAccess(
                                                            Param0,
                                                            ConvertIfNeeded(Param1, typeof(int))
                                                            )
                                                        );
                    }
                    else
                    {
                        _rule.Target = _rule.MakeReturn(Binder,
                                                        Ast.Assign(
                                                            Ast.ArrayAccess(
                                                                Param0,
                                                                ConvertIfNeeded(Param1, typeof(int))
                                                                ),
                                                            ConvertIfNeeded(Param2, _types[0].GetElementType())
                                                            )
                                                        );
                    }
                    return(true);
                }
            }

            MethodInfo[] defaults = GetMethodsFromDefaults(_types[0].GetDefaultMembers(), oper);
            if (defaults.Length != 0)
            {
                MethodBinder binder = MethodBinder.MakeBinder(Binder,
                                                              oper == Operators.GetItem ? "get_Item" : "set_Item",
                                                              defaults);

                BindingTarget target = binder.MakeBindingTarget(CallTypes.ImplicitInstance, _types);

                if (target.Success)
                {
                    if (oper == Operators.GetItem)
                    {
                        _rule.Target = _rule.MakeReturn(Binder, target.MakeExpression(_rule, _rule.Parameters));
                    }
                    else
                    {
                        _rule.Target = _rule.MakeReturn(Binder,
                                                        Ast.Block(
                                                            target.MakeExpression(_rule, _rule.Parameters),
                                                            _rule.Parameters[2]
                                                            )
                                                        );
                    }
                }
                else
                {
                    _rule.Target = Binder.MakeInvalidParametersError(target).MakeErrorForRule(_rule, Binder);
                }
                return(true);
            }

            return(false);
        }
        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));
        }