/// <summary> /// Reduces the provided DynamicExpression into site.Target(site, *args). /// </summary> public Expression ReduceDyn(DynamicExpression node, out SiteInfo siteInfo) { MaybeInit(); if (RewriteDelegate(node.DelegateType, out Type delegateType)) { node = Expression.MakeDynamic(delegateType, node.Binder, node.Arguments); } CallSite cs = CallSite.Create(node.DelegateType, node.Binder); // TODO: fix this eventually to return the SiteInfo and not the Expression Expression access = RewriteCallSite(cs, _typeGen, delegateType ?? node.DelegateType, out siteInfo); // ($site = siteExpr).Target.Invoke($site, *args) ParameterExpression site = Expression.Variable(cs.GetType(), "$site"); return(Expression.Block( new[] { site }, Expression.Call( Expression.Field( Expression.Assign(site, access), cs.GetType().GetField("Target") ), node.DelegateType.GetMethod("Invoke"), ClrExtensions.ArrayInsert(site, node.Arguments) ) )); }
private Expression GenerateComplexCall(ObjExpr objx, GenContext context) { Expression call; Expression target = GenTargetExpression(objx, context); List <Expression> exprs = new List <Expression>(_args.Count); List <ParameterExpression> sbParams = new List <ParameterExpression>(); List <Expression> sbInits = new List <Expression>(); List <Expression> sbTransfers = new List <Expression>(); GenerateComplexArgList(objx, context, _args, out exprs, out sbParams, out sbInits, out sbTransfers); Expression[] argExprs = ClrExtensions.ArrayInsert <Expression>(target, exprs); Type returnType = HasClrType ? ClrType : typeof(object); // TODO: Get rid of Default InvokeMemberBinder binder = new ClojureInvokeMemberBinder(ClojureContext.Default, _methodName, argExprs.Length, IsStaticCall); //DynamicExpression dyn = Expression.Dynamic(binder, returnType, argExprs); DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), argExprs); //if (context.Mode == CompilerMode.File) if (context.DynInitHelper != null) { call = context.DynInitHelper.ReduceDyn(dyn); } else { call = dyn; } if (returnType == typeof(void)) { call = Expression.Block(call, Expression.Default(typeof(object))); } else { call = Expression.Convert(call, returnType); } if (sbParams.Count > 0) { // We have ref/out params. Construct the complicated call; ParameterExpression callValParam = Expression.Parameter(returnType, "__callVal"); ParameterExpression[] allParams = ClrExtensions.ArrayInsert <ParameterExpression>(callValParam, sbParams); call = Expression.Block( returnType, allParams, Expression.Block(sbInits), Expression.Assign(callValParam, call), Expression.Block(sbTransfers), callValParam); } return(call); }
internal void LightEmit(ObjExpr fn, Type fnType) { if (DynMethod != null) { return; } if (Prim != null || fn.IsStatic) { throw new InvalidOperationException("No light compile allowed for static methods or methods with primitive interfaces"); } Type[] argTypes = ClrExtensions.ArrayInsert(fnType, GetArgTypes()); DynamicMethod meth = new DynamicMethod(GetMethodName(), GetReturnType(), argTypes, true); CljILGen baseIlg = new CljILGen(meth.GetILGenerator()); try { Label loopLabel = baseIlg.DefineLabel(); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); //GenContext.EmitDebugInfo(baseIlg, SpanMap); baseIlg.MarkLabel(loopLabel); _body.Emit(RHC.Return, fn, baseIlg); if (_body.HasNormalExit()) { baseIlg.Emit(OpCodes.Ret); } } finally { Var.popThreadBindings(); } DynMethod = meth; }
// TODO: See if it is worth removing the code duplication with MethodExp.GenDlr. private Expression GenerateComplexCall(RHC rhc, ObjExpr objx, GenContext context) { Expression call; Expression target = GenTargetExpression(objx, context); List <Expression> exprs = new List <Expression>(_args.Count); List <ParameterExpression> sbParams = new List <ParameterExpression>(); List <Expression> sbInits = new List <Expression>(); List <Expression> sbTransfers = new List <Expression>(); MethodExpr.GenerateComplexArgList(objx, context, _args, out exprs, out sbParams, out sbInits, out sbTransfers); Expression[] argExprs = ClrExtensions.ArrayInsert <Expression>(target, exprs); Type returnType = this.ClrType; Type stubType = Compiler.CompileStubOrigClassVar.isBound ? (Type)Compiler.CompileStubOrigClassVar.deref() : null; if (returnType == stubType) { returnType = objx.BaseType; } // TODO: get rid of Default CreateInstanceBinder binder = new ClojureCreateInstanceBinder(ClojureContext.Default, _args.Count); DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), argExprs); // I'd like to use returnType in place of typeof(object) in the previous, // But I can't override ReturnType in DefaultCreateInstanceBinder and this causes an error. // Look for the conversion below. //if (context.Mode == CompilerMode.File) if (context.DynInitHelper != null) { call = context.DynInitHelper.ReduceDyn(dyn); } else { call = dyn; } call = Expression.Convert(call, returnType); if (sbParams.Count > 0) { // We have ref/out params. Construct the complicated call; ParameterExpression callValParam = Expression.Parameter(returnType, "__callVal"); ParameterExpression[] allParams = ClrExtensions.ArrayInsert <ParameterExpression>(callValParam, sbParams); call = Expression.Block( returnType, allParams, Expression.Block(sbInits), Expression.Assign(callValParam, call), Expression.Block(sbTransfers), callValParam); } return(call); }