Over the last few months I had the opportunity to implement a DSL for my day job. Well, my day job doesn’t involve writing compilers, but it does involve writing incredibly tedious C code to interface an archaic 4GL – OpenROAD – to a whole bunch of second & third tier code written in C in the form of Tuxedo Servers. So, I thought to myself, why spend weeks writing this junk, when I can spend weeks writing a compiler to write that junk for me?
So, off I went, and implemented…. SMeL! – the “Service Meta Language”. Ok, so the acronym sucks, but the other really rude ones wouldn’t have flown well in corporate-ville. Anyway, I ended up spending many nights implementing this, as I couldn’t justify doing this during the day, but the end result was worth it , I think. It allows me to spend days writing services, instead of months, leaving me to browse YouTube at my leisure 😉
Anyway, our project now has a full featured DSL that allows us to import the 4GL classes straight from OpenROAD, define their members directionality, and map the member to columns on the database.
Marking class member directionality allows SMeL’s codegen to create Tuxedo services that know whether the data will be coming or going.
Mapping the data to the columns allows the SMeL compiler to check the data types and sizes against their respective columns , and warn of any inconsistencies, showing up possible bugs where the data would mismatch, before it generates any SQL.
Because we have descriptions of both the class data, and the tables they’re applied to , SMeL also functions as an ORM tool, and includes code generation for Pro*C to read/write multiple records, do joins based solely on the SMeL class definitions, and lots of other time ( and error) savers, like event based error handling and partial table mappings. Something as simple as generating the error handling means that any statement that could cause error is automatically checked, and returned. No more will a Tuxedo service go off half cocked because someone forgot to intercept an error and return!
The SMeL compiler is implemented entirely in Java, and uses Antlr & Stringtemplate heavily. Although I’d consider myself a .NET aficionado, I didn’t find Java all that different, especially when using a decent IDE like IntelliJ, and at the time I started the project, Antlr didn’t support the .NET code gen, so i took the plunge and wrote the whole thing in Java. Antlr has since made it to the full V3 release , and now includes a working C# code gen. Stringtemplate also has some working C# assemblies, and is now tightly integrated with Antlr V3. If I were to implement anything serious in Antlr, I think I’d be tempted to go down the C# route, now the Codegen’s caught up.
Anyway, having implemented a full DSL, I think I would probably have done some things differently. The majority of our code is already in C, so I briefly considered augmenting an existing C based grammar with new keywords to enable the level of ORM that we required. Unfortunately the C files we have are already augmented with both Pro*C and ESQLC, so I’d have supplement my grammar with those as well. Feasible, but much more time consuming than stepping back and implementing something from scratch which generates both ESQLC and Pro*C files.
The end result is pleasing, I have a small DSL, with some 60 keywords, that’s capable of completely generating all the code required to implement a Tuxedo service across all three tiers, add in a sprinkling of automation to build these services and we could almost call ourselves ‘Agile’ without smirking.