لا يتم استدعاء الطريقة المنبعثة في المخرجات التي تم إنشاؤها


أقوم بإنشاء مترجم DFA صغير يتم عرضه مباشرة على التجميع باستخدام System.Reflection.Emit

لاحظ أنه يوجد أدناه تعريف FALIB. سيتم تعريف هذا دائمًا عند استخدام المترجم.

من المفترض أن يقوم كود IL الخاص بي بتنفيذ نسخة محددة من هذا

#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 بطرق ملموسة، وهو ما قمت به على الرغم من عدم تنفيذهما حاليًا.

المشكلة التي أواجهها هي أن طريقة 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をコピーしました