首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >球拍中的模块元语言

球拍中的模块元语言
EN

Stack Overflow用户
提问于 2016-06-16 19:29:20
回答 1查看 460关注 0票数 8

我试图用Racket编写一个模块元语言mylang,它接受将修改的主体传递给的第二种语言,这样:

代码语言:javascript
复制
(module foo mylang typed/racket body)

相当于:

代码语言:javascript
复制
(module foo typed/racket transformed-body)

当然,可以用任何其他模块语言替换typed/racket部件。

我尝试了一个简单的版本,使身体保持不变。它可以很好地运行在命令行上,但是在DrRacket中运行时会出现以下错误:

代码语言:javascript
复制
/usr/share/racket/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:479:30: require: namespace mismatch;
 reference to a module that is not available
  reference phase: 1
  referenced module: "/usr/share/racket/pkgs/typed-racket-lib/typed-racket/env/env-req.rkt"
  referenced phase level: 0 in: add-mod!

以下是整个代码:

代码语言:javascript
复制
#lang racket

(module mylang racket
  (provide (rename-out [-#%module-begin #%module-begin]))
  (require (for-syntax syntax/strip-context))
  (define-syntax (-#%module-begin stx)
    (syntax-case stx ()
      [(_ lng . rest)
       (let ([lng-sym (syntax-e #'lng)])
         (namespace-require `(for-meta -1 ,lng-sym))
         (with-syntax ([mb (namespace-symbol->identifier '#%module-begin)])
           #`(mb . #,(replace-context #'mb #'rest))))])))

(module foo (submod ".." mylang) typed/racket/base
  (ann (+ 1) Number))

(require 'foo)

需求(即我宁愿避免的解决方案):

  • (require (only-in typed/racket))模块中添加一个mylang可以完成这项工作,但我对一个通用解决方案很感兴趣,在这个解决方案中,mylang不需要了解al上的typed/racket (也就是说,如果有人添加了一个新的语言foo,那么mylang就应该开箱即用)。
  • 另外,我对声明子模块并立即声明require和re-provide it,就像这里所做的的技巧不感兴趣,因为这会改变到实际模块的路径(例如,maintest就失去了它们的特殊行为)。 它在编译时也比较慢,因为子模块获得探视和/或实例化的次数更多(通过编写(begin-for-syntax (displayln 'here))可以看出这一点,并对大型typed/racket程序产生了明显的影响。
  • 如果DrRacket中的箭头适用于委托语言提供的内置箭头,例如,在上面的示例中,有从ann+Numbertyped/racket/base的箭头,则额外积分。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-25 19:15:46

您可以做的一件事,我认为这不违反您的要求,就是把它放在一个模块中,充分展开该模块,然后匹配到#%plain-module-begin来插入一个需求。

代码语言:javascript
复制
#lang racket

(module mylang racket
  (provide (rename-out [-#%module-begin #%module-begin]))
  (define-syntax (-#%module-begin stx)
    (syntax-case stx ()
      [(_ lng . rest)
       (with-syntax ([#%module-begin (datum->syntax #f '#%module-begin)])
         ;; put the code in a module form, and fully expand that module
         (define mod-stx
           (local-expand
            #'(module ignored lng (#%module-begin . rest))
            'top-level
            (list)))
         ;; pattern-match on the #%plain-module-begin form to insert a require
         (syntax-case mod-stx (module #%plain-module-begin)
           [(module _ lng (#%plain-module-begin . mod-body))
            #'(#%plain-module-begin
                (#%require lng)
                .
                mod-body)]))])))

;; Yay the check syntax arrows work!
(module foo (submod ".." mylang) typed/racket/base
  (ann (+ 1) Number))

(require 'foo)

如果你想以某种方式改变身体,你可以在膨胀之前或之后这样做。

插入额外(#%require lng)的模式匹配是必要的,因为在lng可用的上下文中扩展模块主体是不够的。将mod-body代码从module表单中删除意味着绑定将引用lng,但lng在运行时将不可用。这就是为什么我在没有它的情况下得到require: namespace mismatch; reference to a module that is not available错误的原因,这也是为什么需要在扩展后添加它。

从评论中更新

然而,正如@GeorgesDupéron在评论中指出的那样,这带来了另一个问题。如果lng提供了一个标识符x,并且使用它的模块导入了一个不同的x,那么就会出现一个不应该存在的导入冲突。要求行应该在模块语言的“嵌套作用域”中,这样它们就可以在这里隐藏像x这样的标识符。

@GeorgesDupéron在这个网球拍用户列表上的电子邮件中找到了解决这个问题的方法,使用mod-body上的(make-syntax-introducer)生成嵌套范围。

代码语言:javascript
复制
(module mylang racket
  (provide (rename-out [-#%module-begin #%module-begin]))
  (define-syntax (-#%module-begin stx)
    (syntax-case stx ()
      [(_ lng . rest)
       (with-syntax ([#%module-begin (datum->syntax #f '#%module-begin)])
         ;; put the code in a module form, and fully expand that module
         (define mod-stx
           (local-expand
            #'(module ignored lng (#%module-begin . rest))
            'top-level
            (list)))
         ;; pattern-match on the #%plain-module-begin form to insert a require
         (syntax-case mod-stx (module #%plain-module-begin)
           [(module _ lng (#%plain-module-begin . mod-body))
            #`(#%plain-module-begin
                (#%require lng)
                .
                #,((make-syntax-introducer) #'mod-body))]))])))
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37867859

复制
相关文章

相似问题

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