为新语言导入 Beautiful Racket reader?
Importing Beautiful Racket reader for new language?
我正在使用 Beautiful Racket to draft a new DSL, bleir
, based on s-expressions. I first install a new racket package using the Master Recipe。
raco pkg new bleir
cd bleir
raco pkg install
然后我在 madatory 文件中设置了一个残留的 reader 和扩展器,main.rkt
:
#lang br/quicklang
(module+ reader
(provide read-syntax)
(require br/quicklang))
(provide (rename-out [bleir-expander #%module-begin]))
(define-macro (bleir-expander PARSE-TREE)
#'(#%module-begin
(display PARSE-TREE)))
然后我写了一个测试文件,tyst-bleir.rkt
[故意拼写错误,以回避字符串名称“test”的潜在问题]:
#lang bleir
42
我遇到问题:
Module Language: only a module expression is allowed, either
#lang <language-name>
or
(module <name> <language> ...)
in: 42
我可以用两种方式修复它,“恶心”和“神秘”。首先,令人作呕的修复,在 tyst-bleir.rkt
:
(module tyst-bleir bleir
42)
这有效,从 br/quicklang
和我的自定义扩展器调用双重导出的 reader,显示 42
。
问题 1:#lang bleir
语法应该 与冗长的 (module ...)
语法相同它不是?为什么 #lang bleir
无法从 br/quicklang
导入 reader?
现在,神秘的修复:
#lang s-exp bleir
42
这显然使用了模块(包?)s-exp
中的替代 s-exp reader,我猜没问题。至少我没有被屏蔽。但是,我不明白为什么我不能以相同的方式使用 br/quicklang
中的 reader。
#lang br/quicklang bleir
42
bleir: unbound identifier in: bleir
问题 2:为什么这不起作用?我可以修好吗?如果是,怎么做?
这是另一个失败的尝试,从另一个方向尝试从 s-exp
导入 main-rkt
中的 reader:
(module+ reader
(provide read-syntax)
(require s-exp))
main.rkt:11:11: cannot open module file
module path: s-exp
path: /usr/share/racket/collects/s-exp/main.rkt
system error: no such file or directory; rkt_err=3 in: s-exp
no package suggestions are available .
问题 3: 为什么这不起作用?我可以修好吗?如果是,怎么做?
问题 1
您没有完全按照您参考的主配方进行操作。如果您继续阅读,您将看到:
read-syntax must return one value: code for a module expression, represented as a syntax object. Typically, the converted S-expressions from the source file are inserted into this syntax object. This syntax object must have no identifier bindings. This module code must include a reference to the expander that will provide the initial set of bindings when the module code is evaluated. In pseudocode:
#lang br
(module reader br
(provide read-syntax)
(define (read-syntax name port)
(define s-exprs (read-code-from port))
(strip-bindings
#`(module dsl-mod-name dsl/expander
#,@s-exprs))))
换句话说,您的 read-syntax
需要 return (strip-bindings #'(module ...))
。
问题 2
我认为您混淆了“用户使用的语言”和“语言设计者使用的语言”。
“用户使用的语言”类似于 #lang bleir
、#lang slideshow
、#lang pollen
等。这些语言提供了执行特定领域任务的结构。例如,#lang slideshow
是一种用于创建演示文稿的语言。 #lang pollen
是一种用于创建书籍的语言。
“语言设计者使用的语言”是一种“用户使用的语言”,这里的用户就是语言设计者。这些语言提供了使语言创建更容易的结构。 #lang br/quicklang
属于此类。
因此,作为语言设计者,您会在 bleir/main.rkt
内部使用 #lang br/quicklang
来构建语言 bleir
。但是您的用户不是语言设计者,不需要编写(甚至不需要知道)#lang br/quicklang
.
主配方谈到了两件事:reader 和扩展器。在完全开发的语言中,您将同时提供 reader 和扩展器。 s-exp
可以看作是“运行”非完全开发的语言的方便 hack 语言,这些语言只有扩展器,但还没有 reader。
所以,#lang s-exp bleir
工作的原因是你有一个功能扩展器,所以 #lang s-exp bleir
使用你的扩展器但完全忽略你的 reader
子模块。 #lang bleir
不起作用的原因是您的 reader
子模块有问题(请参阅问题 1)。 #lang br/quicklang bleir
不起作用的原因是用户写 #lang br/quicklang
.
没有任何意义
我建议您忘记 s-exp
并修复您的 reader。 AFAIK,Beautiful Racket 并没有真正谈论 s-exp
,如果您正在阅读本书,使用 s-exp
只会让您感到困惑。
问题 3
如果您需要技术解答,https://docs.racket-lang.org/guide/hash-lang_syntax.html (or more generally https://docs.racket-lang.org/reference/reader.html#%28part._parse-reader%29) 回答您的问题:
Unlike racket, s-exp cannot be used as a module path with require. Although the syntax of language for #lang overlaps with the syntax of module paths, a language is not used directly as a module path. Instead, a language obtains a module path by trying two locations: first, it looks for a reader submodule of the main module for language. If this is not a valid module path, then language is suffixed with /lang/reader. (If neither is a valid module path, an error is raised.) The resulting module supplies read and read-syntax functions using a protocol that is similar to the one for #reader.
我正在使用 Beautiful Racket to draft a new DSL, bleir
, based on s-expressions. I first install a new racket package using the Master Recipe。
raco pkg new bleir
cd bleir
raco pkg install
然后我在 madatory 文件中设置了一个残留的 reader 和扩展器,main.rkt
:
#lang br/quicklang
(module+ reader
(provide read-syntax)
(require br/quicklang))
(provide (rename-out [bleir-expander #%module-begin]))
(define-macro (bleir-expander PARSE-TREE)
#'(#%module-begin
(display PARSE-TREE)))
然后我写了一个测试文件,tyst-bleir.rkt
[故意拼写错误,以回避字符串名称“test”的潜在问题]:
#lang bleir
42
我遇到问题:
Module Language: only a module expression is allowed, either #lang <language-name> or (module <name> <language> ...) in: 42
我可以用两种方式修复它,“恶心”和“神秘”。首先,令人作呕的修复,在 tyst-bleir.rkt
:
(module tyst-bleir bleir
42)
这有效,从 br/quicklang
和我的自定义扩展器调用双重导出的 reader,显示 42
。
问题 1:#lang bleir
语法应该 与冗长的 (module ...)
语法相同它不是?为什么 #lang bleir
无法从 br/quicklang
导入 reader?
现在,神秘的修复:
#lang s-exp bleir
42
这显然使用了模块(包?)s-exp
中的替代 s-exp reader,我猜没问题。至少我没有被屏蔽。但是,我不明白为什么我不能以相同的方式使用 br/quicklang
中的 reader。
#lang br/quicklang bleir
42
bleir: unbound identifier in: bleir
问题 2:为什么这不起作用?我可以修好吗?如果是,怎么做?
这是另一个失败的尝试,从另一个方向尝试从 s-exp
导入 main-rkt
中的 reader:
(module+ reader
(provide read-syntax)
(require s-exp))
main.rkt:11:11: cannot open module file module path: s-exp path: /usr/share/racket/collects/s-exp/main.rkt system error: no such file or directory; rkt_err=3 in: s-exp no package suggestions are available .
问题 3: 为什么这不起作用?我可以修好吗?如果是,怎么做?
问题 1
您没有完全按照您参考的主配方进行操作。如果您继续阅读,您将看到:
read-syntax must return one value: code for a module expression, represented as a syntax object. Typically, the converted S-expressions from the source file are inserted into this syntax object. This syntax object must have no identifier bindings. This module code must include a reference to the expander that will provide the initial set of bindings when the module code is evaluated. In pseudocode:
#lang br
(module reader br
(provide read-syntax)
(define (read-syntax name port)
(define s-exprs (read-code-from port))
(strip-bindings
#`(module dsl-mod-name dsl/expander
#,@s-exprs))))
换句话说,您的 read-syntax
需要 return (strip-bindings #'(module ...))
。
问题 2
我认为您混淆了“用户使用的语言”和“语言设计者使用的语言”。
“用户使用的语言”类似于 #lang bleir
、#lang slideshow
、#lang pollen
等。这些语言提供了执行特定领域任务的结构。例如,#lang slideshow
是一种用于创建演示文稿的语言。 #lang pollen
是一种用于创建书籍的语言。
“语言设计者使用的语言”是一种“用户使用的语言”,这里的用户就是语言设计者。这些语言提供了使语言创建更容易的结构。 #lang br/quicklang
属于此类。
因此,作为语言设计者,您会在 bleir/main.rkt
内部使用 #lang br/quicklang
来构建语言 bleir
。但是您的用户不是语言设计者,不需要编写(甚至不需要知道)#lang br/quicklang
.
主配方谈到了两件事:reader 和扩展器。在完全开发的语言中,您将同时提供 reader 和扩展器。 s-exp
可以看作是“运行”非完全开发的语言的方便 hack 语言,这些语言只有扩展器,但还没有 reader。
所以,#lang s-exp bleir
工作的原因是你有一个功能扩展器,所以 #lang s-exp bleir
使用你的扩展器但完全忽略你的 reader
子模块。 #lang bleir
不起作用的原因是您的 reader
子模块有问题(请参阅问题 1)。 #lang br/quicklang bleir
不起作用的原因是用户写 #lang br/quicklang
.
我建议您忘记 s-exp
并修复您的 reader。 AFAIK,Beautiful Racket 并没有真正谈论 s-exp
,如果您正在阅读本书,使用 s-exp
只会让您感到困惑。
问题 3
如果您需要技术解答,https://docs.racket-lang.org/guide/hash-lang_syntax.html (or more generally https://docs.racket-lang.org/reference/reader.html#%28part._parse-reader%29) 回答您的问题:
Unlike racket, s-exp cannot be used as a module path with require. Although the syntax of language for #lang overlaps with the syntax of module paths, a language is not used directly as a module path. Instead, a language obtains a module path by trying two locations: first, it looks for a reader submodule of the main module for language. If this is not a valid module path, then language is suffixed with /lang/reader. (If neither is a valid module path, an error is raised.) The resulting module supplies read and read-syntax functions using a protocol that is similar to the one for #reader.