Skip to content

Instantly share code, notes, and snippets.

@panesofglass
Created July 13, 2013 02:20
Show Gist options
  • Save panesofglass/5989138 to your computer and use it in GitHub Desktop.
Save panesofglass/5989138 to your computer and use it in GitHub Desktop.
// Learn more about F# at http://fsharp.net
// See the 'F# Tutorial' project for more help.
open System
open System.IO
open Microsoft.FSharp.Compiler.Interactive.Shell
type Result =
| Success of string
| Error of string
| Incomplete
type FSharpEngine() =
let stdin = new StreamReader(Stream.Null)
let stdoutStream = new CompilerOutputStream()
let stdout = StreamWriter.Synchronized(new StreamWriter(stdoutStream, AutoFlush=true))
let stderrStream = new CompilerOutputStream()
let stderr = StreamWriter.Synchronized(new StreamWriter(stderrStream, AutoFlush=true))
let getOutput (session: FsiEvaluationSession) code =
let tryget() =
let error = stderrStream.Read()
if error.Length > 0 then Error error else
Success(stdoutStream.Read())
try session.EvalInteraction(code)
if code.EndsWith ";;" then tryget()
else Incomplete
with ex -> Error ex.Message
let commonOptions = [| "fsi.exe"; "--nologo"; "--readline-" |]
let session = FsiEvaluationSession(commonOptions, stdin, stdout, stderr)
let combine (d1: #IDisposable) (d2: #IDisposable) =
{ new IDisposable with member x.Dispose() = d1.Dispose(); d2.Dispose() }
let (>>=) d1 d2 = combine d1 d2
member x.Execute(code) =
getOutput session code
member x.AddReference(ref) =
session.EvalInteraction(sprintf "#r @\"%s\"" ref)
member x.SilentAddReference(ref) =
x.AddReference ref
stdoutStream.Read() |> ignore
member x.ImportNamespace(``namespace``) =
session.EvalInteraction(sprintf "open %s" ``namespace``)
member x.SilentImportNamespace(``namespace``) =
x.ImportNamespace ``namespace``
stdoutStream.Read() |> ignore
member x.Dispose() =
(stdin >>= stdoutStream >>= stdout >>= stderrStream >>= stderr).Dispose()
interface IDisposable with
member x.Dispose() = x.Dispose()
[<EntryPoint>]
let main argv =
let put result =
match result with
| Success(result) -> printfn "> %s" result
| Error(result) -> printfn "Error %s" result
| Incomplete -> printfn "> "
let engine = new FSharpEngine()
engine.Execute("1+1") |> put
engine.Execute("""let name = "Ryan" """) |> put
engine.Execute("""printfn "Hello, %s" name""") |> put
Console.ReadLine() |> ignore
engine.Dispose()
0 // return an integer exit code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment