views:

344

answers:

1

I'm building a spreadsheet-like application, where a lot of small calculations needs to be stitched together in a tree-structure. These calculations are user-defined and I need a way for the user to enter them at runtime.

My current approach is to write a small "expression DSL" in F#, where I parse the input with FParsec, build a syntax tree based on a discriminated union and then can evaluate the expression. This works pretty well.

However, I'm thinking of looking in to basing the language on the DLR instead. Are there any upsides to go down this road (parse the input, generate the AST using the Scripting.AST stuff instead of my own, and let the DLR handle the execution of the calculation)?

Each calculation will probably be pretty small. The dependency between the calculations will be taken care of on a higher level.

Can I expect better performance since the DLR will generate CIL code for the expression or will the overhead eat that up?

(as for using an existing language like IronPython, it will probably be hard since I'm planning to add a lot of slice-and-dice operators and dimensionality-handling stuff to the language syntax)

+5  A: 

It's difficult to answer a question in such broad terms, but here are some of my thoughts.

Using F# to build the parser sounds good.

FSParsec is a great library. I'm kinda partial towards FSLex and FSYacc. Either way, in F# there are libraries specifically designed for parsing which save you time.

Generating code with the DLR sounds OK.

The DLR is a great platform for dynamic code generation. However, your application is much more specific. If you are limiting yourself to just computing values you should use the Expression Trees APIs from .NET 3.5. This API is designed for representing arbitrary code expressions. The DLR on the other hand is designed as a runtime or dynamic languages. I'm not saying it's impossible, just that it isn't the right tool for the job.

Don't compile your generated code.

If you do go with the DLR to represent your AST, the cost of compiling and executing will likely be far greater than simply interpreting the tree. Do compile the code if: A.) you are executing the same function / method many times or B.) the function / method is very complicated.

C# + DLR, IronPython, F#, or some combination of the three are all sound choices. Ultimately the 'correct' choice is the one that gets the job done in as quick of a time as possible.

Chris Smith
Thank you for your insights. I completely overlooked the linq expression trees. I will try to modify my parser to generate trees using this API and do some performance tests on their evaluation to compare with the naive interpretation/evaluation I'm doing now in F#.
Rickard
Note that you can use F# Quotations and in the FSharp.PowerPack.Linq library you can convert the F# Quotation expression into a LINQ Expression Tree. There isn't a ton of documentation on this, however but you might be interested.
Chris Smith