invoke fsi on memory (not file) - f#

Let's say we have a fsi script like this:
#r "System.Core.dll"
let script = "Console.WriteLine(\"Hello, World!\")"
// fsi script ???
We can use #load to invoke fsi on a file, but is it possible to somehow invoke fsi on an in-memory string without writing that to a file first?
The use-case is an API compatibility tester: given a dll, I would like to create a script that invocations all its public APIs and compile that script against a different version of the same dll.
I could always write the generated script to disk, but it would be much cleaner if I could run it directly.

The tasks of kind you outlined in your question may be performed with tools provided within Microsoft.FSharp.Compiler.Interactive namespace, in particular, with the help of type FsiEvaluationSession of Microsoft.FSharp.Compiler.Interactive.Shell.
This gist authored by Ryan Riley demoes exactly your scenario using a thin wrapper type FSharpEngine over FsiEvaluationSession, making programmatic use of fsi as convenient as:
....
let engine = new FSharpEngine()
engine.Execute("<some F# code>") |> processOutput
....
engine.Dispose()

Related

Load a file into F#'s FSI - without using #load

I want to load a file from a .fsx script into into the F# Interactive Session but I can't use #load since I only want to load it if a certain condition is true.
Is there a function like FSI.LoadFile or something instead of the compiler directive?
Looking at the source code (fsi.fs, line 1710 here
| IHash (ParsedHashDirective("load",sourceFiles,m),_) ->
fsiDynamicCompiler.EvalSourceFiles (istate, m, sourceFiles, lexResourceManager),Completed
Now, some of these parameters are probably easy to fake - in particular sourceFiles and m. I suspect that the other parameters are harder to fake.
I suspect that you are not trying to solve the problem in a good way. An alternative solution may be to do something like
let conditionally_load fname cond =
if cond then System.IO.File.Copy(fname,"dummy.fs")
else System.IO.File.Create("dummy.fs")
conditionally_load "something.fs" true
#load "dummy.fs"
Although you might need a ;; before the #load to ensure that the function runs before the #load
What you are looking to do is tricky, since you want the decision on whether to load additional code to be taken at evaluation time. A solution to this would be to modify the shell so that script loading can be scheduled at the next iteration of the REPL. In essence, your FSI.LoadFile function would simply add the path to a global queue, in the form of a ParsedHashDirective("load",["foo.fsx"], ...) expression.
The queue could then be prepended to the actions list next time the ExecInteractions method is called in line 1840. This should work fine, but clearly you won't be getting any intellisense support.

F# 'modular' scripting

What is the recommended way to load+reload fsx files? Just experimenting... yes yes right language right job ect ect..
I love how the following can be done in FSI:
#load "script.fsx";
open Script
> let p = script.x 1
Error: This expression was expected to have type string but here has int...
(* edit script.fsx x to make it int -> int *)
>
> #load "script.fsx"
> let p = script.x 1
val it : int = 2
But how do we do this for an application that we are running via fsi blah.fsx? Maybe something that is sitting in a while loop. It seems #load and #use must not be inside let or module.. i.e. you cannot use #load like let reload script = #load script, wonder why?
My original method was to have .fs files and recompile + relaunch each time I wanted to add/fix something. This method feels primitive.
Second method was to attempt to use the #load directive inside of a module, which turns out to not work (kind of makes sense in terms of scoping)...
module test1 =
#load #"C:\users\pc\Desktop\test.fsx"
open Test
module test2 =
...
Another way would be to create a new process for every module by loading fsi module.fsx with process diagnostics, but this seems horrible, inefficient and ugh.
I have a feeling deep in my heart that this will not be trivial inside .NET, but I would like to pose the question anyway, FSI does it... I wonder if I can leverage the FSI API or something (or at the least to copy their code)?
TL;DR I read the following about erlang and want it for myself in F#.
Erlang: Is there a way to reload changed modules into an already running node with rebar?
"...any time a module in your program changes on disk, the reloader will replace the running copy automatically."
I don't know if this would work in FS but in ML you can load a master file that loads all your files in your project and then executes any code that you need to use to knit them together and runs your application. To see an example of a massive app run from inside of a REPL look at the Isabelle/HOL site at the Cambridge laboratory of Computational Science http://www.cl.cam.ac.uk/research/hvg/Isabelle/installation.html. After downloading the app look in the src code directory for any file called root.ml. There will be half a dozen of them that control various levels of implementation. This is recursive because a top level file can call a file in several sub-directories that loads that particular sub-feature. This allows targeting your application to various scenarios depending on which top level file is executed.
Typical .NET Framework applications cannot unload/reload assemblies unless they are in an App Domains that are separate from the primary one that starts up with the application. This is essentially how most plugin systems are designed for applications that run on the full .NET Framework. Things may be changing post .NET Standard 2.0 in .NET Core with the Collectible Assemblies feature.
References:
https://github.com/dotnet/coreclr/issues/552
https://github.com/dotnet/corefx/issues/19773

How to compile F# library from another F# program

I want to make my Application configuration as F# file wich will be compiled to dll. (like XMonad configuration with xmonad.hs on haskell). I found it more interesting and just better way then using XML serialization.
So is there any way how can I compile single file (or more) to Library with some configuration like
module RNExcel.Repository
open RNExcel.Model
type ExpenseReportRepository() =
member x.GetAll() =
seq{ yield {Name="User1"
Role="someRole"
Password = "123321"
ExpenseLineItems =
[{ExpenseType="Item1"
ExpenseAmount="50"};
{ExpenseType="Item2"
ExpenseAmount="50"}]}
yield {Name="User2"
Role="Estimator"
Password = "123123"
ExpenseLineItems =
[{ExpenseType="Item1"
ExpenseAmount="50"};
{ExpenseType="Item2"
ExpenseAmount="125"}]} }
my idea was to run shell .... and msbuild the project , but I don't think it will works for every user with .net 4
Check out the F# Power Pack, specifically the FSharp.CodeDom library. You can use this library to compile F# code at run-time and, with a little Reflection thrown in, can likely achieve your goal of code-as-configuration with minimal fuss.
I think that using CodeDOM provider from the PowerPack as Ben suggested is a way to go. I'd just like to add a few things (and it didn't fit into the comment box).
To parse and compile the F# code with the configuration, you need just to compile the source file that the users write using F# PowerPack. The compilation part of PowerPack is complete and works just fine. It invokes the F# compiler under the cover and gives you the compiled assembly back. The only problem is that the users of your application will need to have F# compiler installed (and not just the redist).
The incomplete part of F# CodeDOM provider is generating F# code from CodeDOM trees (because the trees were not designed to support F#), but that's not needed in this case.

