Phương thức phát ra không được gọi trong đầu ra được tạo

lập trình


Tôi đang tạo một trình biên dịch DFA nhỏ hiển thị trực tiếp cho một tập hợp bằng System.Reflection.Emit

Lưu ý rằng bên dưới có định nghĩa FALIB. Điều này sẽ luôn được xác định khi trình biên dịch được sử dụng.

Mã IL của tôi được cho là sẽ triển khai một phiên bản cụ thể của điều này

#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));
	}

}

Nó chỉ cần điền vào SearchImpl và MatchImpl bằng các phương pháp cụ thể mà tôi đã thực hiện mặc dù hiện tại chúng chưa được triển khai.

Vấn đề tôi gặp phải là thế này – phương thức MatchImpl gọi vẫn ổn.

Phương pháp SearchImpl – thật kỳ lạ. Nó không những không được gọi mà còn không có bất kỳ phương thức nào ủy quyền cho nó. Tôi không gặp lỗi, trình biên dịch bị lỗi hoặc thời gian chạy. Nó chỉ âm thầm thất bại khi tôi cố gắng gọi nó.

Điều duy nhất tôi có thể nghĩ đến là kiểu trả về của tôi là một cấu trúc. Đó là sự khác biệt duy nhất ở đây mà tôi có thể thấy – đó và cái tên.

Những gì tôi đã thử:

C#
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);

	}
}

Tôi cũng đã thử thêm những dòng này để điều chỉnh ngăn xếp trong trường hợp tôi cần nó được lấp đầy ngay cả trong trường hợp bị ném:

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

Tôi nhận được kết quả tương tự.

Giải pháp 1

Tôi không hiểu tại sao, nhưng khi tôi lấy sản lượng ra khỏi lớp FARunner của mình và tự tay thực hiện điều tra viên của mình thì mọi thứ đều hoạt động tốt.

Tôi kết thúc việc này như đã được giải quyết mặc dù tôi rất bối rối.

コメント

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