private DynamicMetaObject InvokeFallback(DynamicMetaObjectBinder action, Expression codeContext, DynamicMetaObject /*!*/[] args)
        {
            InvokeBinder ib = action as InvokeBinder;

            if (ib != null)
            {
                if (_baseMetaObject != null)
                {
                    return(_baseMetaObject.BindInvoke(ib, args));
                }

                return(ib.FallbackInvoke(this.Restrict(this.GetLimitType()), args));
            }

            PythonInvokeBinder pib = action as PythonInvokeBinder;

            if (pib != null)
            {
                IPythonInvokable ipi = _baseMetaObject as IPythonInvokable;
                if (ipi != null)
                {
                    return(ipi.Invoke(pib, codeContext, this, args));
                }

                if (_baseMetaObject != null)
                {
                    return(pib.InvokeForeignObject(this, args));
                }

                return(pib.Fallback(codeContext, this, args));
            }

            // unreachable, we always have one of these binders
            throw new InvalidOperationException();
        }
        private DynamicMetaObject BindWorker(DynamicMetaObject /*!*/ context, DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            // we don't have CodeContext if an IDO falls back to us when we ask them to produce the Call
            IPythonInvokable icc = target as IPythonInvokable;

            if (icc != null)
            {
                // call it and provide the context
                return(icc.Invoke(
                           this,
                           context.Expression,
                           target,
                           args
                           ));
            }
            else if (target.Value is IDynamicMetaObjectProvider)
            {
                return(InvokeForeignObject(target, args));
            }
#if FEATURE_COM
            else if (Microsoft.Scripting.ComInterop.ComBinder.CanComBind(target.Value))
            {
                return(InvokeForeignObject(target, args));
            }
#endif

            return(Fallback(context.Expression, target, args));
        }