questions about fsi

how to change the working directory of fsi in VS.
how to auto load DLLs (e.g. the powerpack) at the startup of fsi.
how to auto open namespaces at the startup of fsi.
Thanks!
There is no direct way to specify this, but you can use the --use:file.fsx command line parameter, which allows you to specify an FSX file that will be loaded by F# interactive when it starts. You can specify the parameter in Tools -> Options -> F# Tools.
To do the three things you asked for, your file.fsx should look like this:
// 3. Open some namespace
open System
// 1. Change the current directory
Environment.CurrentDirectory <- "C:\\Temp"
// 2. Reference an assembly (e.g. PowerPack)
#r #"FSharp.PowerPack.dll"
See F# Interactive Options for a description of all of the available command line options. As detailed on that page, you can use the -r option to reference a particular DLL. There aren't built-in options for the other two questions you asked, but as Tomas mentioned, you can put them into a file which you #use.

statically analysing Lua code for potential errors

I'm using a closed-source application that loads Lua scripts and allows some customization through modifying these scripts. Unfortunately that application is not very good at generating useful log output (all I get is 'script failed') if something goes wrong in one of the Lua scripts.
I realize that dynamic languages are pretty much resistant to static code analysis in the way C++ code can be analyzed for example.
I was hoping though, there would be a tool that runs through a Lua script and e.g. warns about variables that have not been defined in the context of a particular script.
Essentially what I'm looking for is a tool that for a script:
local a
print b
would output:
warning: script.lua(1): local 'a' is not used'
warning: script.lua(2): 'b' may not be defined'
It can only really be warnings for most things but that would still be useful! Does such a tool exist? Or maybe a Lua IDE with a feature like that build in?
Thanks, Chris
Automated static code analysis for Lua is not an easy task in general. However, for a limited set of practical problems it is quite doable.
Quick googling for "lua lint" yields these two tools: lua-checker and Lua lint.
You may want to roll your own tool for your specific needs however.
Metalua is one of the most powerful tools for static Lua code analysis. For example, please see metalint, the tool for global variable usage analysis.
Please do not hesitate to post your question on Metalua mailing list. People there are usually very helpful.
There is also lua-inspect, which is based on metalua that was already mentioned. I've integrated it into ZeroBrane Studio IDE, which generates an output very similar to what you'd expect. See this SO answer for details: https://stackoverflow.com/a/11789348/1442917.
For checking globals, see this lua-l posting. Checking locals is harder.
You need to find a parser for lua (should be available as open source) and use it to parse the script into a proper AST tree. Use that tree and a simple variable visibility tracker to find out when a variable is or isn't defined.
Usually the scoping rules are simple:
start with the top AST node and an empty scope
item look at the child statements for that node. Every variable declaration should be added in the current scope.
if a new scope is starting (for example via a { operator) create a new variable scope inheriting the variables in the current scope).
when a scope is ending (for example via } ) remove the current child variable scope and return to the parent.
Iterate carefully.
This will provide you with what variables are visible where inside the AST. You can use this information and if you also inspect the expressions AST nodes (read/write of variables) you can find out your information.
I just started using luacheck and it is excellent!
The first release was from 2015.

Resources