F# Metaprogramming part 2: Dynamic synthesis of executable F# code
No, this is not an April 1 Fool’s day joke. Someone asked for this on Stack Overflow few days ago. As this is a good complementary to my JITting foray, I spent some time today on this exciting matter and was able to come up with reasonably succinct working sample. I simply repost here my own SO answer.
The desired can be achieved using F# CodeDom provider. A minimal runnable snippet below demonstrates the required steps. It takes an arbitrary presumably correct F# code from a string and tries to compile it into an assembly file. If successful, then it loads this just synthesized assembly from the correspondent dll file and invokes a known function from there, otherwise it shows what’s the problem with compiling the code.
open System open System.CodeDom.Compiler open Microsoft.FSharp.Compiler.CodeDom // Our (very simple) code string consisting of just one function: unit -> string let codeString = "module Synthetic.Code\n let syntheticFunction() = \"I've been compiled on the fly!\"" // Assembly path to keep compiled code let synthAssemblyPath = "synthetic.dll" let CompileFSharpCode(codeString, synthAssemblyPath) = use provider = new FSharpCodeProvider() let options = CompilerParameters([||], synthAssemblyPath) let result = provider.CompileAssemblyFromSource( options, [|codeString|] ) // If we missed anything, let compiler show us what's the problem if result.Errors.Count <> 0 then for i = 0 to result.Errors.Count - 1 do printfn "%A" (result.Errors.Item(i).ErrorText) result.Errors.Count = 0 if CompileFSharpCode(codeString, synthAssemblyPath) then let synthAssembly = Reflection.Assembly.LoadFrom(synthAssemblyPath) let synthMethod = synthAssembly.GetType("Synthetic.Code").GetMethod("syntheticFunction") printfn "Success: %A" (synthMethod.Invoke(null, null)) else failwith "Compilation failed"
If anyone wants to play with this toy, two references will be needed: to FSharp.Compiler.dll and to FSharp.Compiler.CodeDom.dll. Enjoy!
Trackbacks & Pingbacks