On this page:
scopes-empty?
scopes<=?
~autoptic-list-to
~autoptic
~autoptic-list
8.18

10 Utilities for Macros🔗ℹ

 (require lathe-comforts/syntax)
  package: lathe-comforts-lib

The lathe-comforts/syntax module defines utilities for use at macroexpansion time.

Some of these utilities are useful for parsing syntax in a way that requires a property we call autopticity. We consider a macro call to be autoptic when all the cons cells, keywords, unquotes, and other structural elements that need to be crawled into or checked for identity (excluding things at the leaves like expressions, data literals, and identifiers not given meaning by the macro’s own design) are all right there at the macro call site, where we can see them all at once. In technical detail, a syntax object representing one of these cons cells or other structural elements is required to have a set of scopes that’s equal to or a superset of the set of scopes on the overall macro call, as though the macro call has created local bindings of what these particular structural elements mean in these particular positions. This helps ensure that even though Racket expressions are often made of cons cells, an arbitrary Racket expression inserted into one of these positions by a macro’s syntax template will not have its cons cells misinterpreted.

An example of a situation which would be ameliorated by use of autoptic parsing is the cond syntax. Racket’s cond is extended by both a => clause notation and the ability to use internal definitions. Someone who wants to define another control flow operation that allows internal definitions might simply insert the user’s definitions into the cond body, but this can inadvertently allow a user to write => at the start of the body as a way to elicit unintended behavior from the control flow abstraction. If the => notation were recognized as a structural element whose meaning was bound by the cons form, then it would simply not be in scope within the user’s inserted definitions, just as for any other local binding within a macroexpansion template.

procedure

(scopes-empty? stx)  boolean?

  stx : syntax?
Returns whether the scopes of the given syntax object are the empty set.

procedure

(scopes<=? a b)  boolean?

  a : syntax?
  b : syntax?
Returns whether the scopes of the first given syntax object are a subset of the scopes of the second one.

pattern expander

{~autoptic-list-to surrounding-stx pattern}

 
  surrounding-stx : syntax?
A pattern expander that parses according to pattern, but only if the syntax object is a syntax list, each of whose syntax object tails has a set of scopes that’s equal to or a superset of the set of scopes on the given syntax object surrounding-stx.

Parsing using this pattern helps to ensure autopticity of the call site being parsed.

This syntax itself must also be called with autopticity. An occurrence of a cons cell that’s part of the call syntax must have a set of scopes that’s equal to or a superset of the set of scopes on the entire call, as though the call has created a local binding of what a cons cell means in these positions. This helps ensure that even though Racket expressions are often made of cons cells, an expression inserted into one of these positions by a macro’s syntax template will not have its cons cells misinterpreted.

pattern expander

{~autoptic pattern}

A pattern expander that parses according to pattern, but only if the syntax object has a set of scopes that’s equal to or a superset of the scopes of the syntax object this-syntax that’s currently being parsed.

Parsing using this pattern helps to ensure autopticity of the call site being parsed.

This syntax itself must also be called with autopticity. An occurrence of a cons cell that’s part of the call syntax must have a set of scopes that’s equal to or a superset of the set of scopes on the entire call, as though the call has created a local binding of what a cons cell means in these positions. This helps ensure that even though Racket expressions are often made of cons cells, an expression inserted into one of these positions by a macro’s syntax template will not have its cons cells misinterpreted.

pattern expander

{~autoptic-list pattern}

A pattern expander that parses according to pattern, but only if the syntax object is a syntax list, each of whose syntax object tails has a set of scopes that’s equal to or a superset of the set of scopes on the syntax object this-syntax that’s currently being parsed.

Parsing using this pattern helps to ensure autopticity of the call site being parsed.

This syntax itself must also be called with autopticity. An occurrence of a cons cell that’s part of the call syntax must have a set of scopes that’s equal to or a superset of the set of scopes on the entire call, as though the call has created a local binding of what a cons cell means in these positions. This helps ensure that even though Racket expressions are often made of cons cells, an expression inserted into one of these positions by a macro’s syntax template will not have its cons cells misinterpreted.