我试图在给定的字符串(而不是文件中)上执行一个定制的#lang。我们叫它broccoli吧。
设置
我的朗是这样定义的:
西兰花/主要
(module reader racket/base
(require broccoli/private/reader)
(provide read read-syntax)) ; basically a reprovide西兰花/私人/读取器
(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))))西兰花/私人/膨化。
(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它很好地使用了经典的方法:
#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。
我肯定有更好的办法,但我不明白出了什么问题。
发布于 2020-01-22 15:22:26
我差点就到了!
我必须在评估器中要求生成模块(这意味着从扩展程序中提供#%app、#%top、#%top-interaction、require和quote )。
(define evaluator (make-module-evaluator (string-append "#lang broccoli\n" text)))
(evaluator '(require 'program)) ; missing step
(evaluator 'meal)在这个解决方案中,我发现奇怪的是,它的行为与文档中说的不一样:
> (define base-module-eval
(make-module-evaluator '(module m racket/base
(define (f) later)
(define later 5))))
> (base-module-eval 'later)
5发布于 2020-01-22 14:13:54
我建议使用read-lang-module将字符串转换为表示模块的语法对象。然后使用make-module-evaluator。
https://stackoverflow.com/questions/59855704
复制相似问题