
@mflatt I’m trying to add splicing-parameterize
to racket/splicing
, but I’m not quite sure how to implement @ryanc’s suggestion to let go of the reference to the parameterization after the bodies. I thought about treating the final body specially, but as a particularly perplexing edge case, it could expand into (begin)
, in which case inspecting the previous body is necessary.

@lexi.lambda I think Ryan’s suggestion was to add (set! new-parameterization #f)
only in a module or top-level context. It should be easy there, and it should be unneeded elsewhere.

That will still cause different behavior in the REPL, right? It will always produce #<void>
instead of printing a value, if relevant.

But maybe that’s acceptable.

I see what you mean, and I agree that it’s acceptable.

Okay, works for me. Thanks for your input; I’ll probably open a PR soon.

@lexi.lambda YAY! :heart:

@mflatt I have a question involving two modules A
and B
, as well as a third module C
that dynamically visits A
.
B
uses an accumulator during expansion

Which it provides (for-syntax).
A
requires B
, and since this accumulator is used at phase 1 B is freshly…err…instantiated (I think that’s the word?)

Anyway, if C
dynamically visits A
, is there any way I can get the accumulators that B
built up (and provided) for that specific instantiation for A
?

How does C
dynamically visit A
?

Honestly, any way that makes it possible.

A
and B
are files on the machine.

I’m happy to parse them as syntax objects and call expand
, I’m happy to call dynamic-require
on the module path, and honestly, I’m happy to do other things which I’m sure I left out as well.

@leif have A
serialize the accumulator into a begin-for-syntax
that re-creates it when C visits A

a la YWIW

@samth So, I am not directly writing A
.

However, I do have control over the language A
is written in.

so make the language do that

So are you saying all modules written in the language A
is written in should have that export?

yes (although I wouldn’t describe it as an export)

Okay, then if A
doesn’t export it (or its serialization), how can C
get it?

I mean, making the box isn’t the problem, its getting it from B
to C
.

Oh, or are you just saying that A
should define it, but not export it.

the technique I described is how C can get it

And then C
should grab the namespace for A
.

I guess that might work.

and neither “define” nor “export” are good words here

So, IIRC, YWIW uses begin-for-syntax
inside of a syntax object to sort of…re-build information every time module A
is visited.

Where as I don’t really care about whether or not the data is there after re-expansions. Rather, I would like something a little more subtle.

I want the actual accumulator used during the visit to B, not just a serialization. And I want it because I am expecting A
to be an incomplete (readable but with, say, buggy macros) file.

This is because that accumulator contains, more or less diagnostic information that B
uses in the language implementation. But now I’m also trying to make a tool to print that information out. And I don’t want to assume A
actually finished expanding.

@samth So if YWIW talks about that sort of thing and I completely missed it, I’m sorry. If I understand its section 3 (where you implement records) of the paper you’re talking about, yes?

Yes, that’s right

I don’t think you can get “the actual value”

Ah, okay.

hmmph…sad day. Thanks.

But ya, that’s why I was asking @mflatt, because if its at all possible, I’m sure he’d know. (As I’m not aware of anyone in the Racket ecosystem actually trying to do such a…odd…thing.)

but why is “the actual value” needed

Because A
may not have finished expanding.

I don’t see how that’s related

Like, say, they could have written the file:
#lang the-lang
(f 1 2 3)
And the expander throws and error saying f
is unbound.

sure

From what I gather, the technique used in YWIW assumes the Zoo
file actually expands.

So it can grab the serialized value from its code.

no, that’s not how it works

the technique inserts expressions which mutate state, and then other code looks at that state

Right. IIRC it inserts something like: (register-def #'c-name #'p-name
#'(f-name ...)))
(copy/paste from the paper)

yes

Mmm…so you’re saying that C
should get access to the registry that register def
adds to

yes

AH, okay.

Wow, that’s subtle.

(I mean, there was a LOT of really cute subtle stuff in the paper I did pick up, but that use of the idea was not one I put two and two together.)

@samth Ah, okay. I think I remember the problem I had with that. Namely, I still can’t get my hands on the registry register-def
mutates. (Unless its somehow parameterizable by C
)

B should provide it

and the C requires B

Oh, you mean B
should provide it at phase 0?

(I mean, it already provides it at phase 1, but obviously it will get reset every time the module runs.)

err…every time module A
gets visited.

I mean B should be something like:

(module B racket/base
(define registry (make-hash))
(provide registry))

@samth Sure, I have a module: (module submod-acc racket/base
(provide (all-defined-out))
(define editor-list-box (box '()))
(define editor-mixin-list-box (box '())))
(require (for-syntax 'submod-acc))

Where editor-list-box
is the registry.

But whenever I do a dynamic-require of A
, that box is (expectedly) empty.

(I’ve also been doing the dynamic require with the (void)
argument)

So it visits the module.

right, so you need to make A update that box

or B, since A depends on B

I already do that (unless its wrong):
(define-for-syntax (add-syntax-to-editor! stx)
(define existing (unbox editor-submod-box))
(when (null? existing)
(syntax-local-lift-module-end-declaration
#'(define-editor-submodule)))
(set-box! editor-submod-box (append (reverse (syntax->list stx)) existing)))
(define-syntax (editor-submod stx)
(syntax-parse stx
[(_ body ...)
(add-syntax-to-editor! (syntax-local-introduce #'(body ...)))
#'(begin)]))

(The same trick that also lets module+ work.)

OH

Except I forgot to add it to the template for the editor-submod
….

@samth Hmm…nope, still empty.
I added: #'(begin
(begin-for-syntax
(set-box! editor-list-box ....)))

Into the template.

that will change the box at at phase 1 of the expansion of A

Also I’m currently trying to get it with something like: (dynamic-require 'editor/stdlib (void))
(dynamic-require '(submod editor/lang submod-acc)
'editor-list-box)

is that what you want?

that won’t do what you want wrt those dynamic-require calls, which are doing things at phase 0

what you want is to generate code that updates the box at whatever phase you actually want it

Ah, woops, the second one should be dynamic-require-for-syntax

But ya, it should be at module A’s phase 1.

OMG, it dynamic-require-for-syntax
worked:

(dynamic-require 'editor/stdlib (void))
(dynamic-require-for-syntax '(submod editor/lang submod-acc)
'editor-list-box)

you might find our PLDI’11 or Scheme’07 papers clearer on this

That’s the advanced macrology paper iirc right?

(Or the TR paper from the macro perspective.)

yes

Okay cool.

It looks like its working now. Thanks so much for your help.