Beispiel #1
0
        /// <summary>
        /// Gets an expression which is used for accessing this slot.  If the slot lookup fails the error expression
        /// is used again.
        ///
        /// The default implementation just calls the TryGetValue method.  Subtypes of PythonTypeSlot can override
        /// this and provide a more optimal implementation.
        /// </summary>
        internal virtual void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder)
        {
            ParameterExpression tmp  = Ast.Variable(typeof(object), "slotTmp");
            Expression          call = Ast.Call(
                typeof(PythonOps).GetMethod("SlotTryGetValue"),
                codeContext,
                AstUtils.Convert(AstUtils.WeakConstant(this), typeof(PythonTypeSlot)),
                instance != null ? instance.Expression : AstUtils.Constant(null),
                owner.Expression,
                tmp
                );

            builder.AddVariable(tmp);
            if (!GetAlwaysSucceeds)
            {
                builder.AddCondition(
                    call,
                    tmp
                    );
            }
            else
            {
                builder.FinishCondition(Ast.Block(call, tmp));
            }
        }
Beispiel #2
0
        /// <summary>
        /// target is the newly initialized value.
        /// args are the arguments to be passed to __init__
        /// </summary>
        public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            DynamicMetaObject codeContext = target;
            CodeContext       context     = (CodeContext)codeContext.Value;

            target = args[0];
            args   = ArrayUtils.RemoveFirst(args);

            ValidationInfo valInfo = BindingHelpers.GetValidationInfo(target);

            Expression          res;
            PythonType          instType         = DynamicHelpers.GetPythonType(target.Value);
            BindingRestrictions initRestrictions = BindingRestrictions.Empty;

            if (IronPython.Modules.Builtin.isinstance(target.Value, _newType) &&
                NeedsInitCall((CodeContext)codeContext.Value, instType, args.Length))
            {
                // resolve __init__
                PythonTypeSlot init;
                instType.TryResolveSlot(context, "__init__", out init);

                if (init is PythonFunction)
                {
                    // avoid creating the bound method, just invoke it directly
                    Expression[] allArgs = new Expression[args.Length + 3];
                    allArgs[0] = codeContext.Expression;
                    allArgs[1] = AstUtils.WeakConstant(init);
                    allArgs[2] = target.Expression;
                    for (int i = 0; i < args.Length; i++)
                    {
                        allArgs[3 + i] = args[i].Expression;
                    }

                    res = DynamicExpression.Dynamic(
                        context.LanguageContext.Invoke(_signature.InsertArgument(Argument.Simple)),
                        typeof(object),
                        allArgs
                        );
                }
                else if (init is BuiltinMethodDescriptor || init is BuiltinFunction)
                {
                    IList <MethodBase> targets;
                    if (init is BuiltinMethodDescriptor)
                    {
                        targets = ((BuiltinMethodDescriptor)init).Template.Targets;
                    }
                    else
                    {
                        targets = ((BuiltinFunction)init).Targets;
                    }

                    PythonBinder binder = context.LanguageContext.Binder;

                    DynamicMetaObject initInvoke = binder.CallMethod(
                        new PythonOverloadResolver(
                            binder,
                            target,
                            args,
                            _signature,
                            codeContext.Expression
                            ),
                        targets,
                        BindingRestrictions.Empty
                        );

                    res = initInvoke.Expression;
                    initRestrictions = initInvoke.Restrictions;
                }
                else
                {
                    // some weird descriptor has been put in place for __init__, we need
                    // to call __get__ on it each time.
                    res = MakeDynamicInitInvoke(
                        context,
                        args,
                        Expression.Call(
                            typeof(PythonOps).GetMethod("GetInitSlotMember"),
                            codeContext.Expression,
                            Expression.Convert(AstUtils.WeakConstant(_newType), typeof(PythonType)),
                            Expression.Convert(AstUtils.WeakConstant(init), typeof(PythonTypeSlot)),
                            AstUtils.Convert(target.Expression, typeof(object))
                            ),
                        codeContext.Expression
                        );
                }
            }
            else
            {
                // returned something that isn't a subclass of the creating type
                // __init__ will not be run.
                res = AstUtils.Empty();
            }

            // check for __del__
            PythonTypeSlot delSlot;

            if (instType.TryResolveSlot(context, "__del__", out delSlot))
            {
                res = Expression.Block(
                    res,
                    Expression.Call(
                        typeof(PythonOps).GetMethod("InitializeForFinalization"),
                        codeContext.Expression,
                        AstUtils.Convert(target.Expression, typeof(object))
                        )
                    );
            }

            return(BindingHelpers.AddDynamicTestAndDefer(
                       this,
                       new DynamicMetaObject(
                           Expression.Block(
                               res,
                               target.Expression
                               ),
                           target.Restrict(target.LimitType).Restrictions.Merge(initRestrictions)
                           ),
                       args,
                       valInfo
                       ));
        }