mflatt
2017-8-9 13:02:24

@lexi.lambda I don’t know if that last example can work at all. The local-expand form can’t generally deal with a mixture of top-level or module-level evaluation and expansion. For example, I struggle with the question: What would it mean to define val when the definition can be discarded after local-expand?


mflatt
2017-8-9 13:03:55

So, your comment about delaying expansion seems like potentially the right idea, but I’m unclear on what part can be delayed. You might need to expand with a non-empty stop list and recognize sequences the way forms with internal-definition positions often do.


lexi.lambda
2017-8-9 17:05:35

@mflatt That makes sense. This is probably an XY problem. I want to expand forms entered into the REPL to see if they end in a definition or expression, so I can print the expression’s type as well as its result. However, I’m not completely sure what the right way to do that is with partial expansion.


samth
2017-8-9 17:06:16

@lexi.lambda the TR repl does that


lexi.lambda
2017-8-9 17:06:38

I thought TR might have some prior art. What is its technique?



lexi.lambda
2017-8-9 17:18:31

@samth I’m not entirely sure what I’m looking at


samth
2017-8-9 17:18:58

You probably have to look at the functions that calls


lexi.lambda
2017-8-9 18:10:26

@samth does it basically just recursively call local-expand with kernel forms as the stop list?


lexi.lambda
2017-8-9 18:10:43

I’m following the code as best as I can but TR is big


lexi.lambda
2017-8-9 20:15:18

@samth @mflatt Unless I’m overlooking something, given what you said, I think doing partial expansion might still expand too much, since it would still require expanding the form that needs that define-for-syntax binding.


lexi.lambda
2017-8-9 20:15:45

I don’t feel like I understand how expansion at the top level works, though.


lexi.lambda
2017-8-9 22:18:11

Hmm… even after trying to simplify my macro to play nicer with the top level, I’ve discovered even something as simple as this still doesn’t work: #lang racket (require (for-syntax racket/syntax syntax/transformer) syntax/parse/define) (define-simple-macro (m1 id:id) (begin (define-syntax id (make-variable-like-transformer #'"something")) (m2 id))) (define-simple-macro (m2 x) #:with result (local-expand #'x 'expression '()) 'result) (begin-for-syntax (println (local-expand #'(m1 foo) 'top-level '())))


lexi.lambda
2017-8-9 22:18:45

Partial expansion wouldn’t help here, because in order to determine if (m1 foo) is an expression, we’d need to expand (m2 id), which fails.


mflatt
2017-8-9 22:25:09

@lexi.lambda I can’t offer a long answer right now, but have you seen expand-syntax-top-level-with-compile-time-evals from syntax/toplevel?


lexi.lambda
2017-8-9 22:26:16

No, I hadn’t! I wasn’t aware of syntax/toplevel; that looks helpful.


lexi.lambda
2017-8-9 22:43:55

@mflatt syntax/toplevel looks very close to what I’m looking for, but I can’t figure out how to use it correctly—if I use it at the top level or in the runtime body of a module, it does what I’d expect, but if I call it at phase 1 or during expansion of #%top-interaction, (expand-syntax-top-level-with-compile-time-evals #'(m1 foo)) produces (#%app m1 foo) for some reason. It seems like maybe that happens because it treats the syntax object as a phase 1 expression? But I need to be able to expand it as a runtime expression.


lexi.lambda
2017-8-9 22:47:14

But now I need to drive for an hour, so I’ll be away from the keyboard as well.


lexi.lambda
2017-8-10 04:18:20

…hours later, my understanding is that I’d need access to the REPL’s namespace in order to properly use expand-syntax-top-level-with-compile-time-evals, but it doesn’t seem like current-namespace is set to the right thing during the expansion of #%top-interaction, and I’m not sure if there’s any way to get ahold of it.


lexi.lambda
2017-8-10 04:30:36

I suppose I can do something like this: (define-simple-macro (#%top-interaction . form) (#%top-interaction* (expand-syntax-top-level-with-compile-time-evals/flatten (quote-syntax form)))) (define (#%top-interaction* forms) (for/last ([form (in-list forms)]) (syntax-parse form #:literal-sets [kernel-literals] [(define-syntaxes . _) (void)] [_ (eval-syntax form)]))) …but I’m not sure if that’s a recommended approach or not!