On this page:
hyperbracket-notation?
hyperbracket-notation-impl?
prop:  hyperbracket-notation
make-hyperbracket-notation-impl
hyperbracket-notation-prefix-expander?
hyperbracket-notation-prefix-expander-impl?
prop:  hyperbracket-notation-prefix-expander
hyperbracket-notation-prefix-expander-expand
make-hyperbracket-notation-prefix-expander-impl
makeshift-hyperbracket-notation-prefix-expander
hyperbracket-open-with-degree
hyperbracket-open-with-degree?
hyperbracket-close-with-degree
hyperbracket-close-with-degree?
8.0

4 Defining Hyperbracket Notations for Racket

 (require punctaffy/hyperbracket) package: punctaffy-lib

In order to use higher-dimensional hypernests for syntax in Racket, we supply some new notations that augment Racket’s low-dimensional lexical structure. We do this not by replacing Racket’s existing reader and macro system, but by letting each Racket macro that cares about higher-dimensional structure do its own parsing of that structure when it needs to. Before this parsing occurs, we represent the structure in Racket syntax in the form of what we call hyperbrackets.

Punctaffy hasn’t been put to the test yet, and there may still be some uncertainty about what the best notation for hypernest-structured programs will be. We may augment Punctaffy with new ideas in the future, and not all possible paths will necessarily lead to the same feature set.

With this in mind, we define our most basic hyperbracket notation keywords in such a way that they have no innate functionality but can instead be assigned meanings (hopefully consistent enough ones) by multiple external DSL implementations.

This is a pretty typical scenario in Racket. Racket has identifiers like _, ..., else, and unquote that are only assigned meaning by some external DSL.

Typically these DSLs recognize these special identifiers using free-identifier=?. This approach allows new keywords to be added over time by exporting them from new (module path, symbol) pairs.

We take a different approach: We treat the identity as part of the functionality of the macro itself, not of the identifier. For each new piece of hyperbracket notation that should be identifiable, we provide some innate way to identify it, essentially treating it as a small macro DSL of its very own. As various experimental DSL implementations based on Punctaffy’s hyperbracket notation mature and stabilize their macro calling conventions, we expect hyperbrackets to be a patchwork of multiple DSLs anyway, so we embrace that from the start.

Note that the term "hyperbracket" could be generalized beyond our Racket-specific use here. Punctaffy’s own hypernest-bracket? values are an abstract syntax representation of 0-dimensional hyperbrackets with labels in certain places. The ones we’re talking about here are instead a concrete (indeed, unparsed) representation of 1-dimensional hyperbrackets with no labels. We’re using the generic term "hyperbracket" for the latter because it’s the one that’s most likely to be relevant most often in the context of Punctaffy’s use as a Racket library, since Racket already has 1-dimensional hypernest bumps (namely, paren matchings) to attach hyperbrackets to.

Structure type property operations for hyperbracket notation keywords. Every macro that needs to be recognized as part of the hyperbracket notation by a hyperbracket parser should implement this property. That way, non-hyperbracket identifiers can be recognized as such, thus allowing hyperbrackets to coexist with existing Racket notations without the risk of making the user’s intent ambiguous.

A structure type that implements this property should generally also implement prop:procedure to display an informative error message when the notation is used in a position where a Racket expression is expected.

Returns something a struct can use to implement the prop:hyperbracket-notation interface.

Structure type property operations for hyperbracket keywords that can desugar to more basic hyperbracket notation when invoked in prefix position.

A structure type that implements this property should generally also implement prop:hyperbracket-notation to signify the fact that it’s a hyperbracket notation,

A structure type that implements this property should generally also implement prop:procedure to display an informative error message when the notation is used in a position where a Racket expression is expected.

procedure

(hyperbracket-notation-prefix-expander-expand expander 
  stx) 
  syntax?
  expander : hyperbracket-notation-prefix-expander?
  stx : syntax?
Uses the given hyperbracket-notation-prefix-expander? to expand the given syntax term. The term should be a syntax list which begins with an identifier that’s bound to the given expander.

Given an implementation for hyperbracket-notation-prefix-expander-expand, returns something a struct can use to implement the prop:hyperbracket-notation-prefix-expander interface.

Given an implementation for hyperbracket-notation-prefix-expander-expand, returns a macro implementation value that can be used with define-syntax to define a prefix hyperbracket notation. DSLs that parse hyperbrackets will typically parse this notation by first transforming it according to the given expander procedure and then attempting to parse the result.

Struct-like operations which construct and deconstruct the hyperbracket-notation? syntax implementation corresponding to ^<d. This notation represents an opening hyperbracket with a specified nonzero degree.

This structure type implements prop:procedure for one argument so that it can behave like a syntax transformer, but invoking that behavior results in a syntax error. In the future, this error may be replaced with a more #%app-like behavior.

Every two hyperbracket-open-with-degree values are equal?. One such value is always an ok/c match for another.

Struct-like operations which construct and deconstruct the hyperbracket-notation? syntax implementation corresponding to ^>d. This notation represents a closing hyperbracket with a specified nonzero degree.

This structure type implements prop:procedure for one argument so that it can behave like a syntax transformer, but invoking that behavior results in a syntax error.

Every two hyperbracket-close-with-degree values are equal?. One such value is always an ok/c match for another.