A while back I wrote about command line scripting of Pharo to backup an SQLite database, specifically, this server's iptables log. Eventually I wrote a program in Pascal to archive and rollover the log database. Reason being, using the excellent Free Pascal compiler, I link SQLite statically into the final executable, meaning I only deploy a single binary executable, which is a tad more convenient than deploying the Pharo VM, image, sources, and script files.
Well, not quite just one file.
My program, iptlb, uses the SQLite online backup API to back up the running log database to an archive database file, then "backs up" an empty template database to the running log database file, effectively overwriting it. Because I want the flexibility to change the database schema during each backup run, iptlb creates a new template database each time it is invoked. Because I also want just one Pascal source file, I want to store the database schema in the source file itself, so that the schema gets version-controlled along with the Pascal code.
However, Pascal does not support multi-line string literals:
This means that I cannot embed the database schema into iptlb's Pascal source directly as a multi-line string. In production, I have to also deploy the database schema SQL as a separate file which is read by iptlb to create its template database.
There is a workaround in Pascal for lack of multi-line strings, as follows:
This looks like a templating thing. And that calls for Mustache!
After fiddling around, I created a simple class PMMultiLineStringTemplate which wraps the work with Mustache. Here's the motivating use case:
Copying the output of dbschema.pas (generated with a proper schema as above) into iptlb.pas, I now have one source file iptlb.pas embedding the SQL schema, and I deploy one binary executable iptlb only.
Goran Krampe's HttpView2 web programming framework has a nice utility called MacroProcessor, which provides PHP-ish expansions, as per the class comment:
The above code produces the string 'This code: 3+4 evaluates to: 7.'
I've previously used MacroProcessor to good effect to generate Linux- and Windows-specific Makefiles from templates.
MacroProcessor's code contains a sprinkling of underscores as assignment operators. The code base is small, so it is possible to convert underscores to the ":=" assignment operator by hand, but what fun is that?
What is fun is to do that in Smalltalk. The following is done in Pharo 1.2, which is where I have a copy of MacroProcessor. The starting points were Compiler, RBParser, Decompiler, etc. After poking around - running code in workspaces and exploring their results, looking at test cases - I come to RBConfigurableFormatter>>acceptAssignmentNode: which looks like this:
Ok... And assignmentOperator turns out to be RBAssignmentNode>>assignmentOperator, which is:
Aha! The next step is obvious:
With the above, and a bit more exploratory programming in workspaces, I end up with the following:
Figure 1: Here's what a method looked like originally.
Figure 2: Here's what the method looks like afterwards.
It remains to file MacroProcessor out from the Pharo 1.2 image, then file it into my current working Pharo 1.4 image.