我想对自定义语言生成的字符串执行某些操作,例如显示它们。我创建了一个模块 - 开始这样的事情:
(define-syntax (module-begin stx)
(syntax-case stx ()
[(_ EXPR ...)
#'(display (apply string-append (filter string? (list EXPR ...))))]))
然而,这阻止我在语言中使用define。我得到错误"定义:表达式上下文中不允许"。
如何在不失去使用define和其他顶级表达式的能力的情况下抓取字符串?我是否需要预先获取所有定义并将其移至开头?
答案 0 :(得分:3)
使用make-wrapping-module-begin
为您完成艰苦的工作。
(require syntax/wrap-modbeg)
(define-syntax module-begin (make-wrapping-module-begin #'wrap-expression))
(define-syntax (wrap-expression stx)
(syntax-case stx ()
[(_ expr) #'(println expr)]))
更改wrap-expression
以使用表达式执行任何操作。它不适用于定义,require
形式等。请注意,您一次获得一个模块体表达式,而不是一次获取所有模块体表达式。
您无权注册模块级定义,解释require
表单等。只有宏扩展器和原始#%plain-module-begin
表单可以执行此操作。因此,您的module-begin
宏必须与他们合作。
您的宏必须使用local-expand
来部分展开每个模块级表单,以便您可以区分以下内容:
require
和provide
表单begin
序列,需要拼接到模块主体当您获得定义或require
或provide
表单时,您只需将其投放到真实的 #%plain-module-begin
原语。你处理的表达;再一次,不过你喜欢。对于begin
表单,您可以重复使用子表单。代码看起来像这样:
(define-syntax (module-begin stx)
(syntax-case stx ()
[(_ form ...)
#'(#%plain-module-begin (wrap-module-form form) ...)]))
(define-syntax (wrap-module-form stx)
(syntax-case stx ()
[(_ form)
(let ([e-form (local-expand #'form 'module #f)])
(syntax-case e-form (begin define-syntaxes define-values #%require #%provide)
[(define-syntaxes . _)
e-form]
[(define-values . _)
e-form]
[(#%require . _)
e-form]
[(#%provide . _)
e-form]
[(begin inner-form ...)
#'(begin (wrap-module-form inner-form) ...)]
[expr
#'(wrap-expression expr)]))]))
(define-syntax (wrap-expression stx)
(syntax-case stx ()
[(_ expr) #'(println expr)]))
所有新代码基本上都是make-wrapping-module-begin
自动为您做的事情。