Accept expressions in left-hand side of quasiquotations
Gershom Bazerman (gershomb@gmail.com) writes: Attached is an experimental patch (not read for prime-time) that extends quasiquotation syntax. At the moment, quasiquoters can only be single identifiers of type QuasiQuoter
(and of course declared outside the current module). This patch allows an entire expression of type QuasiQuoter
in the quoter position. The staging restriction is extended to all free variables in the quasiquoter expression.
So if qq1 :: Int -> QuasiQuoter
, one can now write [$qq1 12 | ... |]
This syntax would be quite useful for my own project (jmacro), and from discussions at ICFP, to others who also are beginning to take serious advantage of quasiquotation.
Here's one use case. Suppose jmt is a QuasiQuoter
which returns both a parsed Javascript expression and its "module signature" (or "typing environment" if you prefer). Then, one can pass that typing environment directly into another quasiquoter in a different module, so that further code can be typechecked at compile-time with functions defined in the first quasiquote available to the Javascript typechecker. This style of programming is currently possible, but it requires defining additional new modules which contain QuasiQuoters
parameterized with each successive typing environment.
There are a number of tricky choices made in this patch, not all of which are perhaps correct.
First, currently, the quoter and quotation are lexed and parsed as a single token. To avoid reinvoking the lexer and/or parser, now '[$' is lexed as one token, and a flag is set in the lexer state which lexes the |...|]
(i.e. the quotation) as a single quotation on encountering the first vbar. This means that guards can't be used inside a quasiquoter expression -- i.e. [$let x | True = 1 in qq1 x|..|]
would fail to parse. This also means that while now in ghc 7, one can write [qq|..]
, to parse a full expression rather than identifier, we need the dollar sign as well.
The former problem (stealing guards within quasiquoter expressions) can be fixed by a syntax change which moves from a single vbar to a new symbol (perhaps $|
or ||
?) to signal the transition between the quoter expression and the quote itself. I tend to feel that the loss of guards within quasiquoter expressions is not too painful, however. Adding a new symbol between quoter and quotee also would simplify the necessary changes to the lexer, removing the need to set a special flag in the lexer state.
The second problem (need to reintroduce a dollar) is somewhat irritating, but not terribly so. One could either introduce the dollar in all cases, which allows simplifying the lexer and parser, or keep the dollarless syntax as well for single identifiers, which adds both complexity and duplicate syntax, but keeps the default case especially lightweight.
The patch as it stands introduces "extended quasiquotations" as an orthogonal change that doesn't affect the existing quasiquotation machinery, and, at the moment, only allows for quasiquotations of expressions (i.e., not patterns, etc.).
If there is sentiment that this is useful and could be accepted, modulo whatever requested tweaks, I'd be happy to do whatever work is necessary -- implementing changes, adding documentation, pushing the changes through to quasiquoters in other positions, etc.