[Mono-dev] F# Interactive on Mono 2.8 (DefineDynamicAssembly troubles)

Tomas Petricek tomas.petricek at gmail.com
Mon Oct 11 08:58:12 EDT 2010


Hi,
I was trying to run the F# Interactive on Mono 2.8 (on both Mac and
Windows) and I'm having some issues. F# Interactive is essentially a
REPL tool that allows you to enter some F# code and compiles it on the
fly using System.Reflection (in case someone wanted to reproduce that,
there is a download on Microsoft web site [1] and now also packages
for various Linux distributions and Mac [2].

I tried entering a simple F# snippet that declares a type (this
creates a class under the cover using Reflection.Emit and then uses
Reflection again to find some information about the created class and
prints it). On Mono 2.6.7, this behaves as expected:

> type Foo = | Bar of int;;
type Foo = | Bar of int

The first line is my input which defines a discriminated union type
and the second line shows information about the type printed later by
F# Interactive. When I try the same thing on Mono 2.8, I get an
exception:

> type Foo = | Bar of int;;
error FS0193: Operation is not supported.

I looked into the F# source code (which is available with the oficial
release [1] and can be actually compiled, but has currently an
annoying license limiations) and I find out that this is caused by a
"NotSupportedException" thrown from "GetConstructorImpl" in
"System.Reflection.MonoGenericClass". Apparently, this exception is
thrown when "IsCompilerContext" is false (but looking at Mono sources,
I'm not quite sure what this property means). I was trying to
understand how can this become "true" and I noticed that there is a
check for some special flag in the constructor of "AssemblyBuilder":

    internal AssemblyBuilder (AssemblyName n, string directory,
AssemblyBuilderAccess access, bool corlib_internal) {
        is_compiler_context = (access & COMPILER_ACCESS) != 0;
        // ...
    }

I couldn't find any documentation on this flag anywhere, so I'm a bit
confused. However, I tried modifying the public F# sources to pass the
flag when creating a dynamic assembly (the value COMPILER_ACCESS is a
private constant with value 0x800). It feels like a horrible hack,
because I just need to pass some "magical constant" converted to an
enum value, but it does the trick and F# Interactive works just fine
after the change... The C# translation of the change I did would look
like this:

    // The original code (throws NotSupportedException in GetConstrucorImpl)
    var dyn = domain.DefineDynamicAssembly(asmName,
AssemblyBuilderAccess.RunAndSave, ".")

    // Pass the magic flag to the assembly builder (works fine!)
    var dyn = domain.DefineDynamicAssembly(asmName,
AssemblyBuilderAccess.RunAndSave | (AssemblyBuilderAccess)0x800, ".")

Is this some kind of special flag that the F# compiler should pass to
the "DefineDynamicAssembly" or is there another way to fix the issue
(without passing magical constants as arguments)? Should I send this
information to the F# team, so that they can make the next release of
F# working on Mono 2.8, or is this something that can be changed in
the next Mono release?

Thanks!
Tomas Petricek

[1] http://www.microsoft.com/downloads/en/details.aspx?FamilyID=f8c623ae-aef6-4a06-a185-05f59be47d67&displaylang=en
[2] http://fsxplat.codeplex.com/releases/view/51797


More information about the Mono-devel-list mailing list