Я пытаюсь выполнить пользовательский #lang для заданной строки (не в файле). Давайте назовем это broccoli
.
Настройка
Мой язык определяется следующим образом:
broccoli / main.rkt
(module reader racket/base
(require broccoli/private/reader)
(provide read read-syntax)) ; basically a reprovide
брокколи / личное /reader.rkt
(provide
(rename-out
[my-read read]
[my-read-syntax read-syntax]))
(define (my-read in)
(syntax->datum
(my-read-syntax #f in)))
(define (my-read-syntax src in)
(with-syntax ([parse-tree (parse src (make-tokenizer in src))]) ; brag stuff
(strip-context
#'(module program broccoli/private/expander
parse-tree))))
брокколи / частный / expander.rkt
(provide
(rename-out [module-begin #%module-begin]))
(define-syntax-rule (module-begin expr)
(#%module-begin
(provide meal)
(define meal (transform 'expr)))) ; some kind of computation
Работает довольно хорошо, если использовать класс c:
#lang broccoli
Hello world!
выдаст:
(module program broccoli/private/expander
(program
(sentence (word "Hello") (word "world"))))
, который затем расширится до:
(provide meal)
(define meal (list 42 38)) ; the result is for the sake of the example, don't mind it
Но я пытаюсь применить его к произвольной строке, полученной из сетевого запроса, и отправить обратно результат. И на этот раз все становится сложнее. Вот что я попробовал:
Попробуйте # 1
(define text "Hello world!")
(define evaluator (make-evaluator 'broccoli text)) ; Error: no #%module-begin found
(evaluator 'meal)
Попробуйте # 2
(define text "Hello world!")
(define module (broccoli-read-syntax #f (open-input-string text)))
(define evaluator (make-module-evaluator #:language 'broccoli/private/expander module))
(evaluator 'meal) ; Error: meal undefined
Попробуйте # 3
(define text "Hello world!")
(define evaluator (make-module-evaluator (string-append "#lang broccoli " text)))
(evaluator 'meal) ; Error: meal undefined
Попробуйте # 4 (это работает, но это не то, что я хочу)
(define text "Hello world!")
(define module (broccoli-read-syntax #f (open-input-string text)))
(define ns (make-base-namespace))
(eval module ns)
(namespace-require ''program ns)
(define result (eval 'meal ns))
Этот последний результат работает правильно, но он не использует песочницу и использует eval
напрямую.
Я уверен, что есть лучше, но я не понимаю, что происходит не так.