public DefineMethodOverride ( |
||
baseMethod | ||
return | ILGen |
// This generates a method like the following: // // TrySetExtraValue(object name, object value) { // if (name1 == name) { // type.name1Slot = value; // return 1; // } // if (name2 == name) { // type.name2Slot = value; // return 1; // } // ... // return 0 // } private void MakeSetMethod() { MethodInfo baseMethod = typeof(CustomSymbolDictionary).GetMethod("TrySetExtraValue", BindingFlags.NonPublic | BindingFlags.Instance); ILGen cg = TypeGen.DefineMethodOverride(baseMethod); foreach (KeyValuePair <GlobalVariableExpression, FieldBuilder> kv in _fields) { SymbolId name = SymbolTable.StringToId(kv.Key.Name); EmitSymbolId(cg, name); // arg0 -> this cg.EmitLoadArg(1); cg.EmitCall(typeof(SymbolId), "op_Equality"); Label next = cg.DefineLabel(); cg.Emit(OpCodes.Brfalse_S, next); cg.EmitFieldGet(kv.Value); cg.EmitLoadArg(2); cg.EmitPropertySet(typeof(ModuleGlobalWrapper), "CurrentValue"); cg.EmitInt(1); cg.Emit(OpCodes.Ret); cg.MarkLabel(next); } cg.EmitInt(0); cg.Emit(OpCodes.Ret); }
// // This generates a method like the following: // // TryGetExtraValue(int name, object out value) { // if (name1 == name) { // value = type.name1Slot.RawValue; // return value != Uninitialized.Instance; // } // if (name2 == name) { // value = type.name2Slot.RawValue; // return value != Uninitialized.Instance; // } // ... // return false // } private void MakeGetMethod() { MethodInfo baseMethod = typeof(CustomSymbolDictionary).GetMethod("TryGetExtraValue", BindingFlags.NonPublic | BindingFlags.Instance); ILGen cg = TypeGen.DefineMethodOverride(baseMethod); foreach (KeyValuePair <GlobalVariableExpression, FieldBuilder> kv in _fields) { SymbolId name = SymbolTable.StringToId(kv.Key.Name); EmitSymbolId(cg, name); // arg0 -> this cg.EmitLoadArg(1); cg.EmitCall(typeof(SymbolId), "op_Equality"); Label next = cg.DefineLabel(); cg.Emit(OpCodes.Brfalse_S, next); cg.EmitLoadArg(2); // Expects to push as an object. EmitGetRawFromObject(cg, kv.Value); cg.Emit(OpCodes.Stind_Ref); EmitGetRawFromObject(cg, kv.Value); cg.EmitFieldGet(typeof(Uninitialized), "Instance"); cg.Emit(OpCodes.Ceq); cg.Emit(OpCodes.Not); cg.Emit(OpCodes.Ret); cg.MarkLabel(next); } cg.EmitInt(0); cg.Emit(OpCodes.Ret); }
private static void EmitOverrideGetHashCode(TypeGen typeGen) { Type baseType = typeGen.TypeBuilder.BaseType; MethodInfo baseMethod = baseType.GetMethod("GetHashCode", Type.EmptyTypes); Compiler cg = typeGen.DefineMethodOverride(baseMethod); // Check if a "hash" method exists on this class cg.EmitType(typeGen.TypeBuilder); cg.EmitString("hash"); cg.EmitCall(typeof(RubyOps).GetMethod("ResolveDeclaredInstanceMethod")); Label callBase = cg.DefineLabel(); cg.Emit(OpCodes.Brfalse_S, callBase); // If so, call it cg.EmitThis(); cg.EmitCall(typeof(RubyOps).GetMethod("CallHash")); cg.EmitReturn(); // Otherwise, call base class cg.MarkLabel(callBase); cg.EmitThis(); cg.Emit(OpCodes.Call, baseMethod); // base call must be non-virtual cg.EmitReturn(); cg.Finish(); }
// we need to get the right execution context #if OBSOLETE private static void EmitOverrideEquals(TypeGen typeGen) { Type baseType = typeGen.TypeBuilder.BaseType; MethodInfo baseMethod = baseType.GetMethod("Equals", new Type[] { typeof(object) }); Compiler cg = typeGen.DefineMethodOverride(baseMethod); // Check if an "eql?" method exists on this class cg.EmitType(typeGen.TypeBuilder); cg.EmitString("eql?"); cg.EmitCall(typeof(RubyOps).GetMethod("ResolveDeclaredInstanceMethod")); Label callBase = cg.DefineLabel(); cg.Emit(OpCodes.Brfalse_S, callBase); // If so, call it cg.EmitThis(); cg.EmitArgGet(0); cg.EmitCall(typeof(RubyOps).GetMethod("CallEql")); cg.EmitReturn(); // Otherwise, call base class cg.MarkLabel(callBase); cg.EmitThis(); cg.EmitArgGet(0); cg.Emit(OpCodes.Call, baseMethod); // base call must be non-virtual cg.EmitReturn(); cg.Finish(); }