To get the expanded forms you'll need to use local-expand
in some way.
Part 1, an incomplete solution
You might think to call local-expand
separately on every expression like this:
#lang racket
(require syntax/parse/define
(for-syntax syntax/stx))
(define-simple-macro (my-module-begin e ...)
; define a function that expands it
#:do [(define (expand/mod-ctx e)
(local-expand e 'module '()))]
; get the expanded versions by calling that function on the e's
#:with (e-expanded ...) (stx-map expand/mod-ctx #'(e ...))
; use the expanded versions inside foo
(#%module-begin
e-expanded ...
(foo e-expanded ...)))
This works when the e
forms are expressions like (+ 1 2)
or (let ([x 3] [y 4]) (make-list x y))
. However, it doesn't work when the e
forms can be definitions.
Part 2, getting the expanded versions from Racket's #%module-begin
One way to support using local-expand
with these module-level definitions is to wrap it in racket's #%module-begin
form before expanding. This allows it to process all the e
s together in one call to local-expand
.
(define-simple-macro (my-module-begin e ...)
; get the expanded versions by calling that function on a
; *constructed* module-begin form
#:with (_ e-expanded ...) (local-expand #'(#%module-begin e ...) 'module-begin '())
; use the expanded versions inside foo
(#%module-begin
e-expanded ...
(foo e-expanded ...)))
This gets Racket's #%module-begin
to handle the definitions, and when it's done, you can pattern match on it with (_ e-expanded ...)
.