sorawee
2020-3-3 09:56:17

Is there a way to reliably convert a syntax object in a macro to runtime syntax object?

I’ve been using #'#', but I found today that this doesn’t work when the syntax object contains an ellipsis.


ryanc
2020-3-3 10:23:09

Use quote-syntax. Always use quote-syntax when you have a syntax constant instead of a syntax template that you want to interpret. (The issue you discovered is fundamentally the same as SQL injection, markup injection, etc, just in a different context.)


deactivateduser60718
2020-3-3 20:46:35

I’m trying to apply my own semantics to a Scribble reader using read-syntax-inside. This example complains that #%datum is not bound when running (run-at-expr (open-input-string "\n")), which makes sense. I thought I would be able to fix it with an (eval '(require (for-syntax racket/base)) ns) or an equivalent namespace-require, but it still fails with the same error. How am I supposed to ensure #%datum and company are available in ns below?

#lang racket (require scribble/reader) (define (run-at-expr in) (define ns (make-base-namespace)) (define (port->sequence) (in-list (syntax-e (read-syntax-inside (object-name in) in)))) (for/foldr ([acc '()]) ([expr (port->sequence)]) (printf "Eval: ~v~n" expr) (define result (eval-syntax expr ns)) (unless (void? result) (cons result acc))))


soegaard2
2020-3-3 21:09:50

Replacing eval-syntax with eval fixes the example. It may or may not be what you want.


soegaard2
2020-3-3 21:20:55

@deactivateduser60718 Maybe it is namespace-syntax-introduce you are looking for? (define (run-at-expr in) (define ns (make-base-namespace)) (define (port->sequence) (parameterize ([current-namespace ns]) (in-list (syntax-e (namespace-syntax-introduce (read-syntax-inside (object-name in) in)))))) (for/foldr ([acc '()]) ([expr (port->sequence)]) (printf "Eval: ~v~n" expr) (define result (eval-syntax expr ns)) (unless (void? result) (cons result acc))))


sorawee
2020-3-4 02:22:18

Thanks! That works perfectly. I have a follow-up question. Will this have a problem once the code is bytecode-compiled (e.g., losing source location information)? I am told to look into transform-template which is supposed to be a better way to handle things, but after reading the documentation and seeing some examples, I still don’t understand what it does, what problem it can solve, etc.