Example #1
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
                       ));
        }