首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何像#lang那样使用自定义读取器?

如何像#lang那样使用自定义读取器?
EN

Stack Overflow用户
提问于 2020-01-22 08:44:54
回答 2查看 70关注 0票数 3

我试图在给定的字符串(而不是文件中)上执行一个定制的#lang。我们叫它broccoli吧。

设置

我的朗是这样定义的:

西兰花/主要

代码语言:javascript
复制
(module reader racket/base
  (require broccoli/private/reader)
  (provide read read-syntax)) ; basically a reprovide

西兰花/私人/读取器

代码语言:javascript
复制
(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))))

西兰花/私人/膨化。

代码语言:javascript
复制
(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

它很好地使用了经典的方法:

代码语言:javascript
复制
#lang broccoli
Hello world!

将产生:

代码语言:javascript
复制
(module program broccoli/private/expander
  (program
    (sentence (word "Hello") (word "world"))))

然后扩展到:

代码语言:javascript
复制
(provide meal)
(define meal (list 42 38)) ; the result is for the sake of the example, don't mind it

但我试图将其应用于从网络请求中获得的任意字符串,并将结果发回。这一次,事情变得更复杂了。以下是我尝试过的:

尝试#1

代码语言:javascript
复制
(define text "Hello world!")
(define evaluator (make-evaluator 'broccoli text)) ; Error: no #%module-begin found
(evaluator 'meal)

尝试#2

代码语言:javascript
复制
(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

代码语言:javascript
复制
(define text "Hello world!")
(define evaluator (make-module-evaluator (string-append "#lang broccoli " text)))
(evaluator 'meal) ; Error: meal undefined

尝试#4 (它有效,但不是我想要的)

代码语言:javascript
复制
(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

我肯定有更好的办法,但我不明白出了什么问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-22 15:22:26

我差点就到了!

我必须在评估器中要求生成模块(这意味着从扩展程序中提供#%app#%top#%top-interactionrequirequote )。

代码语言:javascript
复制
(define evaluator (make-module-evaluator (string-append "#lang broccoli\n" text)))
(evaluator '(require 'program)) ; missing step
(evaluator 'meal)

在这个解决方案中,我发现奇怪的是,它的行为与文档中说的不一样:

代码语言:javascript
复制
> (define base-module-eval
    (make-module-evaluator '(module m racket/base
                              (define (f) later)
                              (define later 5))))
> (base-module-eval 'later)
5
票数 2
EN

Stack Overflow用户

发布于 2020-01-22 14:13:54

我建议使用read-lang-module将字符串转换为表示模块的语法对象。然后使用make-module-evaluator

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59855704

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档