
Is it possible to pass down a syntax object from one phase to the other? I have a macro at phase 2, which creates a macro at phase 1. But to be able to pass down syntax objects, I put them into structs, then transform them back into syntax objects using stx-map, datum->syntax, and co. Is there a better way?

I think I found a simpler way by simply generating a #'()
call

In principle the compilation happening in phase 2 and phase 1 can happen at separate times (say monday and tuesday). Therefore the solution you found (letting phase 2 generate a phase 1 program containing a call to syntax
) seems to be The Right Thing®.

Ok, another short question… (I feel like I’ll never be finished with that freakin’ macro) If I produce a syntax-list, then bind it with #:with (elem ...) (my-syntax-list-producer)
it fails and just binds the first item in the list

Double check: what does (display (my-syntax-list-producer)
print?

it prints a correct syntax like so: #'((elem1 blabla) (elem2 blabla))

Also try #:with ((elem …) …)

Is it always a list of two-element lists?

nope, there can be more or less elements inside

oh, wait, I think I see the issue

it had a syntax-class

but the syntax-class is already resolved at this point

?

Ok, so my issue is that I want to merge two (elem:my-class …) bindings into a single one

Oh, where my-class
is a splicing class?

nope

it’s a simple class

but it parses a lot of stuff and creates attributes

and I want to get those attributes later, but since the merge happens between different phases, the attributes are gone

(I know, it’s complicated :P)

That’s a lot of things to do at once

So you need to rewrite (a1 a2 …) (b1 b2 …) to (a1 b1 a2 b2 …) ?

yep

(append-map list as bs)

right now I’m doing an append, then datum->syntax

but datum->syntax loses the class attributes, it just renders plain syntax

attributes on the indivisual elements?

yep

(append-map list (syntax->list as) (syntax->list bs)) ought to be fine?

yeah, that’s what I do… but in fact I realize the issue is that I can’t pass attributes down a phase level. I need to render them into a syntax
call, so I lose them

Hmm. I can’t remember how that works.

Well, the only way I see would be to make a call to syntax
with each attribute rendered in the list

so that I can get them back by position

something like #:with (elem:class ...) (my-elements)
#'(define-syntax my-other-phase (quote-syntax #'(elem.attr1 elem.attr2 elem.attr3)))

I would do this by having a single attribute of the syntax class to represent the info that needs to be passed down a phase level

yep

I’m going this way

And then if that attribute is called nextphase
the syntax call would look like #'(elem.nextphase ...)

It’s reassuring to know there are people like you who can actually understand what I’m doing… Cause I don’t x)

I’ve learned because I’ve failed before but kept going eventually finding it

So, before I try putting everything in a single syntax for the next phase… Can you confirm that there’s no way to create a syntax-class instance manually?

cause that would simplify the code

Not sure what you mean

Do you (@jerome.martin.dev) mean something like this? (syntax-parse <manually-created-syntax-object
[elem:class <use elem here>])

yep, except I’d like to return the bound value instead of using it. But I guess it’s not possible

It breaks the fundamentals of syntax-parsing

I’m going to use a simple list with two elements and put the attributes I need in there

like this: (list (quote-syntax (<elem>.attr1 ...))
(quote-syntax (<elem>.attr2 ...)))

or maybe…

(quote-syntax ((<elem>.attr1 <elem>.attr2) ...))

then I can do #:with ((attr1 attr2) ...) (merge-elements)

Off topic: @jerome.martin.dev If you are interested in a free C64 book: https://fusionretrobooks.com/collections/pdf/products/pdf-the-story-of-the-commodore-64-in-pixels_?fbclid=IwAR0DH_gLvlCnxN3tOEBcvaRgxv6tGe148nJmdnIfhGpm8MBKyaHRzkVi_5k

Oh my god my code works

I think it’s the most complicated macro I ever wrote

and it’s only 150 lines long x)

well, actually even less than that, I’m counting (define-for-syntax) helpers too

it generate macros that can inherit from other macros

