This is another journal entry of my progress toward an extensible quasiquotation syntax. It wanders a bit, but I think it has a happy ending. :)
My last post was about “higher quasiquotation.” Since then, I’ve taken to calling that subject hypersnippets, since the characteristic feature is that it’s a repeated iteration of the concept of “the snippet of code between this boundary and this boundary.” Degree-N hypersnippets are made up of all the code in between a degree-(N-1) hypersnippet shape and zero or more nonoverlapping degree-(N-1) hypersnippet shapes appearing inside it. A degree-1 hypersnippet is like a text selection, and degree-0 hypersnippet is a text stream. Quotation is a certain kind of DSL where the syntax is hypersnippet-shaped, but there are potentially other uses for these shapes.
(Spoilers: Yesterday I finally convinced myself hypersnippet shapes were precisely the opetopes, and hypersnippet-shaped data is data that’s composable using the operations of an opetopic ω-category. So hypersnippets in my original sense are an ω-category generated by some free 1-cells corresponding to characters that can appear in a text stream. (Update 6-3-2018: Michael Arntzenius points out that these generators on their own would just generate strings. I was also sloppy about specifying the generator cells’ sources and targets here. Looks like I need one generator of each opetopic shape to be the holes, with each one’s sources and target being lower-dimensional holes; as well as one generator corresponding to each text character, each of which is a 2-cell with no sources, targeting the unique 1-cell hole.) Nevertheless, I’m still going to refer to these as “hypersnippets” in this post, and I think it’s valuable to refer to them by their intended usage domain in case they morph into a slightly different concept, even if the concept now seems to have stabilized into something that corresponds with opetopes.)
Lately I’ve been trying to iron out the details of a generalization of quasiquotation which I call “higher quasiquotation.” The basic idea is that just as a quasiquotation is a region in one parenthesis-delimited region (marked by
quasiquote) and a set of other parenthesis-delimited regions (marked by
unquote), we can go on to talk about regions between quasiquoted regions, regions between those regions, and so on.
If you think of values with holes as being functions, then the notion that this is a “higher-order” quasiquotation is clear: Each quasiquotation determines a value of type
(c SExpr -> SExpr), the next higher degree of quasiquotation determines a value of type
(c (c SExpr -> SExpr) -> (c SExpr -> SExpr)), and so on, where
c is some collection like
c a = Map String a. But these functions aren’t the whole story; the quasiquotations should be able to be pulled apart like other data structures, not just filled in to create s-expressions.
I haven’t managed to write a full macroexpander for higher quasiquotation yet. I’ve written this post to share my status as it is.
Cene is a language I’ve built over the last couple of years. I’ve talked about Staccato and Tenerezza here, and that code has turned into Cene.
What sets Cene apart: Extensibility support
Cene’s design revolves around the primary idea that future generations will have better ideas for programming languages than we do, so most of what sets it apart is its support for custom languages, which mainly has to do with the design of its macroexpander.
Cene’s macroexpansion phase incrementally writes definitions (of macros, functions, etc.) to monotonic state resources using deterministic concurrency. These state resources are expressive enough that user-defined macros can use them to achieve combinations of open-world and closed-world extensibility, which is what I consider to be Cene’s primary feature.