Reconstruct-Template
~list/  ctx
?list/  ctx
8.12

Reconstruct-Template🔗ℹ

Source code: https://github.com/AlexKnauth/reconstruct-template.

Provides ~list/ctx and ?list/ctx as a pattern-expander and a template-metafunction. These two go together so that if x is a syntax-list:
(syntax-parse x
  [{~list/ctx ctx e ...}
   #'{?list/ctx ctx e ...}])
=
x
You can think of these as similar to (e ...) as a syntax-pattern or syntax-template, where ctx saves the lexical context, source location, and syntax properties of the parens, and transfers them over to the result syntax object.

syntax

{~list/ctx ctx-id pattern ...}

A syntax-parse pattern that matches a syntax-list like (pattern ...). However, it also binds the ctx-id as a pattern variable that saves the lexical-context information, source-location, and syntax-properties of the parentheses.

Examples:
> (syntax-parse #'(1 2 3)
    [{~list/ctx p a b c}
     (values #'a #'b #'c)])

#<syntax:eval:2:0 1>

#<syntax:eval:2:0 2>

#<syntax:eval:2:0 3>

> (syntax-parse #'[1 2 3]
    [{~list/ctx p a b c}
     (values (syntax-column #'p)
             (syntax-span #'p)
             (syntax-property #'p 'paren-shape))])

0

1

#f

syntax

{?list/ctx ctx-id template ...}

A syntax template form that constructs a syntax-list like (template ...). However, it attaches the information saved in the ctx-id onto the parentheses of the new syntax object, including its lexical-context, source-location, and syntax properties.

Examples:
> (define stx1 #'[1 2 3])
> (define stx2
    (syntax-parse stx1
      [{~list/ctx p a b c}
       #'{?list/ctx p c b a}]))
> stx1

#<syntax:eval:2:0 (1 2 3)>

> stx2

#<syntax:eval:2:0 (3 2 1)>

; same source location
> (equal? (syntax-position stx1)
          (syntax-position stx2))

#t

; same syntax properties
> (equal? (syntax-property stx1 'paren-shape)
          (syntax-property stx2 'paren-shape))

#t

; same scopes
> (bound-identifier=? (datum->syntax stx1 'x)
                      (datum->syntax stx2 'x))

#t

The main intended use of ~list/ctx and ?list/ctx is for reconstructing syntax objects when making expanders for new core-form languages. This purpose is similar to syntax/loc/props from Alexis King’s blog post Reimplementing Hackett’s type language: expanding to custom core forms in Racket.

The main advantage of ~list/ctx and ?list/ctx over syntax/loc or syntax/loc/props is that they work even for stx-list templates nested deeply within a template, as well as for stx-list templates under ellipses. For example, if x is a well-formed let expression:

(syntax-parse x
  [{~list/ctx p1 l
              {~list/ctx p2 {~list/ctx p3 x a} ...}
              b}
   #'{?list/ctx p1 l
                {?list/ctx p2 {?list/ctx p3 x a} ...}
                b}])
=
x