I just have a small question for you @alexknauth : Remember yesterday you gave me the way to create a wrapper around struct ids at compile time? I have doubts about #:property prop:procedure
being passed (make-variable-like-transformer #'internal-id)
. It takes only one argument so when a call is done like so (my-own-wrapper value1 value2 value3)
it fails as “arity mismatch”

For the record, a complete example: ;; in begin-for-syntax:
(struct metactor (normal struct-info attributes)
#:property prop:procedure (struct-field-index normal)
#:property prop:struct-info (lambda (self) (metactor-struct-info self))
#:property prop:metattributes (lambda (self) (metactor-attributes self)))
;; in macro template for next phase:
(struct <id> () #:name internal-id #:constructor-name internal-id)
(define-syntax <id>
(metactor
(make-variable-like-transformer #'internal-id)
(extract-struct-info (syntax-local-value #'internal-id))
(~? (quote-syntax ((<own-attr>.parse-pattern <own-attr>.term) ...)) #'())))

the only part I don’t understand is the use of make-variable-like-transformer
and struct-field-index

obviously it just works if I use internal-id instead, so it’s not a big deal for me. I just want to understand what’s happening

I’ll have to try it on my computer

Thanks! I cannot express how awesome the help I get here is :slightly_smiling_face: When I’m describing my problem I feel like I’m using some weird incantation spells, but you actually understand!

Oh, sorry, I forgot that make-variable-like-transformer
produces a set!
-transformer instead of a “normal” procedure.

So to get around this I usually define: (begin-for-syntax
(define (make-var-like-transformer id)
(set!-transformer-procedure (make-variable-like-transformer id))))

To whoever made make-variable-like-transformer
, why is the value it returns not a procedure?

And to whoever made prop:procedure
why do you get an “arity mismatch” error if the value doesn’t lead to a procedure, instead of a “not a procedure” error?

It returns a set!-transformer
. So something needs to know whether a transformer is a set!-transformer. Probably set!-values
. But is that what you are getting at?

But something can be both a set!-transformer?
and a procedure?
if it implements both prop:set!-transformer
and prop:procedure

Could it be that set!-transformers are older than applicable structs?

Thanks! It works fine now :slightly_smiling_face:

It seems 203 is the first version of the docs where “structures as functions” are mentioned (that section is not in the 202 docs).

On the other hand set!-transformers are older. But as I read the old docs on set!-transformer a normal procedure is expected.

That choice allows procedure?
to be a constant-time test.

(define x 5)
(define-syntax m1 (make-set!-transformer (λ (stx) #'x)))
m1 ;=> 5
(define-syntax m2 (compose identity (make-set!-transformer (λ (stx) #'x))))
;=error>
;compose: contract violation
; expected: procedure?
; given: #<set!-transformer>

Anyone knows what’s the oldest version of PLT Scheme that still runs on macOS?

That makes sense as to why procedure?
would return true. However, it doesn’t make sense why the error message would say “arity mismatch”

:slightly_smiling_face: Attempted to download v103. Got to choose between Mac Classic ppc or 68k.

Version 350 gives a similar error message: procedure application: expected procedure, given: #<set!-transformer>; arguments were: #<syntax::474>

I guess it’s more that procedure-arity
returns '()
(and since procedure?
returns true, then procedure-arity
needs to return something). With that choice, attempting to apply the procedure should report an arity error.

Thanks for the link! A great book for a Commodore fan :slightly_smiling_face:

I have a function that’s just like make-variable-like-transformer
except that it doesn’t produce a set!-transformer
or handle setter-stx
.
What should it be called? make-constant-like-transformer
doesn’t seem right. Is something like make-expression-id-transformer
better? Expression alias? Named expression transformer? Other ideas?

I seem to copy some version of this function into every file or every project I write. Also, the fact that it doesn’t exist in the base racket distribution has caused problems for both me and just recently for Jerome.

The only problem I’m having is giving it a name.

@alexknauth I think you already solved this? https://twitter.com/AlexKnauth/status/1063213319031570432

Is make-id-transformer
a good name?

I am constantly frustrated because both make-rename-transformer
and make-variable-like-transformer
are so close but can’t be used in so many situations that require a procedure?
value.

@alexknauth You could change make-variable-like-transformer
to return an instance of a struct that implements both prop:set!-transformer
and prop:procedure
. Or you could add an argument to suppress the make-set!-transformer
wrapper.

Should make-set!-transformer
return such a struct that has both?

I don’t know. That’s a bigger change, and it risks breaking code that assumes set!-transformer
s and procedures are disjoint. I don’t know if any such code exists.

I think the procedure?
behavior should be the default behavior of some procedure in the documentation. I don’t want it to be “hidden” behind an optional argument.

I think it’s fine to change make-variable-like-transformer
to return something that implements both interfaces. (It’s more recent and less widely used than set!-transformer
, which is why I think there’s less risk with it.)

Okay.

@ryanc That’s what I’ve now done in https://github.com/racket/racket/pull/2540