private void DoEmitPrim(ObjExpr fn, TypeBuilder tb)
{
MethodAttributes attribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual;
string methodName = "invokePrim";
Type returnType;
if (_retType == typeof(double) || _retType == typeof(long))
returnType = ReturnType;
else
returnType = typeof(object);
MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, returnType, _argTypes);
SetCustomAttributes(baseMB);
CljILGen baseIlg = new CljILGen(baseMB.GetILGenerator());
try
{
Label loopLabel = baseIlg.DefineLabel();
Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));
GenContext.EmitDebugInfo(baseIlg, SpanMap);
baseIlg.MarkLabel(loopLabel);
EmitBody(Objx, baseIlg, _retType, Body);
if (Body.HasNormalExit())
baseIlg.Emit(OpCodes.Ret);
}
finally
{
Var.popThreadBindings();
}
// Generate the regular invoke, calling the prim method
MethodBuilder regularMB = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), ArgTypes);
SetCustomAttributes(regularMB);
CljILGen regIlg = new CljILGen(regularMB.GetILGenerator());
regIlg.Emit(OpCodes.Ldarg_0);
for (int i = 0; i < _argTypes.Length; i++)
{
regIlg.EmitLoadArg(i + 1);
HostExpr.EmitUnboxArg(fn, regIlg, _argTypes[i]);
}
regIlg.Emit(OpCodes.Call, baseMB);
if (ReturnType.IsValueType)
regIlg.Emit(OpCodes.Box, ReturnType);
regIlg.Emit(OpCodes.Ret);
}