While researching for post - speak-language-of-domain i spent some time building external DSL and experimented with parser and compiler.
Parser & compiler are important components for external DSL because it converts external DSL to executable.
We will take a few examples of external DSL and look at what is required to build a full solution.
Rule Engine
external DSL pipeline |
Loading a DSL file is a trivial thing , it can be uploaded to the system using a web interface.
Once a file is uploaded then it needs to be parsed, this is where things become little interesting and many built in libraries are available to parse files and extract tokens but in this example we will do simple parsing and code generation.
For parsing template files that will be used, content of the DSL file is put in template file before compilation.
For this example I am going to use the template file.
Above template file has 2 variables $REPLACE & //CODE, these two variables are replaced during the parsing and code generation phase.
$REPLACE - will contain some random value to give a unique name to the block of code that needs to be compiled.
//CODE - will contain DSL code submitted by the user.
Once tokens are replaced we are ready for compilation.
For compilation we will use JavaCompiler API, this api gives a programmatic interface to JVM compiler. Very powerful API for doing something in running VM.
Code snippet for compiling code using JavaCompiler interface.
Once code is compiled then using the java reflection rule can be loaded.
Code snippet for DSLLoader
Once the rule is loaded from DSL then it is straightforward to update the current VM to use the newly created rule.
DSL code is type safe, all the checks are done at compile time and it is highly optimized code because it has no reflection or other magic, so it will benefit from all the hotspot compiler.
For DSL creator perspective these rules can be tested in sandbox before using it production.
Few things that can be improved are error messages when DSL has compilation error, right now it is just showing java error messages and it will not be that user friendly for non java programmers.
Trading System
newOrder(equity("IBM"), (order, ts) -> {
order
.buy(100)
.at(126.07d);
ts.execute(order);
});
newOrder(equity("GOOG"), (order, ts) -> {
order
.sell(100)
.at(1506.85)
.partial();
ts.execute(order);
});
buy 100 IBM stocks at 122.06