8

最初に、CLR / .NET言語をデバッグ可能にするを読みましたが、それでもこれを実装するのに問題があります。

Linq式を生成し、LambdaExpression#CompileToMethodを呼び出すことで機能するおもちゃの言語を作成しました。これらの式のほとんどには、次のようにデバッグ情報が添付されています。

//SmithExpression#InsertDebugInfo
Expression InsertDebugInfo(Expression expression, DebugInfo debugInfo) {
    var column = 1;
    var debugExpr = Expression.DebugInfo(debugInfo.SymbolDocumentInfo
                 ,Info.LineNumber, column, Info.LineNumber, column + 1);
    return Expression.Block(debugExpr, expression);
}

DebugInfoは次のようになります。

public class DebugInfo {
    /* arbitrary value from http://www.famkruithof.net/uuid/uuidgen */
    public static Guid SmithGuid = new Guid("83c65910-8376-11e2-9e96-0800200c9a66");

    public readonly SymbolDocumentInfo SymbolDocumentInfo;
    public readonly DebugInfoGenerator DebugPdbGenerator;

    public DebugInfo(String name) {
        SymbolDocumentInfo = Expression.SymbolDocument(name, SmithGuid);
        DebugPdbGenerator = DebugInfoGenerator.CreatePdbGenerator();
    }
}

全体がそのように構成されています(initに関する部分は無視できます):

public static Action CompileSmithExpression(SmithExpression sexpression
           ,DebugInfo debugInfo, Parameter moduleParameter, Expando module) {
    AssemblyName assemblyName = 
        new AssemblyName(
             "RuntimeHelpers.CompileToSmithExpression helper assembly"
          );
    AssemblyBuilder assemblyBuilder =
        AppDomain.CurrentDomain.DefineDynamicAssembly(
          assemblyName, AssemblyBuilderAccess.RunAndSave
        );

    ModuleBuilder moduleBuilder = assemblyBuilder
             .DefineDynamicModule(assemblyName.Name, "onlyModule.dll");

    var debugAttributes =
        DebuggableAttribute.DebuggingModes.Default |
        DebuggableAttribute.DebuggingModes.DisableOptimizations;

    ConstructorInfo constructor =
        typeof(DebuggableAttribute)
       .GetConstructor(new Type[] { 
           typeof(DebuggableAttribute.DebuggingModes)
           }
        );
    var cab = new CustomAttributeBuilder(constructor, new object[] { debugAttributes });
    assemblyBuilder.SetCustomAttribute(cab);
    moduleBuilder.SetCustomAttribute(cab);

    TypeBuilder typeBuilder = 
       moduleBuilder.DefineType("MyDynamicType", TypeAttributes.Public);

    //inits generates expressions that set 'constant' fields to their values.
    //the call also adds the 'constant' fields to the typeBuilder.
    //Must call ToArray() to make it run.
    var inits = FieldInits(sexpression, typeBuilder).ToArray();
    var ex = sexpression.ToExpression(debugInfo);
    var fullDlrExpression = Expression.Block(inits.Append(ex));

    var parameters = new ParameterExpression[] { moduleParameter.DlrParameter };
    var lambda = Expression.Lambda(fullDlrExpression, parameters);

    /* Method will take the module as a parameter. */
    MethodBuilder meth = typeBuilder.DefineMethod(
        "MyMethod",
        MethodAttributes.Public | MethodAttributes.Static,
        typeof(void),
        new Type[] { typeof(Expando) } );

    lambda.CompileToMethod(meth, debugInfo.DebugPdbGenerator);

    Type madeType = typeBuilder.CreateType();

    return () => madeType.GetMethod("MyMethod").Invoke(null, new Object[] { module });
}

コードを実行すると、必要な例外が発生しますが、式に含まれているデバッグ情報は含まれていません。「<error_immediate、1>」のように言いたいのですが。

Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.MissingMemberException: Can't invoke member error of [] []
at (wrapper dynamic-method) object.CallSite.Target (System.Runtime.CompilerServices.Closure,System.Runtime.CompilerServices.CallSite,Smith.Expando) <IL 0x0004f, 0x00127>
at System.Dynamic.UpdateDelegates.UpdateAndExecute1<Smith.Expando, object> (System.Runtime.CompilerServices.CallSite,Smith.Expando) <0x0040b>
at MyDynamicType.MyMethod (Smith.Expando) <IL 0x002bc, 0x00aaa>
at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) <IL 0x00016, 0x00067>
etc...

私の最善の推測は、デバッグ情報が実際にそこにあるということですが、スタックトレースにそれを表示させるには、さらに多くの作業を行う必要があります。何か案は?

4

1 に答える 1