Esempio n. 1
0
        public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
            ContractUtils.RequiresNotNull(target, "target");
            ContractUtils.RequiresNotNull(target, "args");

            // there must be only one argument and it is always object[].
            // see SplatCallSite.Invoke
            Debug.Assert(args.Length == 1);
            Debug.Assert(args[0] != null);
            Debug.Assert(args[0].Expression.Type == typeof(object[]));


            // We know it is an array.
            DynamicMetaObject arg = args[0];

            Expression argAsArrayExpr = arg.Expression;

            object[] argValues = (object[])arg.Value;
            int argLen = argValues.Length;

            DynamicMetaObject[] splattedArgs = new DynamicMetaObject[argLen];
            ArgumentInfo[] arginfos = new ArgumentInfo[argLen];

            for (int i = 0; i < argLen; i++) {
                Expression argExpr = Expression.ArrayIndex(
                    argAsArrayExpr,
                    Expression.Constant(i)
                );

                splattedArgs[i] = new DynamicMetaObject(
                    argExpr,
                    BindingRestrictions.Empty,
                    argValues[i]
                );
                arginfos[i] = Expression.ByRefArgument(i);
            }


            BindingRestrictions arrayLenRestriction = BindingRestrictions.GetExpressionRestriction(
                Expression.Equal(
                    Expression.ArrayLength(
                        argAsArrayExpr
                    ),
                    Expression.Constant(argLen)
                )
            );

            ComInvokeAction invokeBinder = new ComInvokeAction(arginfos);
            DynamicMetaObject innerAction = target.BindInvoke(invokeBinder, splattedArgs);

            BindingRestrictions restrictions =
                target.Restrictions.
                Merge(arg.Restrictions).
                Merge(arrayLenRestriction).
                Merge(innerAction.Restrictions);

            return new DynamicMetaObject(
                innerAction.Expression,
                restrictions
            );
        }
Esempio n. 2
0
        internal static bool IsStrongBoxArg(DynamicMetaObject o, ArgumentInfo argInfo) {
            if (argInfo.IsByRef) {
                return false;
            }

            Type t = o.LimitType;
            return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(StrongBox<>);
        }
Esempio n. 3
0
        internal DelegateSignatureInfo(LanguageContext context, Type returnType, ParameterInfo[] parameters) {
            Assert.NotNull(context, returnType);
            Assert.NotNullItems(parameters);

            _context = context;
            _parameters = parameters;
            _returnType = returnType;
            
            if (_returnType != typeof(void)) {
                _convert = _context.CreateConvertBinder(_returnType, true);
            }
            
            ArgumentInfo[] args = new ArgumentInfo[_parameters.Length];
            for (int i = 0; i < args.Length; i++) {
                args[i] = Expression.PositionalArg(i);
            }

            _invoke = _context.CreateInvokeBinder(args);
        }
 private static void AppendArgument(StringBuilder builder, ArgumentInfo argument)
 {
     builder.Append("[");
     builder.Append(argument.ArgumentType.Name);
     builder.Append("]");
     builder.Append(" ");
     builder.Append(argument.Name);
 }
 public RubyInvokeMemberBinder(RubyContext/*!*/ context, string/*!*/ name, ArgumentInfo[]/*!*/ arguments)
     : base(name, false, arguments) {
     _context = context;
 }
        /// <summary>
        /// Generates stub to receive the CLR call and then call the dynamic language code.
        /// </summary>
        private object[] EmitClrCallStub(ILGen cg) {

            List<ReturnFixer> fixers = new List<ReturnFixer>(0);
            ArgumentInfo[] args = new ArgumentInfo[_parameters.Length];
            for (int i = 0; i < args.Length; i++) {
                args[i] = Expression.PositionalArg(i);
            }
            ConvertBinder convert = _context.CreateConvertBinder(_returnType, true);
            InvokeBinder action = _context.CreateInvokeBinder(args);


            // Create strongly typed return type from the site.
            // This will, among other things, generate tighter code.
            Type[] siteTypes = MakeSiteSignature();
            
            Type siteType = DynamicSiteHelpers.MakeCallSiteType(siteTypes);            
            CallSite callSite = DynamicSiteHelpers.MakeSite(action, siteType);

            Type convertSiteType = null;
            CallSite convertSite = null;

            if (_returnType != typeof(void)) {
                convertSiteType = DynamicSiteHelpers.MakeCallSiteType(typeof(object), _returnType);
                convertSite = DynamicSiteHelpers.MakeSite(convert, convertSiteType);
            }

            // build up constants array
            object[] constants = new object[] { TargetPlaceHolder, callSite, convertSite };
            const int TargetIndex = 0, CallSiteIndex = 1, ConvertSiteIndex = 2;

            LocalBuilder convertSiteLocal = null;
            FieldInfo convertTarget = null;
            if (_returnType != typeof(void)) {
                // load up the conversesion logic on the stack
                convertSiteLocal = cg.DeclareLocal(convertSiteType);
                EmitConstantGet(cg, ConvertSiteIndex, convertSiteType);

                cg.Emit(OpCodes.Dup);
                cg.Emit(OpCodes.Stloc, convertSiteLocal);

                convertTarget = convertSiteType.GetField("Target");
                cg.EmitFieldGet(convertTarget);
                cg.Emit(OpCodes.Ldloc, convertSiteLocal);
            }

            // load up the invoke logic on the stack
            LocalBuilder site = cg.DeclareLocal(siteType);
            EmitConstantGet(cg, CallSiteIndex, siteType);
            cg.Emit(OpCodes.Dup);
            cg.Emit(OpCodes.Stloc, site);

            FieldInfo target = siteType.GetField("Target");
            cg.EmitFieldGet(target);
            cg.Emit(OpCodes.Ldloc, site);

            EmitConstantGet(cg, TargetIndex, typeof(object));

            for (int i = 0; i < _parameters.Length; i++) {
                if (_parameters[i].ParameterType.IsByRef) {
                    ReturnFixer rf = ReturnFixer.EmitArgument(cg, i + 1, _parameters[i].ParameterType);
                    if (rf != null) fixers.Add(rf);
                } else {
                    cg.EmitLoadArg(i + 1);
                }
            }

            // emit the invoke for the call
            cg.EmitCall(target.FieldType, "Invoke");

            // emit the invoke for the convert
            if (_returnType == typeof(void)) {
                cg.Emit(OpCodes.Pop);
            } else {
                cg.EmitCall(convertTarget.FieldType, "Invoke");
            }

            // fixup any references
            foreach (ReturnFixer rf in fixers) {
                rf.FixReturn(cg);
            }

            cg.Emit(OpCodes.Ret);
            return constants;
        }
 public RubyCreateInstanceBinder(RubyContext/*!*/ context, ArgumentInfo[]/*!*/ arguments)
     : base(arguments) {
     _context = context;
 }
