public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
{
Label endLabel = ilg.DefineLabel();
Label faultLabel = ilg.DefineLabel();
GenContext.EmitDebugInfo(ilg, _spanMap);
LocalBuilder thunkLoc = ilg.DeclareLocal(typeof(ILookupThunk));
LocalBuilder targetLoc = ilg.DeclareLocal(typeof(Object));
LocalBuilder resultLoc = ilg.DeclareLocal(typeof(Object));
GenContext.SetLocalName(thunkLoc, "thunk");
GenContext.SetLocalName(targetLoc, "target");
GenContext.SetLocalName(resultLoc, "result");
// TODO: Debug info
// pseudo-code:
// ILookupThunk thunk = objclass.ThunkField(i)
// object target = ...code...
// object val = thunk.get(target)
// if ( val != thunk )
// return val
// else
// KeywordLookupSite site = objclass.SiteField(i)
// thunk = site.fault(target)
// objclass.ThunkField(i) = thunk
// val = thunk.get(target)
// return val
ilg.EmitFieldGet(objx.ThunkField(_siteIndex)); // thunk
ilg.Emit(OpCodes.Stloc, thunkLoc); // (thunkLoc <= thunk)
_target.Emit(RHC.Expression, objx, ilg); // target
ilg.Emit(OpCodes.Stloc, targetLoc); // (targetLoc <= target)
ilg.Emit(OpCodes.Ldloc, thunkLoc);
ilg.Emit(OpCodes.Ldloc, targetLoc);
ilg.EmitCall(Compiler.Method_ILookupThunk_get); // result
ilg.Emit(OpCodes.Stloc, resultLoc); // (resultLoc <= result)
ilg.Emit(OpCodes.Ldloc, thunkLoc);
ilg.Emit(OpCodes.Ldloc, resultLoc);
ilg.Emit(OpCodes.Beq, faultLabel);
ilg.Emit(OpCodes.Ldloc, resultLoc); // result
ilg.Emit(OpCodes.Br, endLabel);
ilg.MarkLabel(faultLabel);
ilg.EmitFieldGet(objx.KeywordLookupSiteField(_siteIndex)); // site
ilg.Emit(OpCodes.Ldloc, targetLoc); // site, target
ilg.EmitCall(Compiler.Method_ILookupSite_fault); // new-thunk
ilg.Emit(OpCodes.Dup); // new-thunk, new-thunk
ilg.EmitFieldSet(objx.ThunkField(_siteIndex)); // new-thunk
ilg.Emit(OpCodes.Ldloc, targetLoc); // new-thunk, target
ilg.EmitCall(Compiler.Method_ILookupThunk_get); // result
ilg.MarkLabel(endLabel); // result
if (rhc == RHC.Statement)
{
ilg.Emit(OpCodes.Pop);
}
}