[racket] getting one macro to tell another macro to define something
Well one problem is expander application his its own mark to deal with, so you can't cancel the mark on x.
https://github.com/plt/racket/blob/master/racket/collects/racket/match/parse-helper.rkt#L157
Another problem is expecting the implementation of match-define to not have any inner macros that would change syntax-local-introduce to a less helpful extent.
What would be ideal is if racket/match could change some "parameter" so that syntax-local-introduce used the introducer defined in the above link, since the generated temporary does not have x's mark that x has annihilated. Instead x's mark will be added to tmp after the transformer returns, and there's nothing you can do about it :(
-Ian
----- Original Message -----
From: "Alexander D. Knauth" <alexander at knauth.org>
To: "J. Ian Johnson" <ianj at ccs.neu.edu>
Cc: "racket users list" <users at racket-lang.org>
Sent: Friday, August 1, 2014 6:31:59 PM GMT -05:00 US/Canada Eastern
Subject: Re: [racket] getting one macro to tell another macro to define something
Well, if the match-expander is invoked in the “dynamic extent” of the match-define form, then would syntax-local-introduce apply that syntax-mark?
On Aug 1, 2014, at 6:20 PM, J. Ian Johnson <ianj at ccs.neu.edu> wrote:
> Well that's a pickle. I can tell you that (mac . args) gets expanded as (X[mac^m] . X[args^m])^m where m is a fresh mark and X expands a form. If m is applied to something with m already, they annihilate each other (see Syntactic Abstraction in Scheme for how this totally works).
> The syntax-local-introduce form allows you to apply the macro application's mark to an arbitrary piece of syntax, so later on the application's mark will annihilate it and voila`, it's like it was textually given to the macro application itself.
>
> Here, however, a match expander is not treated as a macro invocation. There is no mark for that match-expander use to introduce. There is, however, the mark from match-define that you'll want to introduce to this temporary you've generated. I think. I haven't quite worked out how to make this work.
> -Ian
> ----- Original Message -----
> From: "Alexander D. Knauth" <alexander at knauth.org>
> To: "racket users list" <users at racket-lang.org>
> Sent: Friday, August 1, 2014 5:55:57 PM GMT -05:00 US/Canada Eastern
> Subject: Re: [racket] getting one macro to tell another macro to define something
>
>
>
>
>
> On Aug 1, 2014, at 5:37 PM, J. Ian Johnson < ianj at ccs.neu.edu > wrote:
>
>
> It's best to expand into a begin-for-syntax that does the desired mutation, rather than mutate within the transformer. You currently _cannot_ do this outside top level forms.
>
>
>
> The reason I can’t do that is because in the real program, sender is actually a match-expander.
>
>
> You are also right about the marks. The call to receiver adds additional marks to the definitions that it pulls out, so you'll need to apply syntax-local-introduce. ...
>
>
>
>
> On Aug 1, 2014, at 5:39 PM, Ryan Culpepper < ryanc at ccs.neu.edu > wrote:
>
>
> Use syntax-local-introduce when putting syntax into a side-channel or getting it back out across macro calls. This only matters when the syntax represents a definition or more generally contains binders whose references are not all in the same syntax.
> ...
>
>
> Thanks, the syntax-local-introduce got it working for that example, but for some reason it’s not working when sender is a match-expander.
>
> I’m still not very clear on when to use syntax-local-introduce and when not to, or even what it does (other than get that example working), so could someone point me in the right direction?
>
>
>
> #lang racket
> (require racket/stxparam
> (for-syntax syntax/parse
> racket/syntax
> racket/set))
> ;; current-defs : (syntax-parameter-of (or/c set-mutable? #f))
> (define-syntax-parameter current-defs #f)
> (define-match-expander sender
> (lambda (stx)
> (syntax-parse stx
> [(sender x)
> #:with tmp (generate-temporary #'x)
> (define defs (syntax-parameter-value #'current-defs))
> (set-add! defs (syntax-local-introduce #'(define x tmp)))
> #'tmp])))
> (define-syntax reciever
> (lambda (stx)
> (syntax-parse stx
> [(reciever)
> (define defs (syntax-parameter-value #'current-defs))
> (with-syntax ([(def ...) (map syntax-local-introduce (set->list defs))])
> #'(begin def ...))])))
>
>
> (syntax-parameterize ([current-defs (mutable-set)])
> (match-define (sender x) 1)
> (reciever)
> x)
>
>
> ;x3: unbound identifier;
> ; also, no #%top syntax transformer is bound in: x3
>
>
>
>
> ____________________
> Racket Users list:
> http://lists.racket-lang.org/users