From 608c5a3151a8c44ae7744c2913f11be11d3aaaad Mon Sep 17 00:00:00 2001 From: 7sharp9 Date: Sun, 23 Jun 2013 23:55:17 +0100 Subject: [PATCH 1/7] Initial commit for F# plugin for ScriptCs --- ScriptCs.sln | 6 + .../FSharpScriptEngine.fs | 134 ++++++++++++++++++ .../ScriptCs.Engine.FSharp.fsproj | 84 +++++++++++ src/ScriptCs.Engine.FSharp/packages.config | 5 + src/ScriptCs/Command/ExecuteReplCommand.cs | 4 +- src/ScriptCs/CompositionRoot.cs | 3 + src/ScriptCs/ScriptCs.csproj | 4 + src/ScriptCs/app.config | 4 + 8 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs create mode 100644 src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj create mode 100644 src/ScriptCs.Engine.FSharp/packages.config diff --git a/ScriptCs.sln b/ScriptCs.sln index 79d00af5..d3b31a96 100644 --- a/ScriptCs.sln +++ b/ScriptCs.sln @@ -33,6 +33,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptCs.Engine.Roslyn", "s EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptCs.Engine.Roslyn.Tests", "test\ScriptCs.Engine.Roslyn.Tests\ScriptCs.Engine.Roslyn.Tests.csproj", "{28D11DE5-9F98-4E0A-8CCC-9CDC19110451}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ScriptCs.Engine.FSharp", "src\ScriptCs.Engine.FSharp\ScriptCs.Engine.FSharp.fsproj", "{113CDD96-0824-491E-B332-62D4FDE02A1E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -67,6 +69,10 @@ Global {28D11DE5-9F98-4E0A-8CCC-9CDC19110451}.Debug|Any CPU.Build.0 = Debug|Any CPU {28D11DE5-9F98-4E0A-8CCC-9CDC19110451}.Release|Any CPU.ActiveCfg = Release|Any CPU {28D11DE5-9F98-4E0A-8CCC-9CDC19110451}.Release|Any CPU.Build.0 = Release|Any CPU + {113CDD96-0824-491E-B332-62D4FDE02A1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {113CDD96-0824-491E-B332-62D4FDE02A1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {113CDD96-0824-491E-B332-62D4FDE02A1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {113CDD96-0824-491E-B332-62D4FDE02A1E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs new file mode 100644 index 00000000..42030980 --- /dev/null +++ b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs @@ -0,0 +1,134 @@ +namespace ScriptCs.Engine.FSharp +open ScriptCs +open Common.Logging +open System +open System.IO +open System.Collections.Generic +open Microsoft.FSharp.Compiler.Interactive.Shell +open ExtCore +open System.Linq + +type Result = Success of String | Error of string | Incomplete + +type FSharpEngine(host:ScriptHost) = + let oin = Console.OpenStandardInput() + let oout = Console.OpenStandardOutput() + let oerr = Console.OpenStandardError() + + let stdinStream = new CompilerInputStream() + let stdin = new StreamReader(stdinStream) + + 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 (stream:CompilerInputStream) code = + + let rec tryget() = + async{ do! Async.Sleep(100) + + let error = stderrStream.Read() + if error.Length > 0 then return Error(error) else + + let result = stdoutStream.Read() + + if result |> String.isNullOrEmpty then return! tryget() + else return Success result } + + stream.Add(code + "\n") + if code.EndsWith ";;" then tryget() + else async.Return Incomplete + + let commonOptions = [| "fsi.exe"; "--nologo"; "--readline-";|] + let session = FsiEvaluationSession(commonOptions, stdin, stdout, stderr) + + // Start the session in the background + do Async.Start <| async {session.Run()} + do session.Interrupt() + do stdoutStream.Read() |> ignore + + let (>>=) (d1:#IDisposable) (d2:#IDisposable) = + {new IDisposable with member x.Dispose() = d1.Dispose(); d2.Dispose()} + + member x.Require<'a>() = host.Require() + + member x.Execute(code, ?timeout) = + let timeout = defaultArg timeout 10000 + Async.RunSynchronously((getOutput stdinStream code), timeout) + + member x.AddReference(ref) = + stdinStream.Add( sprintf "#r @\"%s\";;\n" ref) + + member x.SilentAddReference(ref) = + let rec wait() = + let res = stdoutStream.Read() + if res = String.empty || res = "\r\n" || res = "> " then + Async.Sleep(25) |> Async.RunSynchronously + wait() + else () + x.AddReference(ref) + wait() + + member x.ImportNamespace(namespace') = + stdinStream.Add(sprintf "open %s;;\n" namespace') + + member x.SilentImportNamespace(namespace') = + let rec wait() = + let res = stdoutStream.Read() + if res = String.empty then + Async.Sleep(25) |> Async.RunSynchronously + wait() + else () + x.ImportNamespace(namespace') + wait() + + interface IDisposable with + member x.Dispose() = () + //(stdinStream >>= stdin >>= stdoutStream >>= stdout >>= stderrStream >>= stderr).Dispose() + +type FSharpScriptEngine( scriptHostFactory:IScriptHostFactory, logger: ILog) = + let mutable baseDir = String.empty + let []sessionKey = "F# Session" + + interface IScriptEngine with + member x.BaseDirectory with get() = baseDir and set value = baseDir <- value + member x.Execute(code: String, scriptArgs, references, namespaces, scriptPackSession) = + let distinctReferences = references.Union(scriptPackSession.References).Distinct() + let sessionState = + match scriptPackSession.State.TryGetValue sessionKey with + | false, _ -> let host = scriptHostFactory.CreateScriptHost(ScriptPackManager(scriptPackSession.Contexts), scriptArgs) + logger.Debug("Creating session") + let session = new FSharpEngine(host) + + distinctReferences |> Seq.iter (fun r -> logger.DebugFormat("Adding reference to {0}", r) + session.SilentAddReference r ) + + namespaces.Union(scriptPackSession.Namespaces).Distinct() + |> Seq.iter (fun ns -> logger.DebugFormat("Importing namespace {0}", ns) + session.SilentImportNamespace ns) + + let sessionState = SessionState<_>(References = distinctReferences, Session = session) + scriptPackSession.State.Add(sessionKey, sessionState) + sessionState + | true, res -> logger.Debug("Reusing existing session") + let sessionState = res :?> SessionState + + let newReferences = match sessionState.References with + | null -> distinctReferences + | s when Seq.isEmpty s -> distinctReferences + | s -> distinctReferences.Except(s) + newReferences |> Seq.iter (fun r -> logger.DebugFormat("Adding reference to {0}", r) + sessionState.Session.AddReference r ) + sessionState + + match sessionState.Session.Execute(code) with + | Success result -> let cleaned = + let splits = result.Split([|"\r"; "\n";|], StringSplitOptions.RemoveEmptyEntries) + let filtered = splits |> Array.filter (fun str -> not(str = "> ")) + let final = filtered |> String.concat "\r\n" + final + ScriptResult(ReturnValue = cleaned) + | Error e -> ScriptResult(CompileException = exn e ) + | Incomplete -> ScriptResult() \ No newline at end of file diff --git a/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj b/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj new file mode 100644 index 00000000..95bd3fc4 --- /dev/null +++ b/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + 2.0 + 113CDD96-0824-491E-B332-62D4FDE02A1E + Library + ScriptCs.Engine.FSharp + ScriptCs.Engine.FSharp + v4.5 + ScriptCs.Engine.FSharp + ..\ + true + 10.0.0 + + + true + full + false + false + bin\Debug\ + DEBUG;TRACE + 3 + bin\Debug\ScriptCs.Engine.FSharp.XML + + + pdbonly + true + true + bin\Release\ + TRACE + 3 + bin\Release\ScriptCs.Engine.FSharp.XML + + + 11 + + + + + + + + + + ScriptCs.Contracts + {6049e205-8b5f-4080-b023-70600e51fd64} + True + + + ..\..\packages\Common.Logging.2.1.2\lib\net40\Common.Logging.dll + True + + + ..\..\packages\ExtCore.0.8.29\lib\net40\ExtCore.dll + True + + + ..\..\..\fsharp\lib\release\4.0\FSharp.Compiler.dll + + + ..\..\..\fsharp\lib\release\4.0\fsiAnyCpu.exe + + + + + + + + ScriptCs.Core + {e590e710-e159-48e6-a3e6-1a83d3fe732c} + True + + + + \ No newline at end of file diff --git a/src/ScriptCs.Engine.FSharp/packages.config b/src/ScriptCs.Engine.FSharp/packages.config new file mode 100644 index 00000000..af175f26 --- /dev/null +++ b/src/ScriptCs.Engine.FSharp/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/ScriptCs/Command/ExecuteReplCommand.cs b/src/ScriptCs/Command/ExecuteReplCommand.cs index 0c081711..d9e5cdb7 100644 --- a/src/ScriptCs/Command/ExecuteReplCommand.cs +++ b/src/ScriptCs/Command/ExecuteReplCommand.cs @@ -56,7 +56,7 @@ public CommandResult Execute() catch (Exception ex) { _logger.Error(ex.Message); - return CommandResult.Error; + return CommandResult.Error; } repl.Terminate(); return CommandResult.Success; @@ -108,4 +108,4 @@ private bool IsManagedAssembly(string path) return true; } } -} +} \ No newline at end of file diff --git a/src/ScriptCs/CompositionRoot.cs b/src/ScriptCs/CompositionRoot.cs index 0ed06d33..b49b49c6 100644 --- a/src/ScriptCs/CompositionRoot.cs +++ b/src/ScriptCs/CompositionRoot.cs @@ -8,6 +8,7 @@ using ScriptCs.Engine.Roslyn; using ScriptCs.Package; using ScriptCs.Package.InstallationProvider; +using ScriptCs.Engine.FSharp; namespace ScriptCs { @@ -58,11 +59,13 @@ public void Initialize() { builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); } else { builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); } builder.RegisterType().As(); diff --git a/src/ScriptCs/ScriptCs.csproj b/src/ScriptCs/ScriptCs.csproj index 5fc6d0e2..12136e5a 100644 --- a/src/ScriptCs/ScriptCs.csproj +++ b/src/ScriptCs/ScriptCs.csproj @@ -99,6 +99,10 @@ {e590e710-e159-48e6-a3e6-1a83d3fe732c} ScriptCs.Core + + {113cdd96-0824-491e-b332-62d4fde02a1e} + ScriptCs.Engine.FSharp + {e79ec231-e27d-4057-91c9-2d001a3a8c3b} ScriptCs.Engine.Roslyn diff --git a/src/ScriptCs/app.config b/src/ScriptCs/app.config index cb1b9770..6edf0e06 100644 --- a/src/ScriptCs/app.config +++ b/src/ScriptCs/app.config @@ -9,6 +9,10 @@ + + + + \ No newline at end of file From a7b7104bceff53ed114b0b0f4b4a811323687742 Mon Sep 17 00:00:00 2001 From: 7sharp9 Date: Mon, 24 Jun 2013 00:11:52 +0100 Subject: [PATCH 2/7] Added disposal, removed else blocks --- src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs index 42030980..e74ad059 100644 --- a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs +++ b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs @@ -67,7 +67,6 @@ type FSharpEngine(host:ScriptHost) = if res = String.empty || res = "\r\n" || res = "> " then Async.Sleep(25) |> Async.RunSynchronously wait() - else () x.AddReference(ref) wait() @@ -80,13 +79,12 @@ type FSharpEngine(host:ScriptHost) = if res = String.empty then Async.Sleep(25) |> Async.RunSynchronously wait() - else () x.ImportNamespace(namespace') wait() interface IDisposable with - member x.Dispose() = () - //(stdinStream >>= stdin >>= stdoutStream >>= stdout >>= stderrStream >>= stderr).Dispose() + member x.Dispose() = + (stdinStream >>= stdin >>= stdoutStream >>= stdout >>= stderrStream >>= stderr).Dispose() type FSharpScriptEngine( scriptHostFactory:IScriptHostFactory, logger: ILog) = let mutable baseDir = String.empty From 026338f642577729bfec10cb9d9863fc8477f236 Mon Sep 17 00:00:00 2001 From: 7sharp9 Date: Mon, 24 Jun 2013 00:14:42 +0100 Subject: [PATCH 3/7] Removed old pipeline debug --- src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs index e74ad059..eaf285b8 100644 --- a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs +++ b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs @@ -116,17 +116,16 @@ type FSharpScriptEngine( scriptHostFactory:IScriptHostFactory, logger: ILog) = let newReferences = match sessionState.References with | null -> distinctReferences | s when Seq.isEmpty s -> distinctReferences - | s -> distinctReferences.Except(s) + | s -> distinctReferences.Except s newReferences |> Seq.iter (fun r -> logger.DebugFormat("Adding reference to {0}", r) sessionState.Session.AddReference r ) sessionState match sessionState.Session.Execute(code) with | Success result -> let cleaned = - let splits = result.Split([|"\r"; "\n";|], StringSplitOptions.RemoveEmptyEntries) - let filtered = splits |> Array.filter (fun str -> not(str = "> ")) - let final = filtered |> String.concat "\r\n" - final + result.Split([|"\r"; "\n";|], StringSplitOptions.RemoveEmptyEntries) + |> Array.filter (fun str -> not(str = "> ")) + |> String.concat "\r\n" ScriptResult(ReturnValue = cleaned) | Error e -> ScriptResult(CompileException = exn e ) | Incomplete -> ScriptResult() \ No newline at end of file From 82942bb523815bf2357b4ed146ef0b8035266b50 Mon Sep 17 00:00:00 2001 From: 7sharp9 Date: Mon, 24 Jun 2013 10:30:39 +0100 Subject: [PATCH 4/7] Added partial message based interaction, output is still stream based. --- .../FSharpScriptEngine.fs | 181 ++++++++---------- .../ScriptCs.Engine.FSharp.fsproj | 4 +- 2 files changed, 81 insertions(+), 104 deletions(-) diff --git a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs index eaf285b8..e861657f 100644 --- a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs +++ b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs @@ -11,121 +11,98 @@ open System.Linq type Result = Success of String | Error of string | Incomplete type FSharpEngine(host:ScriptHost) = - let oin = Console.OpenStandardInput() - let oout = Console.OpenStandardOutput() - let oerr = Console.OpenStandardError() - - let stdinStream = new CompilerInputStream() - let stdin = new StreamReader(stdinStream) + let stdin = new StreamReader(System.IO.Stream.Null) - let stdoutStream = new CompilerOutputStream() - let stdout = StreamWriter.Synchronized(new StreamWriter(stdoutStream, AutoFlush=true)) + 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 (stream:CompilerInputStream) code = + let stderrStream = new CompilerOutputStream() + let stderr = StreamWriter.Synchronized(new StreamWriter(stderrStream, AutoFlush=true)) + + let getOutput (session: FsiEvaluationSession) code = - let rec tryget() = - async{ do! Async.Sleep(100) + let tryget() = + let error = stderrStream.Read() + if error.Length > 0 then Error(error) else - let error = stderrStream.Read() - if error.Length > 0 then return Error(error) else + Success(stdoutStream.Read()) - let result = stdoutStream.Read() - - if result |> String.isNullOrEmpty then return! tryget() - else return Success result } + session.EvalInteraction(code) + if code.EndsWith ";;" then tryget() + else Incomplete + + let commonOptions = [| "fsi.exe"; "--nologo"; "--readline-";|] + let session = FsiEvaluationSession(commonOptions, stdin, stdout, stderr) - stream.Add(code + "\n") - if code.EndsWith ";;" then tryget() - else async.Return Incomplete - - let commonOptions = [| "fsi.exe"; "--nologo"; "--readline-";|] - let session = FsiEvaluationSession(commonOptions, stdin, stdout, stderr) + // Start the session in the background + //do Async.Start <| async {session.Run()} + //do session.Interrupt() + //do stdoutStream.Read() |> ignore - // Start the session in the background - do Async.Start <| async {session.Run()} - do session.Interrupt() - do stdoutStream.Read() |> ignore + let (>>=) (d1:#IDisposable) (d2:#IDisposable) = + {new IDisposable with member x.Dispose() = d1.Dispose(); d2.Dispose()} - let (>>=) (d1:#IDisposable) (d2:#IDisposable) = - {new IDisposable with member x.Dispose() = d1.Dispose(); d2.Dispose()} + member x.Execute(code) = + getOutput session code - member x.Require<'a>() = host.Require() + member x.AddReference(ref) = + session.EvalInteraction(sprintf "#r @\"%s\"" ref) - member x.Execute(code, ?timeout) = - let timeout = defaultArg timeout 10000 - Async.RunSynchronously((getOutput stdinStream code), timeout) + member x.SilentAddReference(ref) = + x.AddReference(ref) + stdoutStream.Read() |> ignore - member x.AddReference(ref) = - stdinStream.Add( sprintf "#r @\"%s\";;\n" ref) + member x.ImportNamespace(namespace') = + session.EvalInteraction(sprintf "open %s" namespace') - member x.SilentAddReference(ref) = - let rec wait() = - let res = stdoutStream.Read() - if res = String.empty || res = "\r\n" || res = "> " then - Async.Sleep(25) |> Async.RunSynchronously - wait() - x.AddReference(ref) - wait() + member x.SilentImportNamespace(namespace') = + x.ImportNamespace(namespace') + stdoutStream.Read() |> ignore - member x.ImportNamespace(namespace') = - stdinStream.Add(sprintf "open %s;;\n" namespace') - - member x.SilentImportNamespace(namespace') = - let rec wait() = - let res = stdoutStream.Read() - if res = String.empty then - Async.Sleep(25) |> Async.RunSynchronously - wait() - x.ImportNamespace(namespace') - wait() - - interface IDisposable with - member x.Dispose() = - (stdinStream >>= stdin >>= stdoutStream >>= stdout >>= stderrStream >>= stderr).Dispose() + interface IDisposable with + member x.Dispose() = + (stdin >>= stdoutStream >>= stdout >>= stderrStream >>= stderr).Dispose() type FSharpScriptEngine( scriptHostFactory:IScriptHostFactory, logger: ILog) = - let mutable baseDir = String.empty - let []sessionKey = "F# Session" + let mutable baseDir = String.empty + let []sessionKey = "F# Session" - interface IScriptEngine with - member x.BaseDirectory with get() = baseDir and set value = baseDir <- value - member x.Execute(code: String, scriptArgs, references, namespaces, scriptPackSession) = - let distinctReferences = references.Union(scriptPackSession.References).Distinct() - let sessionState = - match scriptPackSession.State.TryGetValue sessionKey with - | false, _ -> let host = scriptHostFactory.CreateScriptHost(ScriptPackManager(scriptPackSession.Contexts), scriptArgs) - logger.Debug("Creating session") - let session = new FSharpEngine(host) - - distinctReferences |> Seq.iter (fun r -> logger.DebugFormat("Adding reference to {0}", r) - session.SilentAddReference r ) - - namespaces.Union(scriptPackSession.Namespaces).Distinct() - |> Seq.iter (fun ns -> logger.DebugFormat("Importing namespace {0}", ns) - session.SilentImportNamespace ns) - - let sessionState = SessionState<_>(References = distinctReferences, Session = session) - scriptPackSession.State.Add(sessionKey, sessionState) - sessionState - | true, res -> logger.Debug("Reusing existing session") - let sessionState = res :?> SessionState - - let newReferences = match sessionState.References with - | null -> distinctReferences - | s when Seq.isEmpty s -> distinctReferences - | s -> distinctReferences.Except s - newReferences |> Seq.iter (fun r -> logger.DebugFormat("Adding reference to {0}", r) - sessionState.Session.AddReference r ) - sessionState - - match sessionState.Session.Execute(code) with - | Success result -> let cleaned = - result.Split([|"\r"; "\n";|], StringSplitOptions.RemoveEmptyEntries) - |> Array.filter (fun str -> not(str = "> ")) - |> String.concat "\r\n" - ScriptResult(ReturnValue = cleaned) - | Error e -> ScriptResult(CompileException = exn e ) - | Incomplete -> ScriptResult() \ No newline at end of file + interface IScriptEngine with + member x.BaseDirectory with get() = baseDir and set value = baseDir <- value + member x.Execute(code, args, references, namespaces, scriptPackSession) = + let distinctReferences = references.Union(scriptPackSession.References).Distinct() + let sessionState = + match scriptPackSession.State.TryGetValue sessionKey with + | false, _ -> let host = scriptHostFactory.CreateScriptHost(ScriptPackManager(scriptPackSession.Contexts), args) + logger.Debug("Creating session") + let session = new FSharpEngine(host) + + distinctReferences |> Seq.iter (fun ref -> logger.DebugFormat("Adding reference to {0}", ref) + session.SilentAddReference ref ) + + namespaces.Union(scriptPackSession.Namespaces).Distinct() + |> Seq.iter (fun ns -> logger.DebugFormat("Importing namespace {0}", ns) + session.SilentImportNamespace ns) + + let sessionState = SessionState<_>(References = distinctReferences, Session = session) + scriptPackSession.State.Add(sessionKey, sessionState) + sessionState + | true, res -> logger.Debug("Reusing existing session") + let sessionState = res :?> SessionState + + let newReferences = match sessionState.References with + | null -> distinctReferences + | refs when Seq.isEmpty refs -> distinctReferences + | refs -> distinctReferences.Except refs + newReferences |> Seq.iter (fun ref -> logger.DebugFormat("Adding reference to {0}", ref) + sessionState.Session.AddReference ref ) + sessionState + + match sessionState.Session.Execute(code) with + | Success result -> let cleaned = + result.Split([|"\r"; "\n";|], StringSplitOptions.RemoveEmptyEntries) + |> Array.filter (fun str -> not(str = "> ")) + |> String.concat "\r\n" + ScriptResult(ReturnValue = cleaned) + | Error e -> ScriptResult(CompileException = exn e ) + | Incomplete -> ScriptResult() \ No newline at end of file diff --git a/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj b/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj index 95bd3fc4..71d66b85 100644 --- a/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj +++ b/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj @@ -58,10 +58,10 @@ True - ..\..\..\fsharp\lib\release\4.0\FSharp.Compiler.dll + Z:\dave\code\fs-ev\lib\release\4.0\FSharp.Compiler.dll - ..\..\..\fsharp\lib\release\4.0\fsiAnyCpu.exe + Z:\dave\code\fs-ev\lib\release\4.0\fsiAnyCpu.exe From 393feede0dbbfb01f767b854692190c3bf21004e Mon Sep 17 00:00:00 2001 From: 7sharp9 Date: Mon, 24 Jun 2013 10:37:09 +0100 Subject: [PATCH 5/7] Added exception wrapping around EvalInteractive --- src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs index e861657f..06ad9092 100644 --- a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs +++ b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs @@ -24,12 +24,13 @@ type FSharpEngine(host:ScriptHost) = let tryget() = let error = stderrStream.Read() if error.Length > 0 then Error(error) else - Success(stdoutStream.Read()) - session.EvalInteraction(code) - if code.EndsWith ";;" then tryget() - else Incomplete + 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) From 2b341be0ad069b98e4d89545f1b16761bc11caec Mon Sep 17 00:00:00 2001 From: 7sharp9 Date: Mon, 24 Jun 2013 10:37:50 +0100 Subject: [PATCH 6/7] Removed commented code --- src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs index 06ad9092..80b873f7 100644 --- a/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs +++ b/src/ScriptCs.Engine.FSharp/FSharpScriptEngine.fs @@ -35,11 +35,6 @@ type FSharpEngine(host:ScriptHost) = let commonOptions = [| "fsi.exe"; "--nologo"; "--readline-";|] let session = FsiEvaluationSession(commonOptions, stdin, stdout, stderr) - // Start the session in the background - //do Async.Start <| async {session.Run()} - //do session.Interrupt() - //do stdoutStream.Read() |> ignore - let (>>=) (d1:#IDisposable) (d2:#IDisposable) = {new IDisposable with member x.Dispose() = d1.Dispose(); d2.Dispose()} From d7783b76e400cfdffbd8a797f80e1e3e0e1064b8 Mon Sep 17 00:00:00 2001 From: 7sharp9 Date: Mon, 24 Jun 2013 12:40:13 +0100 Subject: [PATCH 7/7] Added FsiEval as a nuget package --- src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj | 8 ++++---- src/ScriptCs.Engine.FSharp/packages.config | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj b/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj index 71d66b85..428f122b 100644 --- a/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj +++ b/src/ScriptCs.Engine.FSharp/ScriptCs.Engine.FSharp.fsproj @@ -57,11 +57,11 @@ ..\..\packages\ExtCore.0.8.29\lib\net40\ExtCore.dll True - - Z:\dave\code\fs-ev\lib\release\4.0\FSharp.Compiler.dll + + True - - Z:\dave\code\fs-ev\lib\release\4.0\fsiAnyCpu.exe + + True diff --git a/src/ScriptCs.Engine.FSharp/packages.config b/src/ScriptCs.Engine.FSharp/packages.config index af175f26..f0bd15c2 100644 --- a/src/ScriptCs.Engine.FSharp/packages.config +++ b/src/ScriptCs.Engine.FSharp/packages.config @@ -2,4 +2,5 @@ + \ No newline at end of file