static void DefineDelegateFieldAndOverride(TypeBuilder tb, int numArgs) { Type fieldType = FuncTypeHelpers.GetFFuncType(numArgs); string fieldName = "_fn" + numArgs; FieldBuilder fb = tb.DefineField(fieldName, fieldType, FieldAttributes.Public); MethodBuilder mb = tb.DefineMethod("invoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(object), CreateObjectTypeArray(numArgs)); ILGenerator gen = mb.GetILGenerator(); Label eqLabel = gen.DefineLabel(); // this._fni == null ? gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldfld, fb); gen.Emit(OpCodes.Ldnull); gen.Emit(OpCodes.Beq, eqLabel); //Not equal to Null, invoke it. gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldfld, fb); for (int i = 0; i < numArgs; i++) { gen.Emit(OpCodes.Ldarg, i + 1); } gen.Emit(OpCodes.Call, fb.FieldType.GetMethod("Invoke")); gen.Emit(OpCodes.Ret); gen.MarkLabel(eqLabel); // Equal to Null: throw WrongArityException gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Call, Method_AFn_WrongArityException); gen.Emit(OpCodes.Throw); }
internal LambdaExpression GenerateImmediateLambda(RHC rhc, ObjExpr objx, GenContext context) { List <ParameterExpression> parmExprs = new List <ParameterExpression>(_argLocals.count()); if (_thisBinding != null) { _thisBinding.ParamExpression = objx.ThisParam; } try { LabelTarget loopLabel = Expression.Label("top"); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); for (int i = 0; i < _argLocals.count(); i++) { LocalBinding b = (LocalBinding)_argLocals.nth(i); ParameterExpression pexpr = Expression.Parameter(typeof(object), b.Name); b.ParamExpression = pexpr; parmExprs.Add(pexpr); } List <Expression> bodyExprs = new List <Expression>(); //bodyExprs.AddRange(typedParmInitExprs); bodyExprs.Add(Expression.Label(loopLabel)); bodyExprs.Add(Compiler.MaybeBox(_body.GenCode(rhc, objx, context))); Expression block; //if (typedParmExprs.Count > 0) // block = Expression.Block(typedParmExprs, bodyExprs); //else block = Expression.Block(bodyExprs); return(Expression.Lambda( FuncTypeHelpers.GetFFuncType(parmExprs.Count), block, Objx.ThisName, parmExprs)); } finally { Var.popThreadBindings(); } }
internal LambdaExpression GenerateImmediateLambda(GenContext context) { List <ParameterExpression> parmExprs = new List <ParameterExpression>(_argLocals.count()); List <ParameterExpression> typedParmExprs = new List <ParameterExpression>(); List <Expression> typedParmInitExprs = new List <Expression>(); //FnExpr fn = context.FnExpr; //ParameterExpression thisParm = Expression.Parameter(fn.BaseType, "this"); //_thisBinding.ParamExpression = thisParm; //fn.ThisParam = thisParm; FnExpr fn = context.FnExpr; _thisBinding.ParamExpression = fn.ThisParam; try { LabelTarget loopLabel = Expression.Label("top"); Var.pushThreadBindings(RT.map(Compiler.LOOP_LABEL, loopLabel, Compiler.METHODS, this)); for (int i = 0; i < _argLocals.count(); i++) { LocalBinding b = (LocalBinding)_argLocals.nth(i); ParameterExpression pexpr = Expression.Parameter(typeof(object), b.Name); //asdf-tag b.ParamExpression = pexpr; parmExprs.Add(pexpr); if (b.Tag != null) { // we have a type hint // The ParameterExpression above will be the parameter to the function. // We need to generate another local parameter that is typed. // This will be the parameter tied to the LocalBinding so that the typing information is seen in the body. Type t = Compiler.TagToType(b.Tag); ParameterExpression p2 = Expression.Parameter(t, b.Name); b.ParamExpression = p2; typedParmExprs.Add(p2); typedParmInitExprs.Add(Expression.Assign(p2, Expression.Convert(pexpr, t))); } } // TODO: Eventually, type this param to ISeq. // This will require some reworking with signatures in various places around here. //if (fn.IsVariadic) // parmExprs.Add(Expression.Parameter(typeof(object), "____REST")); // If we have any typed parameters, we need to add an extra block to do the initialization. List <Expression> bodyExprs = new List <Expression>(); bodyExprs.AddRange(typedParmInitExprs); bodyExprs.Add(Expression.Label(loopLabel)); bodyExprs.Add(Compiler.MaybeBox(_body.GenDlr(context))); Expression block; if (typedParmExprs.Count > 0) { block = Expression.Block(typedParmExprs, bodyExprs); } else { block = Expression.Block(bodyExprs); } return(Expression.Lambda( FuncTypeHelpers.GetFFuncType(parmExprs.Count), block, _fn.ThisName, parmExprs)); } finally { Var.popThreadBindings(); } }