I wanted to write something that would delete old rsync snapshots. I took the domain-specific language approach, where the language specifies the retention policy for snapshots, like this:
policy = recent <||> weekly <||> monthlymeanings the final policy is to keep 'recent', 'weekly' and 'monthly' backups, with other statements defining what those three other policies mean. I won't write more about the language here - there's more on the webpage for the tool, snaprotate.
One particular piece of this I don't feel terribly comfortable with, and thats how to invoke/run the policy files.
I can imagine two different interfaces:
$ snaprotate -f policyfileor
$ policyfile
I took the second approach, making policies first order unix executables - commands that can be run like any other command.
In unix tradition the way you indicate the language of a script is with a shebang line (#!/something) at the start of the script.
So then I want my scripts to look like something like this:
#!/usr/bin/snaprotate policy = recent <||> weekly <||> monthly
This is almost a valid Haskell program, but: i) I need to import the SnapRotate module, and ii) I don't want to specify a
main
routine (which looks something like:main = runPolicy policy).
So the
snaprotate
commandline looks almost like runhaskell
but does some source file rearranging to address the above two points, and to remove the #! shebang line.#!/bin/bash FN=$(mktemp /tmp/snaprotateXXXXX).hs FNHS=$FN.hs LIBDIR=$(dirname $0) cat > $FNHS << 32804384892038493284093 import SnapRotate main = runLevels policy 32804384892038493284093 cat $1 | grep --invert-match '^#!' >> $FNHS shift runhaskell -i$LIBDIR $FNHS $@I wonder if this is the best way to implement such an embedding?
It is clearly suboptimal. Your EOF marker of 32804384892038493284093 is not prime.
ReplyDeleteAn easier approach is to use literate haskell.
ReplyDeleteThis is common in Setup.lhs files for cabal:
#!/usr/bin/runhaskell
\begin{code}
...
\end{code}
or
#!/usr/bin/runhaskell
> your dsl
> goes here
From a language-user perspective, I think thats worse, although I can see its easier to implement from the language-implementor side because its using existing mechanisms.
ReplyDeleteIts worse because its more boiler plate that doesn't relate directly to the language, and doesn't add anything: "you must put a > at the start of every line.." "so why don't I write a little program to put a > at the start of every line for me?" "umm..."
there are some other comments on
ReplyDeletedons' posting of this on reddit