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); }
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); }