उत्पन्न आउटपुट में उत्सर्जित विधि को नहीं बुलाया जा रहा है


मैं एक छोटा डीएफए कंपाइलर बना रहा हूं जो System.Reflection.Emit का उपयोग करके सीधे असेंबली में प्रस्तुत होता है

ध्यान दें कि नीचे एक FALIB परिभाषा है। जब कंपाइलर का उपयोग किया जाता है तो इसे हमेशा परिभाषित किया जाएगा।

मेरा आईएल कोड इसका एक ठोस संस्करण लागू करने वाला है

#if FALIB
public
#endif
abstract partial class FARunner
{
		
	protected abstract int MatchImpl(LexContext lc);
	protected abstract FAMatch SearchImpl(LexContext lc);
	/// <summary>
	/// Searches through text for the next occurance of a pattern matchable by this machine
	/// </summary>
	/// <param name="lc">The <see cref="LexContext"/> with the text to search</param>
	/// <returns>A series of <see cref="FAMatch"/> instances with the matches</returns>
	public IEnumerable<FAMatch> Search(LexContext lc)
	{
		while(lc.Current!=LexContext.EndOfInput)
		{
			yield return SearchImpl(lc);
		}
	}
	/// <summary>
	/// Indicates whether this machine will match the indicated text
	/// </summary>
	/// <param name="lc">A <see cref="LexContext"/> containing the text</param>
	/// <returns>The accept symbol if matched, otherwise -1.</returns>
	public int Match(LexContext lc)
	{
		return MatchImpl(lc);
	}
	/// <summary>
	/// Searches through text for the next occurance of a pattern matchable by this machine
	/// </summary>
	/// <param name="@string">The <see cref="IEnumerable{char}"/> with the text to search</param>
	/// <returns>A series of <see cref="FAMatch"/> instances with the matches</returns>
	public IEnumerable<FAMatch> Search(IEnumerable<char> @string)
	{
		foreach (var match in Search(LexContext.Create(@string)))
		{
			yield return match;
		}
	}
	/// <summary>
	/// Searches through text for the next occurance of a pattern matchable by this machine
	/// </summary>
	/// <param name="reader">The <see cref="TextReader"/> with the text to search</param>
	/// <returns>A series of <see cref="FAMatch"/> instances with the matches</returns>
	public IEnumerable<FAMatch> Search(TextReader reader)
	{
		foreach (var match in Search(LexContext.CreateFrom(reader)))
		{
			yield return match;
		}
	}
	/// <summary>
	/// Indicates whether this machine will match the indicated text
	/// </summary>
	/// <param name="text">The text</param>
	/// <returns>True if the passed in text was a match, otherwise false.</returns>
	public int Match(IEnumerable<char> text)
	{
		return Match(LexContext.Create(text));
	}

}

इसे केवल ठोस तरीकों से SearchImpl और MatchImpl भरने की जरूरत है, जो मैंने किया है, हालांकि वे वर्तमान में लागू नहीं हैं।

मुझे जो परेशानी हो रही है वह यह है – मैचइम्पल विधि बिल्कुल ठीक कॉल करती है।

SearchImpl विधि – अच्छा यह अजीब है। इसे न केवल कॉल किया जाता है, न ही इसे सौंपने वाली कोई भी विधि। मुझे कोई त्रुटि, कंपाइलर थ्रो या रनटाइम नहीं मिला। जब मैं इसे कॉल करने का प्रयास करता हूं तो यह चुपचाप विफल हो जाता है।

एकमात्र चीज जिसके बारे में मैं सोच सकता हूं वह यह है कि मेरा रिटर्न प्रकार एक संरचना है। यहाँ केवल यही अंतर है जो मैं देख सकता हूँ – ख़ैर वह और नाम।

मैंने क्या प्रयास किया है:

सी#
public static partial class FACompiler
{
	public static FARunner Compile(this FA fa, IProgress<int> progress = null)
	{
		if (fa == null) throw new ArgumentNullException(nameof(fa));
		fa = fa.ToDfa(progress);
		var name = "FARunner" + fa.GetHashCode();
		var asmName = new AssemblyName(name);
		var asm = Thread.GetDomain().DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run);
		ModuleBuilder mod = asm.DefineDynamicModule("M"+name);
		TypeBuilder type = mod.DefineType(name, TypeAttributes.Public | TypeAttributes.Sealed, typeof(FARunner));
		Type[] paramTypes = new Type[] { typeof(LexContext) };
		Type searchReturnType = typeof(FAMatch);
		MethodBuilder searchImpl = type.DefineMethod("SearchImpl", MethodAttributes.Public | MethodAttributes.ReuseSlot |
			MethodAttributes.Virtual | MethodAttributes.HideBySig, searchReturnType, paramTypes);
		ILGenerator searchGen = searchImpl.GetILGenerator();
		searchGen.ThrowException(typeof(NotImplementedException));
			
		MethodInfo searchImplBase = typeof(FARunner).GetMethod("SearchImpl",BindingFlags.NonPublic | BindingFlags.Instance);
		type.DefineMethodOverride(searchImpl, searchImplBase);

		Type matchReturnType = typeof(int);
		MethodBuilder match = type.DefineMethod("MatchImpl", MethodAttributes.Public | MethodAttributes.ReuseSlot |
			MethodAttributes.Virtual | MethodAttributes.HideBySig, matchReturnType, paramTypes);
		ILGenerator matchGen = match.GetILGenerator();
		matchGen.ThrowException(typeof(NotImplementedException));
		MethodInfo matchBase = typeof(FARunner).GetMethod("MatchImpl", BindingFlags.NonPublic | BindingFlags.Instance);
		type.DefineMethodOverride(match, matchBase);

		Type newType = type.CreateType();

		return (FARunner)Activator.CreateInstance(newType);

	}
}

मैंने स्टैक को समायोजित करने के लिए इन पंक्तियों को जोड़ने का भी प्रयास किया, यदि मुझे थ्रो की स्थिति में भी इसे भरने की आवश्यकता होती:

सी#
LocalBuilder famatch = searchGen.DeclareLocal(typeof(FAMatch));
searchGen.Emit(OpCodes.Ldloca_S, famatch);
searchGen.Emit(OpCodes.Initobj, typeof(FAMatch));

मुझे वही परिणाम मिलते हैं।

समाधान 1

मुझे समझ में नहीं आता कि ऐसा क्यों है, लेकिन जब मैंने अपने FARunner क्लास से यील्ड ली और अपने गणनाकर्ता को हाथ से लागू किया तो सब कुछ ठीक से काम करने लगा।

मैं इसे सुलझा हुआ मान कर बंद कर रहा हूं, भले ही मैं भ्रमित हूं।

コメント

タイトルとURLをコピーしました