public override void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            // See MethodExpr.EmitComplexCall to see why this is so complicated

            //  Build the parameter list

            List <ParameterExpression> paramExprs = new List <ParameterExpression>();
            List <Type> paramTypes = new List <Type>();

            Type paramType            = _target.HasClrType && _target.ClrType != null && _target.ClrType.IsPrimitive ? _target.ClrType : typeof(object);
            ParameterExpression param = Expression.Parameter(paramType);

            paramExprs.Add(param);
            paramTypes.Add(paramType);


            // Build dynamic call and lambda
            Type returnType = HasClrType ? ClrType : typeof(object);

            GetMemberBinder   binder = new ClojureGetZeroArityMemberBinder(ClojureContext.Default, _memberName, false);
            DynamicExpression dyn    = Expression.Dynamic(binder, returnType, paramExprs);

            LambdaExpression lambda;
            Type             delType;
            MethodBuilder    mbLambda;

            MethodExpr.EmitDynamicCallPreamble(dyn, _spanMap, "__interop_" + _memberName + RT.nextID(), returnType, paramExprs, paramTypes.ToArray(), ilg, out lambda, out delType, out mbLambda);

            //  Emit target + args (no args, actually)

            _target.Emit(RHC.Expression, objx, ilg);

            MethodExpr.EmitDynamicCallPostlude(lambda, delType, mbLambda, ilg);
        }
Example #2
0
        private void EmitComplexCall(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            // See the notes on MethodExpr.EmitComplexCall on why this is so complicated

            List <ParameterExpression> paramExprs = new List <ParameterExpression>(_args.Count + 1);
            List <Type> paramTypes = new List <Type>(_args.Count + 1);

            paramExprs.Add(Expression.Parameter(typeof(Type)));
            paramTypes.Add(typeof(Type));

            int i = 0;

            foreach (HostArg ha in _args)
            {
                i++;
                Expr e       = ha.ArgExpr;
                Type argType = e.HasClrType && e.ClrType != null && e.ClrType.IsPrimitive ? e.ClrType : typeof(object);

                switch (ha.ParamType)
                {
                case HostArg.ParameterType.ByRef:
                {
                    Type byRefType = argType.MakeByRefType();
                    paramExprs.Add(Expression.Parameter(byRefType, ha.LocalBinding.Name));
                    paramTypes.Add(byRefType);
                    break;
                }

                case HostArg.ParameterType.Standard:
                    if (argType.IsPrimitive && ha.ArgExpr is MaybePrimitiveExpr)
                    {
                        paramExprs.Add(Expression.Parameter(argType, ha.LocalBinding != null ? ha.LocalBinding.Name : "__temp_" + i));
                        paramTypes.Add(argType);
                    }
                    else
                    {
                        paramExprs.Add(Expression.Parameter(typeof(object), ha.LocalBinding != null ? ha.LocalBinding.Name : "__temp_" + i));
                        paramTypes.Add(typeof(object));
                    }
                    break;

                default:
                    throw Util.UnreachableCode();
                }
            }

            // Build dynamic call and lambda
            Type returnType             = HasClrType ? ClrType : typeof(object);
            CreateInstanceBinder binder = new ClojureCreateInstanceBinder(ClojureContext.Default, _args.Count);

#if CLR2
            // Not covariant. Sigh.
            List <Expression> paramsAsExprs = new List <Expression>(paramExprs.Count);
            paramsAsExprs.AddRange(paramExprs.ToArray());
            DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), paramsAsExprs);
#else
            DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), paramExprs);
#endif

            LambdaExpression lambda;
            Type             delType;
            MethodBuilder    mbLambda;

            MethodExpr.EmitDynamicCallPreamble(dyn, _spanMap, "__interop_ctor_" + RT.nextID(), returnType, paramExprs, paramTypes.ToArray(), ilg, out lambda, out delType, out mbLambda);

            //  Emit target + args

            EmitTargetExpression(objx, ilg);

            i = 0;
            foreach (HostArg ha in _args)
            {
                i++;
                Expr e       = ha.ArgExpr;
                Type argType = e.HasClrType && e.ClrType != null && e.ClrType.IsPrimitive ? e.ClrType : typeof(object);

                switch (ha.ParamType)
                {
                case HostArg.ParameterType.ByRef:
                    MethodExpr.EmitByRefArg(ha, objx, ilg);
                    break;

                case HostArg.ParameterType.Standard:
                    if (argType.IsPrimitive && ha.ArgExpr is MaybePrimitiveExpr)
                    {
                        ((MaybePrimitiveExpr)ha.ArgExpr).EmitUnboxed(RHC.Expression, objx, ilg);
                    }
                    else
                    {
                        ha.ArgExpr.Emit(RHC.Expression, objx, ilg);
                    }
                    break;

                default:
                    throw Util.UnreachableCode();
                }
            }

            MethodExpr.EmitDynamicCallPostlude(lambda, delType, mbLambda, ilg);
        }