Esempio n. 8
0
        // this helper prepares arguments for COM binding by transforming ByVal StongBox arguments
        // into ByRef expressions that represent the argument's Value fields.
        internal static void ProcessArgumentsForCom(ref DynamicMetaObject[] args, ref IList<ArgumentInfo> argInfos) {
            Debug.Assert(args != null);
           
            DynamicMetaObject[] newArgs = new DynamicMetaObject[args.Length];
            ArgumentInfo[] newArgInfos = new ArgumentInfo[args.Length];

            bool hasArgInfos = HasArgInfos(args, argInfos);

            for (int i = 0; i < args.Length; i++) {
                DynamicMetaObject curArgument = args[i];

                // set new arg infos to their original values or set default ones
                // we will do this fixup early so that we can assume we always have
                // arginfos in COM binder.
                if (hasArgInfos) {
                    newArgInfos[i] = argInfos[i];
                } else {
                    // TODO: this fixup should not be needed once refness is expressed only by argInfos
                    if (IsByRef(curArgument)) {
                        newArgInfos[i] = Expression.ByRefPositionalArgument(i);
                    } else {
                        newArgInfos[i] = Expression.PositionalArg(i);
                    }
                }

                if (IsStrongBoxArg(curArgument, newArgInfos[i])) {


                    var restrictions = curArgument.Restrictions.Merge(
                        GetTypeRestrictionForDynamicMetaObject(curArgument)
                    );

                    // we have restricted this argument to LimitType so we can convert and conversion will be trivial cast.
                    Expression boxedValueAccessor = Expression.Field(
                        Helpers.Convert(
                            curArgument.Expression,
                            curArgument.LimitType
                        ),
                        curArgument.LimitType.GetField("Value")
                    );

                    IStrongBox value = curArgument.Value as IStrongBox;
                    object boxedValue = value != null ? value.Value : null;

                    newArgs[i] = new DynamicMetaObject(
                        boxedValueAccessor,
                        restrictions,
                        boxedValue
                    );

                    NamedArgumentInfo nai = newArgInfos[i] as NamedArgumentInfo;
                    if (nai != null) {
                        newArgInfos[i] = Expression.ByRefNamedArgument(nai.Name);
                    } else {
                        newArgInfos[i] = Expression.ByRefPositionalArgument(i);
                    }
                } else {
                    newArgs[i] = curArgument;
                }
            }

            args = newArgs;
            argInfos = newArgInfos;
        }
Esempio n. 9
0
        private static Type MarshalType(DynamicMetaObject mo, ArgumentInfo ainf) {
            Type marshalType = (mo.Value == null && mo.HasValue) ? null : mo.LimitType;

            // we are not checking that mo.Expression is writeable or whether evaluating it has no sideeffects
            // the assumption is that whoever matched it with ByRef arginfo took care of this.
            if (ainf.IsByRef){
                // Null just means that null was supplied.
                if (marshalType == null) {
                    marshalType = mo.Expression.Type;
                }
                marshalType = marshalType.MakeByRefType();
            }
            return marshalType;
        }
Esempio n. 10
0
 private static void WriteArgument(StringBuilderOutputWriter builder, ArgumentInfo argument)
 {
     builder.Write("[");
     builder.Write(argument.ArgumentType.Name);
     builder.Write("]");
     builder.Write(" ");
     builder.Write(argument.Name);
 }