简体   繁体   English

使用Racket进行语言扩展,通过宏定义辅助函数

[英]Language extension using Racket, defining helper functions via macros

I've been stuck with an issue for a number of hours now. 我现在已经坚持了几个小时的问题。 I'm trying to define a DSL using Racket's language extension features. 我正在尝试使用Racket的语言扩展功能来定义DSL。 I want to do something like the following pseudo-code. 我想做类似下面的伪代码。 Ultimately I'd like to generate functions and macros given the input in the DSL, and most of that seems to work now, the problem is providing definitions which should work at the same level as the declarations. 最后,我想在DSL中输入生成函数和宏,并且大多数现在似乎都可以工作,问题是提供的定义应该与声明处于同一级别。 Is this even possible? 这甚至可能吗? It's late, and I'm sure I'm missing something really trivial. 现在已经晚了,我肯定我错过了一些非常微不足道的东西。 The most basic example of the problem is this: 问题的最基本的例子是:

tinylang.rkt: tinylang.rkt:

#lang racket

; here we redefine module begin.
(provide (all-defined-out)
         (except-out (all-from-out racket) #%module-begin)
         (rename-out [module-begin #%module-begin])
         )

(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ stmts ...)
     #`(#%module-begin
       (define (hello) (print "Yes!") (newline))
       ; (provide (for-syntax hello))
       (print "Function defined.")
       stmts ...   )]))

Now I try to use this new language elsewhere: 现在我尝试在其他地方使用这种新语言:

try.rkt: try.rkt:

#lang s-exp "tinylang.rkt"
(hello)

But I get the error "hello: unbound identifier in module in: hello", when loading the second module. 但是在加载第二个模块时,我收到错误“hello:模块中的未绑定标识符:hello”。

The problem is that hello is defined in the lexical scope of tinylang.rkt but you want it to be in scope in try.rkt . 问题是hello是在tinylang.rkt的词法范围内定义的,但是你希望它在try.rkt范围内。 You can use datum->syntax to set the lexical context of a piece of syntax. 您可以使用datum->syntax来设置一段语法的词法上下文。

This will fix the problem: 这将解决问题:

#lang racket

; here we redefine module begin.
(provide (all-defined-out)
         (except-out (all-from-out racket) #%module-begin)
         (rename-out [module-begin #%module-begin])
         )

(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ stmts ...)
     #`(#%module-begin
       #,(datum->syntax 
          stx
          (syntax->datum 
           #'(define (hello) (print "Yes!") (newline))))
       (print "Function defined.")
       stmts ...   )]))

UPDATE: 更新:

In response to comments, the previous solution could be simplified to: 在回应评论时,先前的解决方案可以简化为:

(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ stmts ...)
     (with-syntax ([hello-fn (datum->syntax stx 'hello)])
       #`(#%module-begin
          (define (hello-fn) (print "Yes!") (newline))
          (print "Function defined.")
          stmts ...   ))]))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM