Skip to content

tbshillcdr/fsc-host

 
 

Repository files navigation

fsc-host Build Status NuGet Badge Coverage

Host the F# compiler in your own apps.

You can easily extend your applications by calling functions and retrieving values on runtime from dynamically compiled scripts.

What is supported

  • Accessing script members on the host side in a strongly-typed way (please note: if the members are not of expected types they will fail casting causing a runtime exception - there is no magic that could fix it)
  • Consuming values and functions (including generics)
  • Referencing NuGet packages and other scripts via the usual #r directive
  • Controlling compilation options
  • Basic assembly caching (opt-in via options - so far invalidation is only supported for the root script file)
  • Basic logging (by passing a logging func via options)

What is planned

  • Invalidate cache on any change in the whole script dependency tree. It only works for the root file at the moment.
  • A new API allowing scripts to become a dynamic implementation for an interface/module (to avoid referencing scripts members by strings)
  • Design a logo 😃

Requirements

  • .NET SDK 6 (it is convenient to package apps using fsc-host as Docker images)

Warning

This project is still in v0 which means the public API hasn't stabilised yet and breaking changes may happen between minor versions. Breaking changes are indicated in the release notes in GitHub releases.

Example

  1. Create a console app and add the package
dotnet new console -lang F# --name fsc-host-test && cd fsc-host-test && dotnet add package Queil.FSharp.FscHost --version 0.14.0
  1. Save the below as script.fsx:
let helloFromScript name = sprintf "HELLO FROM THE SCRIPT, %s" name

let myPrimes = [2; 3; 5]
  1. In your Program.cs:
open Queil.FSharp.FscHost

try

  // compile a script and retrieve two properties out of it
  let getScriptProperties () =
    File "script.fsx"
    |> CompilerHost.getMember2 Options.Default
         (Member<string -> string>.Path "Script.helloFromScript")
         (Member<int list>.Path "Script.myPrimes")

  let (helloWorld, primesOfTheDay) = getScriptProperties () |> Async.RunSynchronously

  let myName = "Console Example"

  myName |> helloWorld |> printfn "%s"

  printfn "Primes of the day: "
  primesOfTheDay |> Seq.iter (printfn "%i")

with
// you can handle more exceptions from the CompilerHost here
| ScriptMemberNotFound(name, foundMembers) ->
  printfn "Couldn't find member: '%s'" name
  printfn "Found members: "
  foundMembers |> Seq.iter(printfn "%s")
  1. You should get the following output when dotnet run:
HELLO FROM THE SCRIPT, Console Example
Primes of the day: 
2
3
5

APIs

The public API of this library comes in two flavours:

  • basic - the CompilerHost.getMember functions family. They take a script and options as the input and return a tuple of extracted member(s). Example

  • compile'n'extract - CompilerHost.getAssembly can be used to compile a script into an assembly (which is automatically loaded). Then members can be extracted with Member.get function. This API gives more flexibility and enables using generic functions. Example

Resources

About

Host the F# compiler in your own apps

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • F# 100.0%