I think you need to use a trampoline for the module body's expansion,
where you expand only one module-body form at a time and let
`#%module-begin` finish up forms like `require` or `define-syntaxes`
before you macro continues with later forms.
The general pattern is that you have a macro `do-module-begin` where
(do-module-begin
expr-0
expr ...)
turns into
(begin
expanded-expr-0
(do-module-begin
expr ...))
where `expr-0` is `local-expand`ed and transformed as needed. The base
module-body expander will process `expanded-expr-0`, importing and
binding macros as needed, before continuing with `(do-module-begin expr
...)` for the rest of the module.
For an example, see the implementation of `syntax/wrap-modbeg`.
This pattern shows up frequently, but I've never hit on quite the right
abstraction to turn the pattern into a library. It's probably just a
matter of trying harder.
At Fri, 29 Jan 2016 21:29:16 -0800 (PST), reilithion wrote:
> I'm trying to make a little EDSL that has one form that is special and needs
> to be collected and later processed. I want to allow a user of the EDSL to
> write a macro that expands to the special form. I have a module-begin that
> (so
> far) looks like this:
>
> (define-syntax (module-begin stx)
> (syntax-parse stx
> ((_ module-contents ...)
> (let-values
> ([(tasks other)
> (partition
> (syntax-parser #:literals (task-internal) ((task-internal _ ...) #t)
> (_ #f))
> (rest
> ;; Problems start here
> (syntax->list
>(local-expand
> #'(#%plain-module-begin module-contents ...)
> 'module-begin
> (list #'task-internal #'module* #'#%app)])
> #`(#%module-begin
> #,@other
> (define all-tasks (list #,@tasks))
> (process all-tasks))
>
> If I don't bother with the local-expand and just use (rest (syntax->list
> stx)), it works basically fine but won't treat macros that expand to
> task-internal specially. I tried mapping local-expand over (syntax->list
> stx),
> but that led to strange errors when I tried to define macros within the EDSL.
>
> This current implementation fails because it expands too much too soon. A
> macro will happily expand into (task-internal args ...), then (task-internal1
> args ...), then (#%app task-internal1 args ...), and then the call to
> partition won't see what it's expecting (in fact, I think it CAN'T see what
> it
> needs to, because I suspect the local-expand of the #%plain-module-begin
> effectively hides the task-internal identifier).
>
> I added a bunch of stuff to the stop-ids list, hoping it would bail before
> transforming task-internal beyond recognition, but nothing I added seemed to
> work.
>
> I also tried calling local-expand on #'(begin module-contexts ...) with the
> 'top-level context-v, but of course begin is automatically added to the
> stop-ids list and local-expand stops right away.
>
> Can I somehow get local-expand to only mostly expand a module? How do I do
> what I'm trying to do here?
>
> Thanks!
> Lucas Paul
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.